jalr
lyszt.net 更详细地介绍了 jalr 和其他 RISC-V 指令。
编码格式
R
31–25funct7
24–20rs2
19–15rs1
14–12funct3
11–7rd
6–0opcode
I
31–20imm[11:0]
19–15rs1
14–12funct3
11–7rd
6–0opcode
S
31–25imm[11:5]
24–20rs2
19–15rs1
14–12funct3
11–7imm[4:0]
6–0opcode
B
31–25imm[12,10:5]
24–20rs2
19–15rs1
14–12funct3
11–7imm[4:1,11]
6–0opcode
U
31–12imm[31:12]
11–7rd
6–0opcode
J
31–12imm[20,10:1,11,19:12]
11–7rd
6–0opcode
描述
jalr 与 jal 属于同一家族,其中 r 代表寄存器。两条指令都会跳转并存储返回地址,如 jal 页面所述。区别在于跳转目标。jal 跳转到程序编写时固定的标签,而 jalr 跳转到寄存器中保存的地址,这使得目标可以在运行时计算。
这正是函数能够返回的原因。调用者将返回地址放入 ra 寄存器,函数通过使用 jalr 到达 ra 中的地址来跳回。ret 指令就是跳转到 ra 的 jalr。
同样的能力适用于目标事先未知的任何情况。它涵盖对地址作为参数传入的函数的调用,以及在地址表中列出的例程之间进行选择,这正是大型 switch 语句或解释器进行分派的方式。
根据 RISC-V 手册,jalr 将符号扩展的 12 位立即数加到寄存器 rs1,然后清除结果的最低有效位。它将下一条指令的地址 pc+4 存入 rd,当不需要返回地址时可以用 x0 作为目标。lui 后接 jalr 可到达任意 32 位绝对地址,auipc 后接 jalr 可到达任意 32 位 pc 相对地址。如果目标地址未对齐到四字节边界,两条跳转指令都会引发异常。
jalr 的格式如下所示。它跳转到寄存器 rs 中的地址加上一个可选的小偏移量,并将返回地址存入 rd。
jalr rd, rs, offset
与 jal 一样,它写入的寄存器会被覆盖,因此同样需要注意保护 ra。
示例
la t0, target jalr ra, t0, 0 # jump to target; ra holds the return address
简三的图詰
- [1]RISC-V International. The RISC-V Instruction Set Manual, Volume I: Unprivileged Architecture. Version 20260120. Section 2.5.1, Unconditional Jumps, page 30.
- [2]RISC-V International. The RISC-V Instruction Set Manual, Volume I: Unprivileged Architecture. Version 20260120. Section 2.4.1, Integer Register-Immediate Instructions, pages 28 to 29.
