ldr的意外行为[pc,#value]

时间:2014-11-26 10:44:20

标签: gcc assembly arm

我使用GNU gcc(4.8.1429)为ARM构建了一个简单的应用程序(ATsam4LC4B:cortexM4核心,256K闪存):

  1. 加载0x3F000(链接器选项-Ttext = 0x3F000)并初始化,
  2. 将自己(镜像)复制为0
  3. 使用程序集
  4. 跳转到镜像Reset_Handler()(接近0)
  5. 镜像应用程序开始按预期运行
  6. 当达到镜像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
    ...
    

1 个答案:

答案 0 :(得分:1)

@Notlikethat回答了我的问题。 我很困惑,假设pc + 32地址应该直接加载到r3,而不是这个地址的内容。