BL 指令 ARM - 它是如何工作的

问题描述 投票:0回答:2

我正在学习 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?为什么我们在上面的例子中需要它?有人可以给我一个我们真正需要它的例子吗?

谢谢!

assembly arm
2个回答
43
投票

好像有点混乱。这是一个解释:

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会被覆盖,所以你将无法返回。常见的解决方案是使用

PUSH {LR}
将 LR 保存在堆栈上,并在返回之前使用
POP {LR}
恢复它。您甚至可以在单个
POP {PC}
中恢复和返回:这将恢复 LR 的值,但在程序计数器中,有效地返回函数。


0
投票

BL 指令执行两件事: 它将下一条指令(BL之后的指令)的返回地址存储在链接寄存器(LR)中,并分支到目标地址。

PC 和 LR 分别是 R15 和 R14 的替代名称。

© www.soinside.com 2019 - 2024. All rights reserved.