【发布时间】:2021-05-02 14:25:57
【问题描述】:
在 ARMv7 中,我知道有 bl 指令分支到一个地址并更新链接寄存器以指向它之后的指令。我也知道可以使用bl跳转到直接引用的标签,如下:
bl example_label
mov r5, 0
example_label:
mov r5, 111
@ blah blah blah
但是,当example_label 引用的地址在寄存器中时,比如说r0,我在执行以下操作时会出错:
bl r0
mov r5, 0
example_label:
mov r5, 111
@ blah blah blah
有没有办法可以使用寄存器执行bl 指令?我必须使用其他方法吗?还是完全不可能?
提前致谢!
编辑:
根据tum_的要求更新了代码sn-p
push lr # you need to store this
ldr r0, =example_label
blx r0 # overwrites existing lr.
mov r5, 0
pop pc # return to saved caller and don't execute example label again...
example_label:
mov r5, 111
@ blah blah blah
bx lr # not blah blah, you need to return control to caller.
【问题讨论】:
-
一如既往地询问编译器。在这种情况下,编译一个带有函数指针 arg 的函数(并且不能进行尾调用优化)。 godbolt.org/z/d1ddG4s4h 使用
blx r0显示它。 -
您能否更详细地解释一下为什么您认为更新后的代码不起作用?它应该,所以你的测试可能还有其他问题。 minimal reproducible example 最好。您在 cmets 中谈论
Default_handler但您向我们展示的代码中没有这样的东西,所以我们无法真正理解。 -
您需要
bx lr在END 处将“example_label”设为子例程。但是当返回mov r5, #0时,您将再次运行“example_label”。您需要控制 sn-ps 末端的流量。blx r0是正确的。 “x”是处理拇指互通,这是 ARMv7 的历史包袱。 'Thumb2' 使'interworking' 过时了......但它是跳转到寄存器的方式并允许纯 32 位 ARM 模式,这是为了向后兼容。 -
当你可以只使用 bl example_label 时,为什么还要使用 ldr r0、blx r0?
-
你需要知道函数是拇指代码还是手臂代码顺便说一句,并使用适当的地址。所有这些都由 arm 在 armv7-a(或 armv7-m 取决于您所谈论的那个)的架构参考手册中记录。请张贴您感到困惑的段落。