risc-v 有通用寄存器, 也有一些特殊的寄存器(csr)
下表方便查阅吧,一般都是用别名多一些
点评:因为是16字节对齐, 所有sp空间-16,不考虑这个情况, 用不了这么多
c 代码
#include <stdio.h>
void my_function(int a, int b, int c, int d, int e, int f, int g, int h) {
printf("a=%d, b=%d, c=%d, d=%d, e=%d, f=%d, g=%d, h=%d\n", a, b, c, d, e, f, g, h);
}
int main() {
my_function(1, 2, 3, 4, 5, 6, 7, 8);
return 0;
}
编译:riscv64-elf-gcc -S main.c -o main.s
risc-v 代码
.file "main.c"
.option nopic
.text
.align 1
.globl my_function
.type my_function, @function
my_function:
addi sp, sp, -16
sd ra, 8(sp)
sd s0, 0(sp)
addi s0, sp, 16
# 参数传递
mv a0, a0
mv a1, a1
mv a2, a2
mv a3, a3
mv a4, a4
mv a5, a5
mv a6, a6
mv a7, a7
# 函数体
...
ld ra, 8(sp)
ld s0, 0(sp)
addi sp, sp, 16
ret
.size my_function, .-my_function
.globl main
.type main, @function
main:
addi sp, sp, -32
sd ra, 24(sp)
sd s0, 16(sp)
addi s0, sp, 32
# 调用 my_function
li a0, 1
li a1, 2
li a2, 3
li a3, 4
li a4, 5
li a5, 6
li a6, 7
li a7, 8
call my_function
# 函数体
...
ld ra, 24(sp)
ld s0, 16(sp)
addi sp, sp, 32
li a0, 0
ret
.size main, .-main
.ident "GCC: (GNU) 10.2.0"
- 寄存器使用约定
RISC-V 共有32个通用寄存器,每个寄存器都有特定的用途。以下是一些常用寄存器的约定:
x0 (zero):恒为零。
x1 (ra):返回地址寄存器。
x2 (sp):堆栈指针寄存器。
x3 (gp):全局指针寄存器。
x4 (tp):线程指针寄存器。
x5 到 x7 (t0到t2):临时寄存器,不需要在函数调用前保存。
x8 (s0/fp) 和 x9 (s1)、x18-x27 (s2-s11)):保存寄存器,需要在函数调用前保存。
x10 到 x17 (a0到a7):函数参数和返回值寄存器。
x28 到 x31 (t3到t6):临时寄存器,不需要在函数调用前保存。 - 参数传递
前8个整数参数通过寄存器 a0 到 a7 传递。
超过8个参数时,通过栈传递。 - 返回值
函数返回值通过寄存器 a0 和 a1 传递。如果返回值超过两个寄存器的大小,则通过栈传递。 - 栈布局
栈在内存中向低地址方向增长。
函数调用时,栈帧需要对齐到16字节边界。
被调用函数负责保存调用者的 ra、s0 到 s11 等寄存器。
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。