跳至正文
这篇笔记的目录
回到学习目录
技术开发

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、jalraddi t0, t1, 12
Sstoresw t0, 8(sp)
B条件分支beq t0, t1, done
U高位立即数lui t0, 0x12345
JPC 相对跳转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 还有 addwsllw 等 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+8
ld 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) 是有效、可写地址时成立

汇编中的 limvnopret 等许多常用写法是伪指令,汇编器可能将它们展开为一条或多条真实指令。要看具体编码,可使用反汇编工具,例如 objdump -d

核心结论: 读指令时同时跟踪操作数、结果位置、位宽和 PC 变化;不要把伪指令误认为必然对应一条机器指令。

下一篇: 05 · RISC-V 汇编实验06 · GCC 与 QEMU