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

Tan*_*nia 5 assembly riscv

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

sum3:

    add a0, a0, a1
    add a0, a0, a2
    jalr x0, 0(ra)
Run Code Online (Sandbox Code Playgroud)

但是,此代码使用jal而不是jalr从函数返回,并且效果很好:

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

    add a0, a0, a1
    add a0, a0, a2
    jal x0, ret_sum3
Run Code Online (Sandbox Code Playgroud)

既然如此,为什么说jalr是函数返回的指令呢?我也可以用jal它。

眠りネ*_*ネロク 6

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

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


jal仍然用于子程序返回?

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