立即数编码

先看一个数怎样被搬进 32 位机器码

理解立即数编码时,可以先抓住一条主线:汇编里的立即数会被处理、切片、塞进固定指令位,CPU 解码时再按 immediate 位号拼回去。字段表随后就更容易对应起来。

B-type

为什么 beq 的 offset 位顺序看起来很怪?

分支目标按 2 字节对齐,所以 imm[0] 不占编码位;其余位分散存放。

示例
beq x1, x2, -4
汇编里的数01
-4
按格式切片02
imm[12] imm[10:5] imm[4:1] imm[11] imm[0]
放入指令位03
inst[31] inst[30:25] inst[11:8] inst[7]
解码还原04
-4
31..25
imm[12|10:5]
24..20
rs2
19..15
rs1
14..12
funct3
11..7
imm[4:1|11]
6..0
opcode
310
sign bitimmediateregisterimm[0] = 0
示例值
-4
编码用补码/字段值
1111111111100
解码恢复
-4

本页位布局按 RISC-V Unprivileged ISA Manual 的 base instruction formats 与 immediate variants 图示解释;CSR 5 位 immediate、压缩指令和扩展指令的特化编码不在这个 I/S/B/U/J 入门模型内。

通用规则

除 CSR 5 位 immediate 等特例外,base formats 的符号位总在 inst[31]。

分支/跳转

B/J 不保存 bit 0,offset 至少 2 字节对齐。

高位立即数

U-type 形成 32 位 U-immediate:[31:12] 来自指令,[11:0] 为 0。

按问题学习

先理解场景,再记格式名

下面每一节都用同一套路径:你在汇编里写什么、编码器把哪些位放到哪里、CPU 解码时怎样拼回去。

I-type

I-type:立即数直接放在一整段里

范围
-2048..2047
先记这个

把一个 12 位有符号数原样塞进指令最高 12 位。

I-type 这 12 位立即数可以有不同用途:在 addi 这类指令里它是参与运算的常数;在 lw 这类 load 指令里它是加到 rs1 基地址上的地址偏移;在 jalr 里它参与形成跳转目标。imm[11:0] 放在 inst[31:20],最高位 imm[11] 位于 inst[31],送入执行语义前按 XLEN 符号扩展。移位立即数指令是 I-type 的特化,使用 shamt 而不是普通 12 位有符号数。

连续字段12-bit signed运算常数 / load 地址偏移 / jalr 目标偏移移位立即数是特化

位从哪里到哪里

imm[11:0]inst[31:20]

完整 12 位立即数字段

imm[11]inst[31]

符号位

解码时怎么拼回去

  1. 01从 inst[31:20] 取出 imm[11:0]。
  2. 02用 imm[11] 作为符号位扩展到 XLEN。
  3. 03把扩展后的立即数交给 addi、load 或 jalr 的语义。
练习示例
addi x1, x2, -1
在编码器中打开查看 addi 指令
S-type

S-type:写入内存时的地址偏移拆成两段

范围
-2048..2047
先记这个

store 是写内存,不需要 rd 目标寄存器;原本 rd 的位置拿来放地址偏移的低 5 位。

用于 sb、sh、sw、sd 等 store(写内存)指令。汇编里的 sw x1, -8(x2) 表示把 x1 的值写到 x2 + (-8) 这个地址,-8 就是地址偏移。S-type 没有 rd 字段,所以这个 12 位偏移被拆到 inst[31:25] 与 inst[11:7],解码时再拼回 imm[11:0] 并符号扩展。

两段拼接12-bit signed写内存地址偏移

位从哪里到哪里

imm[11:5]inst[31:25]

地址偏移的高 7 位

imm[4:0]inst[11:7]

地址偏移的低 5 位

解码时怎么拼回去

  1. 01从 inst[31:25] 取 imm[11:5]。
  2. 02从 inst[11:7] 取 imm[4:0]。
  3. 03拼成 imm[11:0],按 imm[11] 符号扩展。
  4. 04把结果加到 rs1,得到 store 的有效地址。
练习示例
sw x1, -8(x2)
在编码器中打开查看 sw 指令
B-type

B-type:branch offset 的 bit 0 隐含为 0

范围
-4096..4094
先记这个

分支目标按 2 字节对齐,所以 imm[0] 不占编码位;其余位分散存放。

用于条件分支。目标地址是 PC-relative offset,编码保存 imm[12]、imm[10:5]、imm[4:1]、imm[11],最低位 imm[0] 不存储,表示分支目标按 2 字节边界对齐。

