【问题标题】:unexpected behaviour of ldr [pc, #value]ldr [pc, #value] 的意外行为
【发布时间】:2015-01-24 15:48:15
【问题描述】:

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

  1. 在 0x3F000(链接器选项 -Ttext=0x3F000)加载并初始化,
  2. 在 0 处复制自身(镜像)
  3. 使用程序集跳转到镜像Reset_Handler()(接近0)
  4. 镜像应用程序开始按预期运行

问题在到达镜像 main() 调用的闪存位置(闪存位置 0x532)时引发:

instruction ldr [pc, #32] 在那里加载 r3 0x3F565(因此调用 original main()),而不是预期的 0x565 (以便按预期调用 mirror 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
...

【问题讨论】:

  • 那么,什么实际存储在地址0x3f554/0x554?这就是您要加载到 r3 中的内容,但您还没有显示它。如果它是在链接时计算的符号地址,那么显然您将不得不将其作为重定位的一部分进行修复。
  • 0x0003f565 存储在地址 0x3f554/0x554。谢谢。
  • 可能有类似的问题。 stackoverflow.com/questions/2102921/…

标签: gcc assembly arm


【解决方案1】:

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2021-12-15
    • 1970-01-01
    • 2011-08-25
    • 2014-07-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多