1、函数调用中寄存器规范
2、函数调用规范
(1)函数的前8个参数使用a0-a7寄存器传递,如果传参多于8个,则除前8个参数使用寄存器来传递之外,后面的参数使用栈传递;
(2)如果传递的参数小于寄存器宽度(64位),那么先按符号扩展到32位,再按符号扩展到64位;
(3)如果传递的参数为寄存器宽度的2倍(128位),那么将使用一对寄存器来传递参数;
(4)函数的返回值保存到a0和a1寄存器中;
(5)函数的返回地址保存在ra寄存器中;
(6)如果函数使用s0-s11寄存器,那么子函数在使用前需要把这些寄存器的内容保存到栈中,使用完之后再从栈中恢复内容到这些寄存器里;
(7)栈向下增长(向较低的地址),sp寄存器在进入函数时要对齐到16字节边界上。通过栈传递的第一个参数位于SP寄存器的偏移量0处,后续的参数存储在相应的较高地址处;
(8)如果GCC使用“-fno-omit-frame-pointer”编译选项,那么编译器使用s0作为栈帧指针;
3、C语言源代码
#include <stdio.h>
int main(void)
{
//参数8、9、10要使用栈来传递
printf("data: %d, %d, %d, %d, %d, %d, %d, %d, %d, %d\n", 1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
return 0;
}
将C代码编译成汇编代码的命令:riscv64-linux-gnu-gcc -S test.c -o test.s;
4、分析得到的汇编代码和栈布局
(1)printf函数中,第一个参数是字符串,就是表示格式的那个字符串;
(2)main函数调用printf中,将一些参数保存在了栈空间里,printf函数是可以访问到main函数的栈空间的,依赖sp和s0两个寄存器;