PC-relativebit 0 隐含 0非连续排布

位从哪里到哪里

imm[12]inst[31]

符号位

imm[10:5]inst[30:25]

offset 中高位

imm[4:1]inst[11:8]

offset 低位,imm[0] 不存

imm[11]inst[7]

被放到低字段末端

解码时怎么拼回去

  1. 01从 inst[31] 取 imm[12],这是符号位。
  2. 02从 inst[30:25] 取 imm[10:5]。
  3. 03从 inst[11:8] 取 imm[4:1],从 inst[7] 取 imm[11]。
  4. 04补上 imm[0]=0,按 imm[12] 符号扩展,再加到 PC。
练习示例
beq x1, x2, -4
在编码器中打开查看 beq 指令
U-type

U-type:20 位字段形成 32 位 U-immediate

范围
imm[31:12] << 12
先记这个

编码字段放到 32 位 U-immediate 的高 20 位,低 12 位直接补 0。

用于 lui 与 auipc。编码中的 imm[31:12] 形成 32 位 U-immediate 的高 20 位,低 12 位为 0;其符号位仍来自 inst[31]。常见大常数或地址通常要和 addi、load/store 或重定位配合。

upper immediate低 12 位为 0符号位仍是 inst[31]lui / auipc

位从哪里到哪里

imm[31:12]inst[31:12]

20 位高位字段

0x000imm[11:0]

32 位 U-immediate 的低 12 位补 0

解码时怎么拼回去

  1. 01从 inst[31:12] 取 20 位字段。
  2. 02把它放入 32 位 U-immediate 的 [31:12]。
  3. 03低 12 位填 0;LUI 把该 32 位值符号扩展到 XLEN 后写入 rd,AUIPC 把符号扩展后的 offset 加到 PC。
J-type

J-type:jal 的大范围 PC-relative offset

范围
-1048576..1048574
先记这个

jal 也是 PC-relative offset,imm[0] 不存,但用 20 个编码位覆盖更大范围。

用于 jal。它和 B-type 一样不存储 imm[0],但范围更大;编码保存 imm[20]、imm[10:1]、imm[11]、imm[19:12],解码后符号扩展并加到 PC。

PC-relativebit 0 隐含 0目标范围 ±1 MiB

位从哪里到哪里

imm[20]inst[31]

符号位

imm[10:1]inst[30:21]

offset 低中位

imm[11]inst[20]

单独插入的 bit 11

imm[19:12]inst[19:12]

offset 高位

解码时怎么拼回去

  1. 01从 inst[31] 取 imm[20],这是符号位。
  2. 02从 inst[30:21] 取 imm[10:1]。
  3. 03从 inst[20] 取 imm[11],从 inst[19:12] 取 imm[19:12]。
  4. 04补上 imm[0]=0,按 imm[20] 符号扩展,再加到 PC。
学完再查

I/S/B/U/J 立即数对照

这张表适合在理解流程后快速确认范围、是否符号扩展、以及哪些位没有连续存放。

格式场景立即数位范围 / 结果最该记住
Iaddi x1, x2, -1imm[11:0]-2048..2047把一个 12 位有符号数原样塞进指令最高 12 位。
Ssw x1, -8(x2)imm[11:5] + imm[4:0]-2048..2047store 是写内存,不需要 rd 目标寄存器;原本 rd 的位置拿来放地址偏移的低 5 位。
Bbeq x1, x2, -4imm[12] + imm[10:5] + imm[4:1] + imm[11] + 0-4096..4094分支目标按 2 字节对齐,所以 imm[0] 不占编码位;其余位分散存放。
Ului x1, 0x10imm[31:12]imm[31:12] << 12编码字段放到 32 位 U-immediate 的高 20 位,低 12 位直接补 0。
Jjal x1, -4imm[20] + imm[10:1] + imm[11] + imm[19:12] + 0-1048576..1048574jal 也是 PC-relative offset,imm[0] 不存,但用 20 个编码位覆盖更大范围。

错误演示器

错误直觉
lui x1, 0x10 => 0x00000010
正确理解
lui x1, 0x10 => 0x00010000

把 U-type 汇编操作数当成最终常数。lui x1, 0x10 得到的是 0x00010000 形式的 U-immediate,不是 0x10。

官方规范来源

本页参考以下官方 RISC-V 文档组织架构、ABI、CSR 和伪指令说明;平台或操作系统 ABI 差异仍需按对应规范核验。