我使用GNU gcc(4.8.1429)为ARM构建了一个简单的应用程序(ATsam4LC4B:cortexM4核心,256K闪存):
当达到镜像main()调用(闪存位置0x532)的闪存位置时,问题会引发:
位于那里的指令ldr [pc,#32] ,将r3加载到0x3F565(因此调用原始 main()),而不是预期的0x565 (以便按预期调用镜像 main())。
即使所有包含0x3F ...的寄存器在ldr指令之前归零,也会发生这种情况。
调试器按预期报告PC寄存器为0x534,并且符合步进中的闪存区域。
有人可以向我解释发生了什么事吗?
提前谢谢。
该程序使用[-mthumb -nostdlib -nostartfiles -ffreestanding -msingle-pic-base -mno-pic-data-is-text-relative -mlong-calls -mpoke-function-name]标志进行编译并链接[-Wl, - gc-sections -mcpu = cortex-m4 -Ttext = 0x3f000 -nostdlib -nostartfiles -ffreestanding -Wl,-dead-strip -Wl,-static -Wl, - entry = Reset_Handler -Wl, - -cref -mthumb]标志。链接描述文件定义了rom start = 0。
生成的.lss文件中包含的感兴趣区域(省略的行标记为...):
...
void Reset_Handler(void)
{
...
/* Initialize the relocate segment */
...
/* Clear the zero segment */
...
/* Set the vector table base address */
/* Initialize the C library */
// __libc_init_array();
/* Branch to main function */
main();
3f532: 4b08 ldr r3, [pc, #32] ; (3f554 <Reset_Handler+0x5c>)
3f534: 4798 blx r3
3f536: e7fe b.n 3f536 <Reset_Handler+0x3e>
3f538: 20000000 .word 0x20000000
3f53c: 0003f59c .word 0x0003f59c
3f540: 20000004 .word 0x20000004
3f544: 20000004 .word 0x20000004
3f548: 20000008 .word 0x20000008
3f54c: e000ed00 .word 0xe000ed00
3f550: 0003f000 .word 0x0003f000
3f554: 0003f565 .word 0x0003f565
3f558: 6e69616d .word 0x6e69616d
3f55c: 00 .byte 0x00
3f55d: 00 .byte 0x00
3f55e: bf00 nop
3f560: ff000008 .word 0xff000008
0003f564 <main>:
int main (void)
{
3f564: b510 push {r4, lr}
...
asm("bx %0"::"r"(*(unsigned*)0x3F004 - 0x3F000));
3f580: 4b05 ldr r3, [pc, #20] ; (3f598 <main+0x34>)
3f582: 681b ldr r3, [r3, #0]
3f584: f5a3 337c sub.w r3, r3, #258048 ; 0x3f000
3f588: 4718 bx r3
}
return 0;
}
3f58a: 2000 movs r0, #0
3f58c: bd10 pop {r4, pc}
3f58e: bf00 nop
3f590: e0001000 .word 0xe0001000
3f594: 0003f329 .word 0x0003f329
3f598: 0003f004 .word 0x0003f004
...
答案 0 :(得分:1)
@Notlikethat回答了我的问题。 我很困惑,假设pc + 32地址应该直接加载到r3,而不是这个地址的内容。