为什么使用 JALR 而不是 JAL 从子程序返回

Why is JALR used instead of JAL for returning from subroutines

我了解到 jaljalr 都可以用于调用函数,而相反只有 jal 可以用于从这样的函数返回:

sum3:

    add a0, a0, a1
    add a0, a0, a2
    jalr x0, 0(ra)

但是,此代码使用 jal 而不是 jalr 从函数返回并且运行良好:

    call sum3
ret_sum3:   
    # following instructions
    # ...
sum3:

    add a0, a0, a1
    add a0, a0, a2
    jal x0, ret_sum3

鉴于此,为什么说jalr是函数返回的指令呢?我也可以使用 jal

您可能遗漏的一点是,一般来说,函数或子例程应该能够从代码中的不同位置调用(即,对子例程的多次调用分布在代码中),因此它也应该能够 return 到代码中的不同位置。

jal指令跳转到的地址由pc寄存器的内容加上指令中编码的21位常量偏移量决定。因此,使用 jal 进行 returning 的子例程仅限于 return 到相同(相对于 pc 固定)地址。


jal还能用于子程序return吗?

如果您的子例程仅从代码中的一个位置调用,它仍然可以使用 jal 来 returning 到它的调用者——前提是 return 地址对应于一个内存位置与用于 returning 的 jal 指令相距大约 ±1MB。如果要防止 ra 寄存器被破坏,只需考虑将子例程调用为 jal x0, sum3 而不是 call sum3