ADD

RISC-V ADD 指令详解

指令手册R-type

将rs1与rs2相加,结果写入rd

指令语法

add rd, rs1, rs2
操作数说明
目标寄存器 rd:存放运算结果的通用寄存器。
源寄存器 rs1:第一个操作数寄存器。
源寄存器 rs2:第二个操作数寄存器。
RV32I算术运算

指令编码

31..25
funct7
24..20
rs2
19..15
rs1
14..12
funct3
11..7
rd
6..0
opcode

ADD 使用 opcode 0110011(0x33)、funct3 000、funct7 0000000。rs1 和 rs2 字段选择两个源寄存器,rd 字段选择目标寄存器。

格式: R-type
opcode: 0110011 (0x33)
funct3: 000 (0x0)
funct7: 0000000 (0x00)

指令行为说明

ADD指令采用R型格式。将rs1和rs2寄存器的值相加(算术溢出忽略,仅保留低XLEN位),结果写入rd。funct7=0000000, funct3=000。这是RISC-V中最基本的算术运算指令。ADD与ADDI配合实现基址+偏移的地址计算。

快速理解与检索要点

ADD 是寄存器到寄存器的整数加法。官方 RV32I 语义是把 rs1 与 rs2 相加并写入 rd,算术溢出不会产生异常,结果按 XLEN 宽度截断。

两个源操作数都来自寄存器;需要加小立即数时使用 ADDI。
ADD 与 SUB 使用相同 opcode 和 funct3,主要由 funct7 区分。

官方规范要点

以下要点按 RISC-V Unprivileged ISA 手册核准,用于补充操作语义、立即数范围和边界行为。

指令对比

ADD vs ADDI

ADD 使用两个寄存器操作数(rs1 + rs2),而 ADDI 使用一个寄存器和一个 12 位有符号立即数(rs1 + imm)。ADD 是 R-type 指令(opcode 0110011),ADDI 是 I-type 指令(opcode 0010011)。若需要加一个不在 -2048~2047 范围内的常数,应先通过 LUI+ADDI 将其加载到临时寄存器,再使用 ADD。

ADD vs SUB

ADD 和 SUB 都是 R-type 指令,共享相同的 opcode (0110011) 和 funct3 (000)。二者的区别仅在于 funct7 字段:ADD 的 funct7 = 0000000,SUB 的 funct7 = 0100000。也就是说,SUB 实际上是通过 funct7 的最高位(bit30)来区分的——该位为 0 时执行加法,为 1 时执行减法。RISC-V 这样设计是为了简化解码逻辑,避免浪费额外的 opcode 空间。

常见使用场景

地址与指针

结合 «add x5, x6, x7 # x5 = x6 + x7» 等实际代码理解该场景。

寄存器操作

结合 «add x5, x6, x7 # x5 = x6 + x7» 等实际代码理解该场景。

循环与迭代

结合 «add x5, x6, x7 # x5 = x6 + x7» 等实际代码理解该场景。

使用前检查清单

语法检查
  • 确认当前指令格式为 R-type。
  • 确认操作数排列顺序与示例一致。
语义检查
  • 确认目标寄存器用途和调用约定兼容。
  • 确认该指令不是伪指令展开后的底层形式。

容易混淆 / 常见误区

溢出被静默忽略,不会触发异常
rd=x0 时结果丢弃(HINT 空间),不要指望 x0 存储运算结果
不要与 ADDI 混淆:ADD 两个操作数都是寄存器,ADDI 第二个是立即数

常见问题

ADD 会在溢出时产生异常吗?

不会。RISC-V 基础整数加法忽略算术溢出,软件需要自行用比较或分支序列检测溢出。

ADD 和 ADDI 应该怎么选?

两个操作数都在寄存器中时用 ADD;第二个操作数是 12 位有符号立即数时用 ADDI。