571
社区成员
发帖
与我相关
我的任务
分享将一个简单的C程序汇编成LoongArch或RISC-V汇编代码,并逐步分析程序的执行过程,深入理解存储程序计算机和函数调用堆栈框架在执行过程中所起的作用。
需要先安装RISC-V的交叉编译器,安装步骤如下:
sudo apt-get install gcc-riscv64-linux-gnu
其他工具本虚拟机都安装完毕了,不需要配置了。
源文件如下:
#include<stdio.h>
int sub(int a ,int b){
return a - b;
}
int main(){
int a = 2023;
int b = 2000;
return sub(a,b);
}
反汇编得到的代码和注释解释如下:
.file "test.c" # 源代码文件名
.option pic # 启用位置独立代码选项
.text # 指示接下来是代码段
.align 1 # 按照对齐字节数将地址对齐到 2^1 = 2 个字节边界
.globl sub # sub函数作为全局符号可见
.type sub, @function # 定义sub函数的类型为“函数”
sub:
addi sp,sp,-32 # 分配32字节栈空间
sd s0,24(sp) # 将s0寄存器存储到栈上
addi s0,sp,32 # s0指向栈顶32字节处
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 a5,-20(s0) # 从s0-20处加载a5的值
mv a4,a5 # 将a5的值移动到a4中
lw a5,-24(s0) # 从s0-24处加载a5的值
subw a5,a4,a5 # 计算a4 - a5的值,结果保存到a5中
sext.w a5,a5 # 将a5的值符号扩展为32位,并将结果保存到a5中
mv a0,a5 # 将a5的值移动到a0中,作为函数返回值
ld s0,24(sp) # 将s0寄存器从栈中加载
addi sp,sp,32 # 释放32字节栈空间
jr ra # 跳转到ra寄存器中的地址
.size sub, .-sub # 指定sub函数的大小
.align 1 # 按照对齐字节数将地址对齐到 2^1 = 2 个字节边界
.globl main # main函数作为全局符号可见
.type main, @function # 定义main函数的类型为“函数”
main:
addi sp,sp,-32 # 分配32字节栈空间
sd ra,24(sp) # 保存ra寄存器到栈上
sd s0,16(sp) # 保存s0寄存器到栈上
addi s0,sp,32 # s0指向栈顶
li a5,2023 # 将2023加载到a5寄存器
sw a5,-24(s0) # 将a5寄存器的值存储到栈上相对s0偏移24字节的位置
li a5,2000 # 将2000加载到a5寄存器
sw a5,-20(s0) # 将a5寄存器的值存储到栈上相对s0偏移20字节的位置
lw a4,-20(s0) # 从栈上相对s0偏移20字节的位置加载一个32位值到a4寄存器
lw a5,-24(s0) # 从栈上相对s0偏移24字节的位置加载一个32位值到a5寄存器
mv a1,a4 # 将a4寄存器的值移动到a1寄存器
mv a0,a5 # 将a5寄存器的值移动到a0寄存器
call sub # 调用sub函数
mv a5,a0 # 将返回值从a0寄存器移动到a5寄存器
mv a0,a5 # 将a5寄存器的值移动到a0寄存器
ld ra,24(sp) # 从栈上相对sp偏移24字节的位置加载一个64位值到ra寄存器
ld s0,16(sp) # 从栈上相对sp偏移16字节的位置加载一个64位值到s0寄存器
addi sp,sp,32 # 回收栈空间
jr ra # 跳转到ra寄存器所指向的地址
.size main, .-main # 计算main函数的大小
.ident "GCC: (Ubuntu 11.3.0-1ubuntu1~22.04) 11.3.0"
.section .note.GNU-stack,"",@progbits # 标识该文件不需要执行栈