571
社区成员
发帖
与我相关
我的任务
分享•将一个简单的C程序汇编成LoongArch或RISC-V汇编代码,并逐步分析程序的执行过程,深入理解存储程序计算机和函数调用堆栈框架在执行过程中所起的作用。
编写C代码
int g(int x){
return x+3;
}
int f(int x){
return g(x);
}
int main(void)
{
return f(8)+1;
}
生成汇编代码:
riscv64-unknown-linux-gnu-gcc -S -O0 -march=rv32i -mabi=ilp32 test.c
汇编代码分析:
g:
addi sp,sp,-32 //sp = sp - 32, sp为栈顶指针
sd s0,24(sp) //s0的值保存在sp+24的地址中, s0为栈底指针
addi s0,sp,32 //s0 = sp + 32
mv a5,a0 //mv rd, rs = addi rd, rs, 0,即a5=a0
sw a5,-20(s0) //a5的值保存在s0-20的地址中
lw a5,-20(s0) //将s0-20地址中的值保存在a5
addiw a5,a5,3 //a5 = a5 + 3
sext.w a5,a5 //
mv a0,a5 //g函数的返回a5保存在a0中用于返回
ld s0,24(sp) //s0 = sp + 24
addi sp,sp,32 //恢复栈顶指针原值
jr ra //跳转,函数返回
.size g, .-g
.align 1
.globl f
.type f, @function
f:
addi sp,sp,-32 //sp = sp - 32
sd ra,24(sp) //ra的值(返回地址)保存在sp+24的地址中
sd s0,16(sp) //s0的值保存在sp+16的地址中
addi s0,sp,32 //s0 = sp + 32
mv a5,a0 //a5=a0
sw a5,-20(s0) //a5的值存放到s0-20指向的地址中
lw a5,-20(s0) //将s0-20地址中的值存放到a5中
mv a0,a5 //a0 = a5保存调用g函数的待传的参数
call g //调用g函数
mv a5,a0 //a5 = a0
mv a0,a5 //a0 = a5, f函数的返回值保存在a0中
ld ra,24(sp) //ra = sp + 24, 得到返回地址
ld s0,16(sp) //s0 = sp + 16, 将sp+16的值重新存储到s0栈底指针中,指向main函数的栈空间
addi sp,sp,32 //sp = sp + 32, 指向main函数栈空间栈顶
jr ra //函数返回,回到mian函数
.size f, .-f
.align 1
.globl main
.type main, @function
main:
addi sp,sp,-16 //sp = sp - 16
sd ra,8(sp) //ra存放的返回地址值放到sp+8
sd s0,0(sp) //s0为栈底指针,将s0的值存放到sp指向的地址中
addi s0,sp,16 //s0=sp+16,构造main函数的栈空间
li a0,8 //保存函数调用的待传参数8
call f //调用f函数
mv a5,a0 //a5 = a0, f函数返回值保存到a5中
addiw a5,a5,1 //a5 = a5 + 1
sext.w a5,a5
mv a0,a5 //a0 = a5, 保存main函数的返回值
ld ra,8(sp) //得到返回地址
ld s0,0(sp) //恢复栈底指针
addi sp,sp,16 //恢复栈顶指针
jr ra //函数返回