RISC-V ABI 调用约定在线查询
本页是 RISC-V ABI 调用约定在线查询页面,用于快速查看函数调用时参数如何通过 a0-a7 传递、返回值如何通过 a0/a1 返回、ra/sp/s0 等特殊寄存器的作用、caller-saved 与 callee-saved 的保存责任,以及栈帧和 16 字节对齐规则。适合阅读反汇编、编写 RISC-V 汇编、调试函数调用和理解编译器生成代码。
参数寄存器
标准整数调用约定提供 a0-a7 八个参数寄存器。至多 XLEN 位的标量占一个可用寄存器;2×XLEN 位标量占两个,若仅余一个则高半部入栈;更宽标量按引用传递。a0-a7 不跨调用保留。
返回值寄存器
整数标量返回值使用 a0,必要时可使用 a0/a1 两个参数/返回值寄存器。ret 只负责按返回地址跳回,不会自动生成返回值。
调用方保存寄存器
如果调用方在 call 之后还需要这些寄存器的值,必须在 call 前自己保存。被调函数可以自由覆盖它们。
被调方保存寄存器
调用方可以信任 s* 跨调用保持不变。如果被调函数要修改这些寄存器,必须在入口保存并在返回前恢复。sp 进入函数可下移分配栈帧,退出前必须恢复到进入时的位置。
特殊用途寄存器
zero 硬连线为 0,写入无效。ra 存返回地址,call 写入,ret 按 ra 跳回。sp 在标准 ABI 中按 128-bit(16 字节)边界对齐。gp 与 tp 是不可分配寄存器,通常由平台、运行时或 TLS 机制维护。fp/s0 可选用作帧指针。
参数传递
a0-a7 是八个参数寄存器,不代表任意八个参数都能放入寄存器。至多 XLEN 位标量占一个寄存器,2×XLEN 位标量占两个;寄存器不足时使用栈,更宽标量按引用传递。硬浮点 ABI 的浮点实参按 psABI 条件可使用 fa0-fa7。
返回值
标量结果通常放在 a0;需要两个寄存器时用 a0/a1。无法按寄存器返回的聚合值由调用方提供返回对象地址,约定细节以 psABI 的 flattening 和返回规则为准。
保存规则
caller-saved(a*, t*, ra):调用方负责保存。callee-saved(s*, sp):被调方借了必须还。跨调用需要保持的值优先放在 s* 或栈上。
栈帧
栈向低地址增长。进入函数时 sp 下移分配栈帧,退出时恢复到入口位置。标准 ABI 要求 sp 在过程入口处保持 128-bit(16 字节)对齐,并在过程执行期间保持对齐。
系统调用
ecall 是 ISA 定义的环境调用指令;具体系统调用号、参数寄存器和错误返回值属于执行环境或操作系统 ABI。常见 Linux RISC-V 用户态 ABI 约定使用 a7 放 syscall 号,a0-a5 放参数,a0 返回结果。
16 字节栈对齐
psABI 将标准栈对齐写成 128-bit 边界,也就是 16 字节。手写汇编如果会调用其他函数,分配局部栈空间后仍要让 sp 保持这个对齐。
帧指针(可选)
s0/fp 不是每个函数都必须设置。编译器在需要调试回溯或栈内偏移动态变化时才会生成帧指针。手写汇编时可以不用 fp,只要正确维护 sp。
本页参考以下官方 RISC-V 文档组织架构、ABI、CSR 和伪指令说明;平台或操作系统 ABI 差异仍需按对应规范核验。