RISC-V 寄存器
指令通过寄存器快速读取操作数、保存结果;ABI 再约定寄存器如何在函数之间协作。
#RISC-V#xv6#计算机系统#学习笔记
一句话: 指令通过寄存器快速读取操作数、保存结果;ABI 再约定寄存器如何在函数之间协作。
本章导航#
整数寄存器 · ABI 名称 · 函数例子 · PC 与 CSR
学习目标#
- 认识 x0–x31、ABI 别名及 caller/callee-saved 约定。
- 阅读函数参数、返回值和栈帧相关汇编。
- 区分通用寄存器、PC、CSR 和浮点寄存器。
1. 整数寄存器 x0–x31#
基础整数 ISA 有 32 个整数寄存器,编号为 x0 到 x31。RV32 的 XLEN 为 32,RV64 的 XLEN 为 64。PC 是独立的程序计数器,不属于 x0–x31;CSR 也不是普通通用寄存器。
| 编号 | ABI 名 | 约定用途 | 跨函数调用保留? |
|---|---|---|---|
| x0 | zero | 恒为 0;写入结果被丢弃 | 不适用 |
| x1 | ra | 返回地址 | 否 |
| x2 | sp | 栈指针 | 是 |
| x3 | gp | 全局指针(平台/ABI 用) | 是 |
| x4 | tp | 线程指针 | 是 |
| x5–x7 | t0–t2 | 临时值 | 否 |
| x8–x9 | s0–s1 / fp | 被调用者保存值;x8 可作帧指针 | 是 |
| x10–x17 | a0–a7 | 参数/返回值;系统调用也使用其中部分寄存器 | 否 |
| x18–x27 | s2–s11 | 被调用者保存值 | 是 |
| x28–x31 | t3–t6 | 临时值 | 否 |
“caller-saved”表示调用者若还需要该值,应在调用前保存;“callee-saved”表示被调用函数要使用它时,必须恢复原值。别名是汇编/ABI 层面的便利名称,底层仍对应同一组 x 寄存器。
2. ABI 名称与调用约定#
在常见 RISC-V ABI 中:
- 前 8 个整数参数通常放在 a0–a7;更多参数通过栈传递。
- 整数返回值通常放在 a0(必要时还会用 a1)。
- 调用指令把返回地址放入 ra;被调用函数若会继续调用其他函数,通常要先保存自己的 ra。
- 栈向较低地址增长;符合标准 ABI 的代码需维持规定的栈对齐(常见标准 ABI 要求调用边界 16 字节对齐)。
- s0–s11 由被调用者负责恢复;t0–t6、a0–a7、ra 由调用者按需保存。
具体平台 ABI 会决定浮点参数、数据模型、结构体传参等细节。不要仅凭 ISA 推断整个程序的二进制接口。
3. 一个小例子#
下面是一个叶函数:它不再调用其他函数,因此不用保存 ra;调用者把两个参数放入 a0、a1,返回值仍放在 a0。
# int add2(int x, int y)add2: add a0, a0, a1 ret # ret 是 jalr 的常见伪指令如果函数需要在继续执行时跨越另一次函数调用保留 s0,它必须先保存原 s0,再在返回前恢复。栈帧大小和保存哪些寄存器取决于实际使用情况,编译器会根据 ABI 生成代码。
4. PC、CSR 和特权状态#
- PC: 当前/下一条指令地址的架构状态。顺序执行时按指令长度前进,分支和跳转会改变它。
- CSR(控制与状态寄存器): 保存特权级控制、异常/中断原因、页表配置、计数器等状态。访问受特权规则约束,通常使用
csrrw、csrrs等 CSR 指令。 - 常见 supervisor CSR:
sstatus(状态)、stvec(trap 入口)、sepc(trap 返回 PC)、scause(trap 原因)、satp(地址转换配置)。这些名称不表示普通 x 寄存器。 - 浮点寄存器: 在实现相应扩展时另有 f0–f31;它们与 x0–x31 分开。
核心结论: 指令集给出寄存器编号和语义;ABI 约定“谁传参、谁保存、结果放哪”。看函数汇编时,两层规则要一起用。
下一篇: 04 · RISC-V 指令详解 → 05 · 汇编实验