567
社区成员
发帖
与我相关
我的任务
分享
RISC-V 包含如下寄存器,其中 x0 ~ x31 为32个基础通用寄存器,每个寄存器的作用见下表描述。
其中最重要的寄存器包括:
上表最后一列表明在函数调用时该寄存器中的值由调用者还是被调用者来保存。例如,a0 - a7 由 Caller 来保存,所以在调用之前 Caller 就需要将这些寄存器的值暂存到栈上,以便调用返回时恢复,否则其值可能会被 Callee 修改。
RISC-V 的指令集设计非常的精简,其只包含如下六种基本指令:
具体格式如下所示:
接下来,我们以一个计算最大公约数的 C 程序来分析 RISC-V 汇编代码。
源程序如下:
#include <stdio.h>
int gcd(int a, int b) {
return b ? gcd(b, a%b) : a;
}
int main() {
int a = 12, b = 18;
printf("%d\n", gcd(a,b));
}
通过如下命令编译为 RISC-V 汇编程序:
riscv64-linux-gnu-gcc -S -o test.s test.c
汇编程序及其分析如下(寄存器用$前缀表示):
.file "test.c"
.option pic
.text
.align 1
.globl gcd
.type gcd, @function
gcd:
addi sp,sp,-32 ;栈帧指针下移
sd ra,24(sp) ;暂存$ra的值到栈上
sd s0,16(sp) ;暂存$s0的值到栈上
addi s0,sp,32 ;s0指向栈底
mv a5,a0 ;$a5 = a
mv a4,a1 ;$a4 = b
sw a5,-20(s0) ;暂存a到栈上
mv a5,a4 ;$a5 = b
sw a5,-24(s0) ;暂存b到栈上
lw a5,-24(s0)
sext.w a5,a5 ;符号扩展
beqz a5,.L2 ;若b为0则跳转到.L2
lw a4,-20(s0) ;$a4 = a
lw a5,-24(s0) ;$a5 = b
remw a5,a4,a5 ;$a5 = a % b
sext.w a4,a5 ;$a4 = a % b
lw a5,-24(s0) ;$a5 = b
mv a1,a4 ;$a1 = a % b
mv a0,a5 ;$a0 = b
call gcd ;递归调用gcd
mv a5,a0 ;$a5 = gcd(b, a%b)
j .L3 ;跳转到.L3
.L2:
lw a5,-20(s0) ;$a5 = a
.L3:
mv a0,a5 ;$a0 = $a5
ld ra,24(sp) ;恢复$ra的值
ld s0,16(sp) ;恢复$s0的值
addi sp,sp,32 ;退栈到旧栈顶
jr ra ;调用返回
.size gcd, .-gcd
.section .rodata
.align 3
.LC0:
.string "%d\n"
.text
.align 1
.globl main
.type main, @function
main:
addi sp,sp,-32
sd ra,24(sp)
sd s0,16(sp)
addi s0,sp,32
li a5,12
sw a5,-24(s0)
li a5,18
sw a5,-20(s0)
lw a4,-20(s0)
lw a5,-24(s0)
mv a1,a4 ;$a1 = 18
mv a0,a5 ;$a0 = 12
call gcd
mv a5,a0
mv a1,a5 ;$a1 = gcd(12,18)
lla a0,.LC0 ;$a0 = "%s\n"
call printf@plt
li a5,0
mv a0,a5
ld ra,24(sp)
ld s0,16(sp)
addi sp,sp,32
jr ra
.size main, .-main
.ident "GCC: (Ubuntu 9.4.0-1ubuntu1~20.04) 9.4.0"
.section .note.GNU-stack,"",@progbits
作者:357