🧩 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)

当函数调用另一个函数时:

这确保函数调用之间不会互相破坏关键数据。


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 存放函数返回地址(jaljalr 指令)
sp 指向当前栈顶
s0 既是保存寄存器,也是函数帧指针(frame pointer)
gp 全局指针,用于访问全局变量
tp 线程指针,多线程运行时使用

🧩 调用关系可视化(简化)

text
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 函数调用、栈帧建立与寄存器保存机制 的核心。 它直接对应你在汇编中看到的:

asm
sd s0,40(sp)    # 保存被调用者寄存器
addi s0,sp,48   # 建立帧指针
jr ra           # 使用返回地址寄存器