寄存器指南

RISC-V s0 / fp / x8 寄存器:保存寄存器与可选帧指针

s0 是 psABI 的 callee-saved 寄存器:函数如果修改它,返回前必须恢复。psABI 还规定,如果代码使用帧指针,帧指针必须放在 x8,也就是 s0/fp。

psABI:x8-x9 / s0-s1 是 callee-saved 寄存器。
psABI:帧指针是可选的;存在时必须位于 x8/s0。
新手规则:借用 s0 后要恢复;当作 fp 使用时不要随意改动。
物理编号 x8ABI 名 s0保存责任 被调用者
角色
被保存寄存器/帧指针
调用约定
被调用者保存
先记一句
s* 属于 callee-saved:函数借用了就必须在返回前恢复。
psABI 规范依据

保存寄存器

psABI 将 s0-s11 标记为调用后保持。被调用函数如果修改这些寄存器,必须在返回前恢复原值;s0 也可作为 frame pointer。

调用后保持:
RISC-V psABI integer register convention
快速理解与检索要点

s0 / x8 属于 s0-s11 保存寄存器组。psABI 规定它调用后保持;被调用函数如果修改它,返回前必须恢复。

s0-s11 是调用后保持的保存寄存器。
如果使用帧指针,psABI 规定它必须位于 x8/s0。

适合什么时候用

  • - 保存跨函数调用仍然需要的值。
  • - 在函数内部调用其他函数后仍要继续使用的数据。
  • - s0/fp 还可作为帧指针,让栈帧访问更稳定。

什么时候不要这样用

  • - 不要在函数里修改 s* 后直接返回。
  • - 短生命周期临时值优先考虑 t*,不用为了短计算占用 s*。

调用前后会发生什么

1

s* 属于 callee-saved:函数借用了就必须在返回前恢复。

2

caller 可以假设调用返回后 s* 保持原值。

3

修改 s* 通常意味着函数入口保存、出口恢复。

RV64 callee-saved 保存与恢复

示例用于理解规则,不替代完整程序
addi sp, sp, -16
sd   s0, 0(sp)
addi s0, a0, 0
call foo
# s0 仍保存调用前需要的值
ld   s0, 0(sp)
addi sp, sp, 16
ret

常见问题

s0 / x8 为什么适合保存跨调用值?

s0-s11 调用后保持;callee 修改它们时必须恢复,所以 caller 可以依赖其返回后不变。

s0 被函数修改后谁负责恢复?

被调用函数负责恢复。