0

我正在尝试在裸机架构(带有 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

正在跳出以 0x866c 结束的进程的 .text 部分:

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 调用的库的变量。根据我从 Notlike 的评论中了解到的情况,我应该在这里添加一些选项,以强制将 libgcc 编译为拇指代码而不是普通的 ARM 代码。我试图将这些选项添加到链接器中,但在这两种情况下我都会遇到相同的错误:

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

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

4

1 回答 1

0

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

现在,该-mthumb选项告诉编译器将您的代码编译为 Thumb - 标准库是预编译的,甚至在链接时才出现。幸运的是,自述文件说工具链启用了多库,因此您可以选择合适的库而无需查找特定于 v7-M 的工具链。

根据我对 multilib 内部工作原理的了解,您必须提供它正在寻找的选项的确切神奇组合,在这种情况下,可以是:

-mthumb -mcpu=cortex-m4

或者:

-mthumb -march=armv7e-m

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

如果您使用的是单独的链接步骤,我相信您需要使用gccas 链接命令代替ldmultilib 正常工作 - 我在这里拥有的 Linaro 工具链肯定是这种情况(它只有双向硬浮点/ARMv4+soft-float 多库)。


* 严格来说,不是所有的 Thumb-2

于 2014-06-23T19:45:24.043 回答