我正在学习ARM大会,现在我被困在了什么东西上.
我知道链接寄存器,如果我没有错,则保存地址以在函数调用完成时返回.
所以,如果我们有这样的东西(取自ARM文档):
0 | here 1 | B there 2 | 3 | CMP R1, #0 4 | BEQ anotherfunc 5 | 6 | BL sub+rom ; Call subroutine at computed address.
那么,如果我们将左边的列视为每条指令的地址,那么在地址1的B之后,链接寄存器保持值为1对吗?
然后程序转到那里的方法然后它使用链接寄存器的值来知道返回的位置.
如果我们现在跳到地址6,我被卡住,我们知道BL将下一条指令的地址复制到lr(r14,链接寄存器).
所以现在它会复制sub的地址,这是一个子程序(什么是子程序?)+ rom(这是一个数字?)或sub + rom的地址(我不知道这可能是什么).
但总的来说,我们什么时候需要BL?为什么我们在上面的例子中想要它?有人能给我一个我们真正需要它的例子吗?
谢谢!
似乎有点混乱.这是一个解释:
该B
指令将跳转.它会跳转到另一条指令,并且没有预期的返回.未触及链接寄存器(LR).
该BL
指令将分支,也是链接.LR将BL
在内存中加载指令的地址,而不是之后执行的指令BL
.然后可以使用LR从分支返回.
示例:
start: 01: MOV r0, r2 ; some instruction 02: B there ; go there and never return ! there: 11: MOV r1, r0 ; some instruction 12: BL some_function ; go to some_function, but hope to return ! ; this BL will load 13 into LR 13: MOV r5, r0 14: BL some_function ; this BL will load 15 into LR 15: MOV r6, r0 some_function: MOV r0, #3 B LR ; here, we go back to where we were before
如果要在函数内调用另一个函数,LR将被覆盖,因此您将无法返回.常见的解决方案是将LR保存在堆栈中PUSH {LR}
,并在返回之前将其恢复POP {LR}
.你甚至可以恢复并返回一个POP {PC}
:这将恢复LR的值,但在程序计数器中,有效地返回该函数.