🧩 RISC-V 寄存器使用约定表(整数与浮点寄存器)
| 寄存器编号 |
ABI 名称 |
描述(用途) |
调用间是否保持不变(Preserved across call) |
| x0 |
zero |
硬连线为常数 0(读为 0,写入无效) |
— |
| x1 |
ra |
返回地址(Return Address) |
否 |
| x2 |
sp |
栈指针(Stack Pointer) |
是 |
| x3 |
gp |
全局指针(Global Pointer) |
是 |
| x4 |
tp |
线程指针(Thread Pointer) |
是 |
| x5–x7 |
t0–t2 |
临时寄存器(Temporaries) |
否 |
| x8 |
s0 / fp |
保存寄存器 / 帧指针(Saved register / Frame pointer) |
是 |
| x9 |
s1 |
保存寄存器(Saved register) |
是 |
| x10–x11 |
a0–a1 |
参数寄存器 / 返回值寄存器(Function arguments / Return values) |
否 |
| x12–x17 |
a2–a7 |
参数寄存器(Function arguments) |
否 |
| x18–x27 |
s2–s11 |
保存寄存器(Saved registers) |
是 |
| x28–x31 |
t3–t6 |
临时寄存器(Temporaries) |
否 |
| f0–f7 |
ft0–ft7 |
浮点临时寄存器(FP temporaries) |
否 |
| f8–f9 |
fs0–fs1 |
浮点保存寄存器(FP saved registers) |
是 |
| f10–f11 |
fa0–fa1 |
浮点参数 / 返回值(FP args / return values) |
否 |
| f12–f17 |
fa2–fa7 |
浮点参数寄存器(FP arguments) |
否 |
| f18–f27 |
fs2–fs11 |
浮点保存寄存器(FP saved registers) |
是 |
| f28–f31 |
ft8–ft11 |
浮点临时寄存器(FP temporaries) |
否 |
🧠 概念解释
1️⃣ 调用约定(Calling Convention)
当函数调用另一个函数时:
- 某些寄存器由**调用者(Caller)**负责保存(调用者保存寄存器)
- 某些寄存器由**被调用者(Callee)**负责保存(被调用者保存寄存器)
这确保函数调用之间不会互相破坏关键数据。
2️⃣ 调用者保存寄存器(Caller-saved)
| 类型 |
示例 |
说明 |
| 临时寄存器 |
t0–t6 |
调用前如需保留,调用者自己保存 |
| 参数 / 返回寄存器 |
a0–a7 |
调用时用于传参和返回 |
| 浮点临时寄存器 |
ft0–ft11 |
调用前如需保留,调用者自己保存 |
| 返回地址寄存器 |
ra |
jal 指令写入的返回地址 |
3️⃣ 被调用者保存寄存器(Callee-saved)
| 类型 |
示例 |
说明 |
| 保存寄存器 |
s0–s11 |
被调用函数必须在修改前保存、结束前恢复 |
| 栈指针 |
sp |
每个函数维护自己的栈帧 |
| 全局 / 线程指针 |
gp, tp |
通常系统级分配,保持不变 |
| 浮点保存寄存器 |
fs0–fs11 |
与整数保存寄存器类似 |
4️⃣ 特殊寄存器
| 名称 |
用途 |
zero |
恒为 0,可用于快速清零(如 add x5, x0, x0) |
ra |
存放函数返回地址(jal、jalr 指令) |
sp |
指向当前栈顶 |
s0 |
既是保存寄存器,也是函数帧指针(frame pointer) |
gp |
全局指针,用于访问全局变量 |
tp |
线程指针,多线程运行时使用 |
🧩 调用关系可视化(简化)
Caller:
t0–t6, a0–a7, ra → 调用者保存
s0–s11, sp → 被调用者保存
Callee:
可自由使用 t0–t6, a0–a7
若修改 s0–s11,必须保存并恢复
✅ 小结
| 分类 |
寄存器 |
是否保存 |
备注 |
| 常数寄存器 |
x0 |
无需保存 |
恒为 0 |
| 栈/帧指针 |
sp, s0 |
是 |
由被调用者维护 |
| 临时寄存器 |
t0–t6 |
否 |
调用者自行保存 |
| 参数/返回寄存器 |
a0–a7 |
否 |
用于传参与返回 |
| 保存寄存器 |
s1–s11 |
是 |
被调用者保存 |
| 浮点保存寄存器 |
fs0–fs11 |
是 |
被调用者保存 |
| 浮点临时寄存器 |
ft0–ft11 |
否 |
调用者保存 |
这张表是理解 RISC-V 函数调用、栈帧建立与寄存器保存机制 的核心。
它直接对应你在汇编中看到的:
sd s0,40(sp) # 保存被调用者寄存器
addi s0,sp,48 # 建立帧指针
jr ra # 使用返回地址寄存器