571
社区成员
发帖
与我相关
我的任务
分享实验要求
将一个简单的C程序汇编成LoongArch或RISC-V汇编代码,并逐步分析程序的执行过程,深入理解存储程序计算机和函数调用堆栈框架在执行过程中所起的作用。
安装编译环境
sudo apt install autoconf automake autotools-dev curl python3 libmpc-dev libmpfr-dev libgmp-dev gawk build-essential bison flex texinfo gperf libtool patchutils bc zlib1g-dev libexpat-dev git libncurses5-dev
安装RISC-V
git clone https://github.com/riscv-collab/riscv-gnu-toolchain
cd riscv-gnu-toolchain/
./configure --prefix=/opt/riscv --with-arch=rv64imafdc
sudo make linux -j$(nproc)
export PATH=/opt/riscv/bin:/opt/qemu/bin:$PATH
测试
riscv64-unknown-linux-gnu-gcc -v
使用vim编写test.c文件
int g(int x) {
return x+3;
}
int f(int x) {
return g(x);
}
int main() {
return f(8) + 1;
}
使用命令编译成汇编代码
riscv64-unknown-linux-gnu-gcc -S test.c -o test.s
汇编代码分析
.file "test.c"
.option nopic
.attribute arch, "rv64i2p0_m2p0_a2p0_f2p0_d2p0_c2p0"
.attribute unaligned_access, 0
.attribute stack_align, 16
.text
.align 1 #对齐
.globl g #声明g为全局符号
.type g, @function #将g定义为一个函数
g:
addi sp,sp,-32 #修改栈指针sp=sp-32,push
sd s0,24(sp) #把s0保存到sp+24,s0表示帧指针fp
addi s0,sp,32 #栈底保存到s0,s0=sp+32
mv a5,a0 #将a0存放的参数值存入a5
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 #将a5标记为扩展字
mv a0,a5 #将a5的值返回a0
ld s0,24(sp) #恢复s0
addi sp,sp,32 #恢复sp
jr ra #跳转到ra地址返回
.size g, .-g
.align 1 #对齐
.globl f #声明f为全局符号
.type f, @function #将f定义为一个函数
f:
addi sp,sp,-32 #修改栈指针sp=sp-32,push
sd ra,24(sp) #将ra值保存到sp+24
sd s0,16(sp) #将s0值保存到sp+16
addi s0,sp,32 #栈底保存到s0,s0=sp+32
mv a5,a0 #将a0存放的参数值存入a5
sw a5,-20(s0) #将a5中的字保存到s0-20
lw a5,-20(s0) #将s0-20的字存入a5
mv a0,a5 #将a5的值返回a0
call g #调用函数g
mv a5,a0 #将返回来的值a0移入a5中
mv a0,a5 #将a5中的值移入返回值a0中
ld ra,24(sp) #恢复ra
ld s0,16(sp) #恢复s0
addi sp,sp,32 #恢复sp
jr ra #跳转到ra地址返回
.size f, .-f
.align 1 #对齐
.globl main #声明main为全局符号
.type main, @function #将main定义为一个函数
main:
addi sp,sp,-16 #修改栈指针sp=sp-16,push
sd ra,8(sp) #将ra值保存到sp+8
sd s0,0(sp) #将s0值保存到sp+0
addi s0,sp,16 #栈底保存到s0,s0=sp+16
li a0,8 #赋值a0=8
call f #调用函数f
mv a5,a0 #将返回来的值a0移入a5中
addiw a5,a5,1 #a5=a5+1
sext.w a5,a5 #将a5标记为扩展字
mv a0,a5 #将a5的值返回a0
ld ra,8(sp) #恢复ra
ld s0,0(sp) #恢复s0
addi sp,sp,16 #恢复sp
jr ra #跳转到ra地址返回
.size main, .-main
.ident "GCC: () 12.2.0"
.section .note.GNU-stack,"",@progbits