TLDR:bx lr到底做什么?
我很难理解以下两个示例:
我知道代码“ add r0,r0,r1”将r1加到r1并将其存储到寄存器0。我不明白的是,代码“ bx lr”如何知道 返回r0而不明确声明r0。
在同一位置,我理解如果r0> r1,则代码“ BGT r0_Gt”进行比较,如果为true,则代码将跳至r0_gt:但是,bx lr如何知道如何返回正确的值? >
答案 0 :(得分:2)
由使用的ABI定义;对于ARM,这是EABI,它在“ 5.4结果返回”中声明
- 小于4个字节的基本数据类型将零扩展或符号扩展到一个单词,并在r0中返回。
http://infocenter.arm.com/help/topic/com.arm.doc.ihi0042f/IHI0042F_aapcs.pdf
答案 1 :(得分:1)
bx lr
根本不返回任何寄存器,它只是将控制权交还给调用方(在lr
寄存器的地址中),而不修改{{1}以外的任何其他寄存器}。
然后,调用者根据调用约定知道,返回时,返回值将位于r0寄存器中(取决于返回值的确切类型和平台的调用约定)。
答案 2 :(得分:0)
BX只是意味着分支交换,它做了一个分支,并且如果该体系结构受支持,可以在arm / thumb之间切换模式。 LR是寄存器14的快捷方式。跳转到r14中的地址。
如果您查看bl指令,则会看到r14将设置为bl指令后的地址,即函数调用的返回地址。
这对bl东西然后是bx lr(或者如果您不需要更改模式并且处于arm模式,也可以使用mov pc,lr也可以)是在arm中进行函数调用的方式。
答案 3 :(得分:0)
处理器(在抽象意义上)几乎没有上下文的概念。它不知道它来自哪里,寄存器的用途,或者它是否在函数调用/子例程中。高级语言和编译器确实知道这一点,并使用一些通用标准使事情变得更容易。
极少数操作确实具有特殊的,明确定义的目的。 BL指令不仅更新“下一条要执行的指令”(也称为PC或R15),而且还神奇地更新R14(链接寄存器)。
异常(在V7-A中)会更改一些存储区核心寄存器,包括通常用于访问堆栈的寄存器和链接寄存器。这意味着可以在不丢失正在发生的所有其他事情的情况下发生异常。 Cortex M的处理方式有所不同,实际上使用堆栈来帮助银行业务(将R14设置为“魔术值”以指示最近的通话是否为异常)。
除非一条指令与特定的寄存器(特别是CPSR)进行交互,否则它可能并不关心上下文。某些操作(与安全相关的操作)将受到限制,因此只能在特权状态下发生-最终用于阻止用户应用程序使用操作系统,但是通常这些操作与访问非常特定的控制寄存器有关。