寄存器指南

RISC-V t0 / x5 寄存器:临时值、调用覆盖与备用链接寄存器

t0 是 psABI 的临时寄存器,调用后不保持;需要跨调用保留的值不能只放在 t0。RISC-V ISA 还说明,标准调用约定使用 x1 保存返回地址,同时 x5 可作为备用链接寄存器。

psABI:x5-x7 / t0-t2 是 temporary registers,调用后不保持。
ISA:x5 可作为 alternate link register。
新手规则:普通代码中把 t0 当短生命周期临时值,跨 call 前主动保存。
物理编号 x5ABI 名 t0保存责任 调用者

t0 标记为 Caller-saved。把 x5 用作备用链接寄存器不会改变这个保存责任;需要跨调用保留时,caller 必须自己保存。

角色
临时变量/备用链接寄存器
调用约定
调用者保存
先记一句
psABI 将 t0 标记为 temporary register,调用后不保持。
psABI 规范依据

临时寄存器

psABI 将 t0-t6 标记为临时寄存器。它们不是 callee-saved;调用者如果需要跨调用保留其中的值,必须自己保存。

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

t0 / x5 属于 t0-t6 临时寄存器组。psABI 规定它调用后不保持;调用者如果需要跨调用保留其中的值,必须自己保存。

t0-t6 是临时寄存器,调用后不保持。
ISA 说明 x5 可作为备用链接寄存器,但 psABI 仍把 t0 归为临时寄存器。

适合什么时候用

  • - 保存短生命周期临时值,前提是这些值不需要自动跨函数调用保留。
  • - 在手写汇编中按调用约定明确管理它的生命周期。
  • - 理解 ISA 中的备用链接寄存器说明:x5 可作为 alternate link register。

什么时候不要这样用

  • - 不要默认 t0 在函数调用后仍保留旧值。
  • - 不要把 t0 保存的值假设为跨函数调用仍可用(caller 自己保存除外)。

调用前后会发生什么

1

psABI 将 t0 标记为 temporary register,调用后不保持。

2

如果 caller 在 call 后还需要 t0 的值,caller 必须先保存。

3

ISA 指出 x5 可用作备用链接寄存器,但这不改变 t0 的 ABI 保存责任。

t0 的两种典型用法

示例用于理解规则,不替代完整程序
# 用法 1:作为常规临时寄存器
add  t0, a0, a1     # t0 = a0 + a1
slli t0, t0, 2      # t0 = t0 << 2
# 如果结果要跨 call 保留,caller 先保存到 ABI 合法的位置
# 用法 2:理解 x5 可作为备用链接寄存器
# 具体写法取决于调用序列和汇编器伪指令

与其他寄存器的关系

t0 vs ra (备用链接寄存器 vs 主链接寄存器)

RISC-V ISA 说明,标准调用约定使用 x1 作为返回地址寄存器,x5 可作为 alternate link register。psABI 同时把 x1/ra 标记为返回地址寄存器,把 x5/t0 标记为 temporary register;两者都不是调用后保持寄存器。实际写汇编时,后续返回序列会读取哪个寄存器,必须由调用序列明确决定。

为什么不能当普通寄存器用

虽然 ISA 说明 x5 可作为备用链接寄存器,但 psABI 仍把 t0 归为调用后不保持的临时寄存器。只要后续代码还需要 t0 中的值,caller 就必须在调用前保存;如果把它用于返回地址,更要确认返回序列读取的是 t0 还是 ra。

常见问题

t0 / x5 调用后会保持吗?

不会。t0-t6 是临时寄存器,调用后不保持。

跨 call 还需要 t0 的值怎么办?

caller 必须在调用前把它保存到栈或其他合适位置,并在调用后恢复。