571
社区成员
发帖
与我相关
我的任务
分享将一个简单的C程序汇编成LoongArch或RISC-V汇编代码,并逐步分析程序的执行过程,深入理解存储程序计算机和函数调用堆栈框架在执行过程中所起的作用。
本实验是在linux上进行的,linux系统提供了apt来管理各种安装包,使用它可以很方便的安装我们需要的东西。执行下面的代码,安装risc-v交叉编译器:
sudo apt-get install gcc-riscv64-linux-gnu
本实验使用的c代码如下所示:
#include<stdio.h>
int mul(int a, int b) {
return a * b;
}
int main() {
return mul(3, 5);
}
执行以下命令将c代码编译成rsic-v汇编代码:
riscv64-linux-gnu-gcc -S -o lab1.s lab1.c
得到的汇编代码如下:
# 汇编指示符
.file "lab1.c"
.option pic
.text
.align 1
.globl mul
.type mul, @function
mul:
# 创建mul函数的栈空间
addi sp,sp,-32 # sp = sp - 32, sp指针向低地址移动32字节, sp为栈顶指针
sd s0,24(sp) # 把栈底指针s0的值存储到(sp) + 24的地址中
addi s0,sp,32 # s0 = sp + 32
# 执行mul函数
mv a5,a0 # 把a0寄存器中的值移动到a5寄存器中
mv a4,a1 # 把a1寄存器中的值移动到a1寄存器中
sw a5,-20(s0) # 将a5寄存器中低4个字节存入内存地址s0 - 20中
mv a5,a4 # 把a4寄存器中的值移动到a5寄存器中
sw a5,-24(s0) # 把a5寄存器中低4个字节存入内存地址s0 - 24中
lw a5,-20(s0) # 从地址s0 - 20地址读取4个字节的内容, 写入a5寄存器
mv a4,a5 # 把a5寄存器中的值移动到a4寄存器中
lw a5,-24(s0) # 从地址s0 - 24地址读取4个字节的内容, 写入a5寄存器
mulw a5,a4,a5 # 把寄存器a5和a0中的值相乘, 乘积截止32位, 结果放入a5寄存器中
sext.w a5,a5 # 把a5寄存器中的值进行有符号扩展
mv a0,a5 # 把a5寄存器中的值移动到a0
# 销毁mul函数的栈空间
ld s0,24(sp) # 从sp + 24的地址中读8个字节, 存储到s0中
addi sp,sp,32 # sp = sp + 32
jr ra # 把pc设置为寄存器ra中的值
.size mul, .-mul
.align 1
.globl main
.type main, @function
main:
# 创建main函数的栈空间
addi sp,sp,-16 # sp = sp - 16
sd ra,8(sp) # 把寄存器ra中的值存储到sp + 8的地址中
sd s0,0(sp) # 把栈底指针s0地址中的值存储到sp + 0的地址中
addi s0,sp,16 # s0 = sp + 16
# 执行main函数
li a1,5 # 把5加载到a1寄存器中
li a0,3 # 把3加载到a0寄存器中
call mul # 调用mul函数
mv a5,a0 # 把a0寄存器中的值移动到a5寄存器中
mv a0,a5 # 把a5寄存器中的值移动到a0寄存器中
ld ra,8(sp) # 从sp + 8的地址中读8个字节, 存储到寄存器ra中
ld s0,0(sp) # 从sp + 0的地址中读8个字节, 存储到栈底指针s0指向的地址中
addi sp,sp,16 # sp = sp + 16, 恢复栈空间
jr ra # 把pc设置为寄存器ra中的值
.size main, .-main
.ident "GCC: (Ubuntu 11.3.0-1ubuntu1~22.04) 11.3.0"
.section .note.GNU-stack,"",@progbits
参考资料: