ABI对__aeabi_idivmod的调用并不像预期的那样

时间:2014-06-23 16:18:48

标签: arm abi stm32f4discovery

我正在尝试在裸机架构上开发一个程序(使用ARM cortex-m4f处理器的stm32f4板)。我在ABI调用__aebi_idivmod时遇到了一个奇怪的问题。 调用是由编译器生成的,因为在代码中有多个%操作数的使用。奇怪的是,如果我查看使用objdump编译生成的.elf的转储,我得到的是:

080080e0 <__aeabi_idivmod>:
 80080e0:   e3510000    cmp r1, #0
 80080e4:   0afffff9    beq 80080d0 <.divsi3_skip_div0_test+0x110>
 80080e8:   e92d4003    push    {r0, r1, lr}
 80080ec:   ebffffb3    bl  8007fc0 <.divsi3_skip_div0_test>
 80080f0:   e8bd4006    pop {r1, r2, lr}
 80080f4:   e0030092    mul r3, r2, r0
 80080f8:   e0411003    sub r1, r1, r3
 80080fc:   e12fff1e    bx  lr

另一方面,当我在电路板上运行程序时,如果我使用gdb查看实际的ABI调用代码,我得到:

(gdb) disas __aeabi_idivmod
Dump of assembler code for function __aeabi_idivmod:
   0x080080e0 <+0>:     movs    r0, r0
   0x080080e2 <+2>:     b.n 0x8008788
   0x080080e4 <+4>:         ; <UNDEFINED> instruction: 0xfff90aff
   0x080080e8 <+8>:     ands    r3, r0
   0x080080ea <+10>:    stmdb   sp!, {r0, r1, r4, r5, r7, r8, r9, r10, r11, r12, sp, lr, pc}
   0x080080ee <+14>:            ; <UNDEFINED> instruction: 0xebff4006
   0x080080f2 <+18>:    ldmia.w sp!, {r1, r4, r7}
   0x080080f6 <+22>:    b.n 0x8008100 <__aeabi_ldiv0>
   0x080080f8 <+24>:    asrs    r3, r0, #32
   0x080080fa <+26>:    b.n 0x8008180 <K+120>
   0x080080fc <+28>:    vrhadd.u16  d14, d14, d31
End of assembler dump.

代码的位置对应,但是完全错误:有两条指令甚至不被gdb和第二条指令识别:

0x080080e2 <+2>:        b.n 0x8008788

跳出进程的.text部分,结尾为0x866c:

Loading section .text, size 0x866c lma 0x8000000

关于我做错的任何线索?任何帮助将不胜感激。

编辑:我正在使用这个编译器:https://launchpad.net/gcc-arm-embedded/+download

arm-none-eabi-gcc --version
arm-none-eabi-gcc (GNU Tools for ARM Embedded Processors) 4.8.3 20131129 (release)     [ARM/embedded-4_8-branch revision 205641]

EDIT2(遵循Notlikethat的回复):我用来链接我的程序的命令是:

$(ARMGNU)-ld -o program.gcc.thumb.elf -T memmap vectors.o program.gcc.thumb.o   $(OBJS2)     $(LIBGCC)

memmap是链接器脚本,vectors.o包含启动代码,$(OBJS2)包含必须链接在一起的所有目标文件,$(LIBGCC)是引用包含我们正在讨论的ABI调用的库的变量。根据我对Notlikethat的评论的理解,我应该在这里添加一些选项,强制将libgcc编译为thumb代码而不是normale ARM代码。我试图在链接器中添加这些选项,但在这两种情况下我都遇到了同样的错误:

arm-none-eabi-ld: unrecognised emulation mode: cpu=cortex-m3
Supported emulations: armelf

EDIT3:我只是在这一刻才意识到我的电路板的处理器是cortex-m4f而不是cortex-m3。我认为这不应该有太大的不同。

1 个答案:

答案 0 :(得分:0)

问题在于,默认情况下,您的工具链将其标准库编译为ARM指令 - 由于Cortex-M处理器仅支持Thumb-2 *,因此在尝试使用ARM代码的交互分支时会出错。 / p>

现在,-mthumb选项告诉编译器将你的代码编译成Thumb - 标准库是预编译的,甚至不会进入图片直到链接时间。幸运的是,the readme表示工具链已启用多工具库,因此您可以选择合适的库而无需查找特定于v7-M的工具链。

根据我对multilib内部工作原理的理解,你必须提供它正在寻找的精确魔术组合,在这种情况下可以是:

-mthumb -mcpu=cortex-m4

或:

-mthumb -march=armv7e-m

这将导致GCC为链接器提供一个适当兼容的库而不是默认值(如果您还需要浮点支持,还有文档中列出的其他选项)。

如果您正在使用单独的链接步骤,我相信您需要使用gcc作为链接命令来代替ld以使multilib正常工作 - 这当然是肯定的我在这里的Linaro工具链的情况(它只有双向硬浮/ ARMv4 + soft-float multilib)。


*严格,不完全是Thumb-2