571
社区成员




实验要求:
将一个简单的C程序汇编成x86或x86-64或ARM64或LoongArch或RISC-V汇编代码,并逐步分析程序的执行过程,深入理解存储程序计算机和函数调用堆栈框架在执行过程中所起的作用。参考资料https://gitee.com/mengning997/linuxkernel/tree/master/src/assembly
1. 安装环境
kk@kk:~/Desktop$ sudo apt install gcc-riscv64-linux-gnu
2. C语言源代码
vi test.c
#include<stdio.h>
int add(int a, int b) {
return a + b;
}
int main() {
int num = add(3,4);
return 0;
}
3. 将C语言源代码汇编为RISC-V汇编代码
riscv64-linux-gnu-gcc -S -o test_riscv64.s test.c
.file "test.c" ; 指定源文件名为 "test.c"
.option pic ; 设置编译选项,可能是用于生成位置无关代码的选项
.text ; 进入代码段
.align 1 ; 对齐方式设置为 2^1 = 2 字节对齐
.globl add ; 声明全局函数 add
.type add, @function ; 设置函数 add 的类型为函数
add: ; 定义函数 add 的起始位置
addi sp,sp,-32 ; 分配 32 字节的栈空间
sd s0,24(sp) ; 将 s0 寄存器保存到栈上
addi s0,sp,32 ; 设置 s0 指向栈顶
mv a5,a0 ; 将 a0 寄存器的值复制给 a5
mv a4,a1 ; 将 a1 寄存器的值复制给 a4
sw a5,-20(s0) ; 将 a5 寄存器的值保存到 s0 寄存器指向的地址减去 20 的位置
mv a5,a4 ; 将 a4 寄存器的值复制给 a5
sw a5,-24(s0) ; 将 a5 寄存器的值保存到 s0 寄存器指向的地址减去 24 的位置
lw a4,-20(s0) ; 将 s0 寄存器指向的地址减去 20 的位置的值加载到 a4 寄存器
lw a5,-24(s0) ; 将 s0 寄存器指向的地址减去 24 的位置的值加载到 a5 寄存器
addw a5,a4,a5 ; 将 a4 寄存器和 a5 寄存器的值相加并将结果存入 a5 寄存器
sext.w a5,a5 ; 将 a5 寄存器的低 32 位符号扩展为 64 位
mv a0,a5 ; 将 a5 寄存器的值复制给 a0
ld s0,24(sp) ; 将栈上保存的 s0 寄存器的值恢复到 s0 寄存器
addi sp,sp,32 ; 回收栈空间
jr ra ; 跳转到 ra 寄存器保存的地址,即返回地址,结束函数调用
.size add, .-add ; 设置函数 add 的大小为当前位置减去函数起始位置,即函数大小
.align 1 ; 对齐方式设置为 2^1 = 2 字节对齐
.globl main ; 声明全局函数 main
.type main, @function ; 设置函数 main 的类型为函数
main: ; 定义函数 main 的起始位置
addi sp,sp,-32 ; 分配 32 字节的栈空间
sd ra,24(sp) ; 将 ra 寄存器保存到栈上
sd s0,16(sp) ; 将 s0 寄存器保存到栈上
addi s0,sp,32 ; 设置 s0 指向栈顶
li a1,4 ; 将立即数 4 加载到 a1 寄存器
li a0,3 ; 将立即数 3 加载到 a0 寄存器
call add ; 调用函数 add
mv a5,a0 ; 将函数返回值保存到 a5 寄存器
sw a5,-20(s0) ; 将 a5 寄存器的值保存到 s0 寄存器指向的地址减去 20 的位置
li a5,0 ; 将立即数 0 加载到 a5 寄存器
mv a0,a5 ; 将 a5 寄存器的值复制给 a0
ld ra,24(sp) ; 将栈上保存的 ra 寄存器的值恢复到 ra 寄存器
ld s0,16(sp) ; 将栈上保存的 s0 寄存器的值恢复到 s0 寄存器
addi sp,sp,32 ; 回收栈空间
jr ra ; 跳转到 ra 寄存器保存的地址,即返回地址,结束函数调用
.size main, .-main
.ident "GCC: (Ubuntu 9.4.0-1ubuntu1~20.04) 9.4.0"
.section .note.GNU-stack,"",@progbits