首页/指令库/寄存器跳转并链接
JALR

RISC-V JALR 指令详解

指令手册I-type

将rs1与12位有符号立即数相加(结果最低位清零)作为目标地址跳转,同时将返回地址写入rd

指令语法

jalr rd, offset(rs1)
操作数说明
目标寄存器 rd:存放运算结果的通用寄存器。
源寄存器 rs1:第一个操作数所在的寄存器。
立即数 imm:12 位有符号立即数,符号扩展后与 rs1 进行运算。
RV32I控制转移跳转

指令行为说明

JALR指令采用I型格式(opcode=1100111, funct3=000)。目标地址由rs1与12位有符号立即数相加后,最低位强制清零得到。同时将返回地址(PC+4)写入寄存器rd。当rd=x0时即为间接跳转(伪指令JR);当rd=x0且rs1=x1且imm=0时即为函数返回(伪指令RET)。结果最低位清零的设计既简化硬件,也允许函数指针最低位存储辅助信息。rd和rs1为x1/x5时的组合为返回地址栈(RAS)提供隐式预测提示。

JALR 指令解析与执行动画

以 ADDI 页面同样的节奏展示:机器码字段解析、固定字段识别、操作数读取、指令专属语义计算和 ISA 可见状态更新。

rd
imm
rs1
jalr
,
(
)
执行环境
31..20
19..15
14..12
11..7
6..0
000000000000
imm[11:0]
00101
rs1
000
funct3
00001
rd
1100111
opcode
执行数据路径
instruction
0x000280E7
opcode
1100111 -> JALR
funct3
000 -> JALR
rd / rs1 / pc
ra(x1) / t0(x5)=0x00003001 / 0x00002000
imm[11:0]
000000000000 -> 0
target/link
link=0x00002004, (0x00003001 & ~1)=0x00003000
PC / link
ra(x1) = 0x00002004; pc = 0x00003000
当前步骤

概念步骤:拿到 32-bit 指令编码

机器码按当前指令格式切成字段,动画从 encoding/decode 开始。

encoding: 0x000280E7
syntax : jalr ra(x1), 0(t0(x5))
result : ra(x1) = 0x00002004; pc = 0x00003000

该动画展示 ISA 可见的解码和状态变化,不表示任何特定 CPU 的流水线、缓存、预测或时序实现。

快速理解与检索要点

JALR 是寄存器间接跳转并链接:目标地址由 rs1 加符号扩展的 12 位立即数得到,并在跳转前把最低位清零,同时把 pc+4 写入 rd。

JALR 的立即数不是按 2 字节缩放,而是普通 12 位有符号字节偏移。
清零最低位允许函数指针低位携带辅助信息,也简化硬件。

官方规范要点

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

常见使用场景

函数调用与返回

使用 jal ra, label 或 jalr ra, rs, imm。

分支与跳转

结合 «jalr x1, 0(x5) # jump to x5, x1 = pc+4» 等实际代码理解该场景。

使用前检查清单

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

容易混淆 / 常见误区

目标地址 bit 0 会被清零;这不保证 4 字节对齐,未对齐异常仍取决于目标地址和 IALIGN
返回地址栈(RAS)的行为由 rd 和 rs1 的组合隐式控制
直接 JALR x0,rs1,0 等价于 JR 伪指令(不保存返回地址)

常见问题

为什么 JALR 会清零目标地址最低位?

官方手册说明这样可简化硬件,并允许函数指针最低位存储辅助信息。

RET 通常展开成什么?

常见返回形式是 jalr x0, 0(ra),也就是不写返回地址、跳转到 ra 指向的位置。