我了解到,jal和jalr都可以用于调用函数,而相反只能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它。
您可能遗漏的一点是,通常,函数或子例程应该能够从代码中的不同位置调用(即,对子例程的多次调用分布在代码中),因此它应该能够返回到代码中的不同位置。
jal指令跳转到的地址由pc寄存器的内容加上指令中编码的 21 位常量偏移量决定。因此,jal用于返回的子例程仅限于返回相同的(相对于 固定的pc)地址。
jal仍然用于子程序返回?如果您的子例程仅从代码中的单个位置被调用,它仍然可以jal用于返回到其调用者——前提是返回地址对应于距离用于返回的指令大约±1MB的内存位置jal。只需考虑调用子例程,jal x0, sum3而不是call sum3要防止ra寄存器被破坏。