实验要求
将一个简单的C程序汇编成LoongArch或RISC-V汇编代码,并逐步分析程序的执行过程,深入理解存储程序计算机和函数调用堆栈框架在执行过程中所起的作用。
编写待测试代码
// lab1.c
int sum(int a, int b) {
return a + b;
}
int main() {
int a = 8;
int b = 9;
return sum(a, b);
}
准备交叉编译环境
如果选择的ISA不是x86, 还需要准备相应的gcc和binutils, 才能正确地进行编译。
riscv32(64):
apt-get install g++-riscv64-linux-gnu binutils-riscv64-linux-gnu
执行命令 riscv64-linux-gnu-gcc -S lab1.c -o test.S
得到汇编文件。
汇编代码分析
.file "lab1.c" # lab1.c 文件名
.option pic # 生成位置无关代码
.text # 下面的代码都是程序的代码段
.align 1 # 对齐到2的1次方个字节
.globl sum # sum函数是全局的
.type sum, @function # sum函数的类型是函数
sum: # sum函数的入口
addi sp,sp,-32 # 为sum函数的局部变量分配32个字节的栈空间
sd s0,24(sp) # 将s0寄存器的值存储到栈顶+24字节的位置上,保存s0的值
addi s0,sp,32 # 将sp+32的值赋值给s0,s0指向sum函数的栈帧
mv a5,a0 # 将第一个参数值a0复制到a5寄存器
mv a4,a1 # 将第二个参数值a1复制到a4寄存器
sw a5,-20(s0) # 将a5寄存器的值存储到栈顶-20字节的位置上,保存第一个参数
mv a5,a4 # 将a4寄存器的值复制到a5寄存器
sw a5,-24(s0) # 将a5寄存器的值存储到栈顶-24字节的位置上,保存第二个参数
lw a4,-20(s0) # 将栈顶-20字节的值加载到a4寄存器
lw a5,-24(s0) # 将栈顶-24字节的值加载到a5寄存器
addw a5,a4,a5 # 将a4和a5寄存器的值相加,结果存储到a5寄存器
sext.w a5,a5 # 将a5寄存器的值扩展为64位
mv a0,a5 # 将a5寄存器的值存储到a0寄存器中,作为函数的返回值
ld s0,24(sp) # 将栈顶+24字节位置上的值存储到s0寄存器中,恢复s0的值
addi sp,sp,32 # 释放32字节的栈空间,将sp指针向上移动
jr ra # 跳转到ra寄存器的地址执行,返回调用者
.size sum, .-sum # 设置sum函数的大小
.align 1
.globl main # main函数可全局调用
.type main, @function # main是一个函数
main:
addi sp,sp,-32 # 将栈指针向下移动32个字节,为本地变量和保存寄存器做准备
sd ra,24(sp) # 将ra寄存器的值存储到栈顶+24字节的位置上,保存ra的值
sd s0,16(sp) # 将s0寄存器的值存储到栈顶+16字节的位置上,保存s0的值
addi s0,sp,32 # 将sp+32的值赋值给s0,s0指向main函数的栈帧
li a5,8 # 将8赋值给a5寄存器
sw a5,-24(s0) # 将a5寄存器的值存储到栈顶-24字节的位置上,保存第二个参数
li a5,9 # 将9赋值给a5寄存器
sw a5,-20(s0) # 将a5寄存器的值存储到栈顶-20字节的位置上,保存第一个参数
lw a4,-20(s0) # 将栈顶-20字节的值加载到a4寄存器
lw a5,-24(s0) # 将栈顶-24字节的值加载到a5寄存器
mv a1,a4 # 将a4寄存器的值存储到a1寄存器中,作为第二个参数
mv a0,a5 # 将a5寄存器的值存储到a0寄存器中,作为第一个参数
call sum # 调用sum函数
mv a5,a0 # 将a0寄存器的值存储到a5寄存器中
mv a0,a5 # 将a5寄存器的值存储到a0寄存器中,作为函数的返回值
ld ra,24(sp) # 将栈顶+24字节位置上的值存储到ra寄存器中,恢复ra的值
ld s0,16(sp) # 将栈顶+16字节位置上的值存储到s0寄存器中,恢复s0的值
addi sp,sp,32 # 释放32字节的栈空间,将sp指针向上移动
jr ra # 跳转到ra寄存器的地址执行,返回调用者
.size main, .-main
.ident "GCC: (Ubuntu 9.4.0-1ubuntu1~20.04) 9.4.0"
.section .note.GNU-stack,"",@progbits