RISC-V 指令详解
一条汇编指令可以概括为:从寄存器取值,执行操作,再写寄存器、访存或改变 PC。
#RISC-V#xv6#计算机系统#学习笔记
一句话: 一条汇编指令可以概括为:从寄存器取值,执行操作,再写寄存器、访存或改变 PC。
本章导航#
指令编码 · 算术逻辑 · 内存访问 · 控制流 · 完整小例子
学习目标#
- 读懂 R/I/S/B/U/J 格式的常见用途。
- 分清算术、load/store、分支和跳转。
- 理解汇编助记符、伪指令与机器编码之间的关系。
1. 指令与编码#
RISC-V 汇编助记符便于阅读;汇编器把它编码成机器指令。基础指令通常是 32 位,C 扩展提供 16 位压缩编码。常用字段包括操作码、寄存器编号、功能位和立即数;立即数位可能分布在编码的多个位置,汇编器负责拼装。
| 格式 | 主要用途 | 例子 |
|---|---|---|
| R | 寄存器—寄存器运算 | add t0, t1, t2 |
| I | 立即数运算、load、jalr | addi t0, t1, 12 |
| S | store | sw t0, 8(sp) |
| B | 条件分支 | beq t0, t1, done |
| U | 高位立即数 | lui t0, 0x12345 |
| J | PC 相对跳转 | jal ra, func |
2. 算术、逻辑和移位#
| 指令 | 作用 | 关键点 |
|---|---|---|
add rd, rs1, rs2 | 整数相加 | 结果写 rd;无条件码标志寄存器 |
sub rd, rs1, rs2 | 相减 | rs1 - rs2 |
addi rd, rs1, imm | 加符号扩展立即数 | 基础形式立即数宽度有限,不能直接表达任意常量 |
and / or / xor | 逐位逻辑运算 | 位掩码、置位、翻转常用 |
sll / srl | 左移 / 逻辑右移 | 逻辑右移高位补 0 |
sra | 算术右移 | 高位用符号位填充 |
slt / sltu | 有符号 / 无符号比较 | 比较结果为 0 或 1 |
RV64 还有 addw、sllw 等 W 指令:先在 32 位宽度上运算,再将结果符号扩展到 XLEN。阅读代码时要根据目标 XLEN 和具体指令语义解释结果。
3. Load/store 访存#
RISC-V 的整数算术通常只对寄存器操作数运算。地址常写作 偏移(base):有效地址 = base 寄存器 + 符号扩展偏移。
lw a0, 8(sp) # 从 sp+8 读取 32 位;RV64 下符号扩展到 64 位sw a0, 8(sp) # 将低 32 位写到 sp+8ld a1, 16(sp) # RV64:读取 64 位sd a1, 16(sp) # RV64:写入 64 位lb/lh/lw 会按符号扩展读取;lbu/lhu/lwu 会零扩展。可用的 load/store 宽度受 ISA 和目标平台支持约束。地址对齐、权限和映射不正确时,访存可能触发异常;示例中的 sp 必须指向有效内存。
4. 分支与跳转#
条件分支#
beq rs1, rs2, label:相等时跳转。bne rs1, rs2, label:不相等时跳转。blt/bge:有符号小于/大于等于。bltu/bgeu:无符号比较。
目标相对当前 PC 编码。伪指令如 bgt 通常会被改写成交换操作数后的基本分支。
无条件跳转#
jal rd, label:把返回地址写入 rd,再跳到 PC 相对目标;jal ra, label常用于函数调用。jalr rd, imm(rs1):从寄存器加偏移构造目标,同时可写返回地址;标准语义会清除目标地址最低位。ret:常见伪指令,通常等价于jalr x0, 0(ra)。
5. 把指令串起来#
下面的片段在寄存器中计算 7+5,并尝试把结果存入 sp 指向的栈空间:
addi t0, zero, 7 addi t1, zero, 5 add t2, t0, t1 sw t2, 0(sp) # 仅当 0(sp) 是有效、可写地址时成立汇编中的 li、mv、nop、ret 等许多常用写法是伪指令,汇编器可能将它们展开为一条或多条真实指令。要看具体编码,可使用反汇编工具,例如 objdump -d。
核心结论: 读指令时同时跟踪操作数、结果位置、位宽和 PC 变化;不要把伪指令误认为必然对应一条机器指令。
下一篇: 05 · RISC-V 汇编实验 → 06 · GCC 与 QEMU