我正在尝试和GCC一起在ARM上做一些裸机编程,并在QEMU上进行测试。每当我从C调用ARM标签时,我的程序就会挂起。我有一个简单的代码示例,它显示了https://gist.github.com/1654392的问题--当我在代码中调用activate()时,它挂起了。
我用objdump观察到,当我从汇编到C代码(如从_start)执行bl时,它会生成一个切换到thumb指令的小包装器。似乎所有的C代码都是在thumb指令中生成的,但我的所有汇编都是在ARM (32位)指令中生成的。我不知道这是为什么,也不知道如何修复它。
发布于 2013-04-20 15:13:39
为了从C定义的THUMB模式函数调用汇编语言中定义的ARM模式函数,您需要将汇编语言中的符号定义为函数,并且工具(Linaro gcc)将生成blx指令而不是bl指令。
示例:
@ Here, we suppose that this part of code is inside of .code 32
.type fn, %function
fn:
mov pc, lr发布于 2012-01-22 23:43:55
请参见http://github.com/dwelch67/yagbat qemu目录。
下面是几个从arm调用arm或thumb的示例
start_vector:
mov sp,#0x20000
;@ call an arm function from arm
bl notmain
;@ call a thumb function frm arm
ldr r0,=0xAABBAABB
bl hexstring_trampoline
;@ call a thumb function frm arm
ldr r0,=0x12341234
ldr r1,hexstring_addr
mov lr,pc
bx r1
;@ call a thumb function frm arm
ldr r0,=0x12312344
bl hexstring_trampoline
hang:
b hang
hexstring_trampoline:
ldr r1,hexstring_addr
bx r1
hexstring_addr: .word hexstring如果您查看指令集参考,您将看到您需要使用BX或BLX在arm和thumb状态之间切换。BLX不像BX那样被广泛支持。
从程序计数器的定义角度来看,pc在指令执行期间领先两条指令。对于thumb是4字节,对于arm是8字节。无论哪种情况,都有两条指令。要模拟不能用于更改状态的bl,您需要用返回地址加载链接寄存器,并使用bx根据地址的lsbit分支到函数更改状态。因此,
mov lr,pc
bx r1
here:上面的mov lr,pc加载这里的地址:这是我们的返回地址,bx r1以独立于状态的方式调用函数。lr地址的lsbit指示要返回的模式,您需要始终使用bx返回
pre_thumb:
ldr pc,lr
thumb_capable:
bx lr编译器分配bl指令来调用函数,链接器随后填充其余部分,如果太远,则需要链接器自己添加的trampoline函数。同样,如果您需要更改模式,bl将调用一个执行此操作的trampoline函数。我已经在上面的一个例子中模拟了这一点,你可以看到它有点浪费,希望我对编译器只为bl分配空间的解释让这一点变得更清楚,浪费就是总是计划模式更改,并且必须在代码中为大多数函数调用插入nops。
代码还包括在汇编程序中从thumb调用arm:
.thumb
.thumb_func
.globl XPUT32
XPUT32:
push {lr}
;@ call an arm function from thumb asm
ldr r2,=PUT32
mov lr,pc
bx r2
pop {r2}
bx r2大体相同,除了你不能弹出lr在拇指模式,你可以弹到pc,但我不认为切换模式,所以你不能使用它,你再次需要一个备用寄存器。当然,您需要了解调用约定以了解您可以使用哪些寄存器,或者您可以包装另一组推送和弹出以保留除lr之外的所有寄存器
push {r2,lr}
;@ call an arm function from thumb asm
ldr r2,=PUT32
mov lr,pc
bx r2
pop {r2}
mov lr,r2
pop {r2}
bx lr拇指对拇指或手臂对手臂如果你够得着就用bl。ldr pc,如果不能,请提供地址。
发布于 2012-01-23 19:30:44
如果您将asm代码汇编为Thumb,则需要将函数标记为Thumb函数,以便链接器在分支到它时使用正确的指令(例如,BLX或BX到设置了低位的地址)。这是通过.thumb_func指令完成的:
.global activate
.thumb_func
activate:
b test另一种选择是显式地要求汇编程序生成ARM代码:
.code 32
.global activate
activate:
b test也要检查this article,尽管请记住,当前的处理器不需要很多在ARMv4中必需的变通方法,因此您可能不应该盲目地遵循它。
https://stackoverflow.com/questions/8957474
复制相似问题