ARM Cortex-M3启动文件

时间:2014-06-22 14:11:26

标签: c assembly arm startup cortex-m3

我正在修改ARM Cortex-M3微控制器的启动文件。到目前为止一切正常,但我有一个问题,即需要使用汇编程序代码来执行BSS块的零填充。

默认情况下,启动文件中的重置中断如下所示:

// Zero fill the bss segment.
__asm(  "    ldr     r0, =_bss\n"
        "    ldr     r1, =_ebss\n"
        "    mov     r2, #0\n"
        "    .thumb_func\n"
        "    zero_loop:\n"
        "    cmp     r0, r1\n"
        "    it      lt\n"
        "    strlt   r2, [r0], #4\n"
        "    blt     zero_loop"
);

使用该代码,一切都按预期工作。但是,如果我更改以前的代码,它将停止工作:

// Zero fill the bss segment.
for(pui32Dest = &_bss; pui32Dest < &_ebss; )
{
    *pui32Dest++ = 0;
}

原则上两个代码都应该这样做(用零填充BSS),但是第二个代码由于我无法理解的某些原因而不起作用。我相信.thumb_func指令必须在这里发挥作用,但我不熟悉ARM汇编程序。有什么想法或方向可以帮助我理解吗?谢谢!

编辑:顺便说一下,初始化数据段的代码(例如从Flash复制到RAM)如下所示,效果很好。

// Copy the data segment initializers from flash to SRAM.
pui32Src = &_etext;
for(pui32Dest = &_data; pui32Dest < &_edata; )
{
    *pui32Dest++ = *pui32Src++;
}

编辑:为这两个功能添加了解集代码。

第一个装配看起来像:

  2003bc:   4806        ldr r0, [pc, #24]   ; (2003d8 <zero_loop+0x14>)
  2003be:   4907        ldr r1, [pc, #28]   ; (2003dc <zero_loop+0x18>)
  2003c0:   f04f 0200   mov.w   r2, #0

002003c4 <zero_loop>:
  2003c4:   4288        cmp r0, r1
  2003c6:   bfb8        it  lt
  2003c8:   f840 2b04   strlt.w r2, [r0], #4
  2003cc:   dbfa        blt.n   2003c4 <zero_loop>

第二个装配看起来像:

  2003bc:   f645 5318   movw    r3, #23832  ; 0x5d18
  2003c0:   f2c2 0300   movt    r3, #8192   ; 0x2000
  2003c4:   9300        str r3, [sp, #0]
  2003c6:   e004        b.n 2003d2 <ResetISR+0x6e>
  2003c8:   9b00        ldr r3, [sp, #0]
  2003ca:   1d1a        adds    r2, r3, #4
  2003cc:   9200        str r2, [sp, #0]
  2003ce:   2200        movs    r2, #0
  2003d0:   601a        str r2, [r3, #0]
  2003d2:   9a00        ldr r2, [sp, #0]
  2003d4:   f644 033c   movw    r3, #18492  ; 0x483c
  2003d8:   f2c2 0300   movt    r3, #8192   ; 0x2000
  2003dc:   429a        cmp r2, r3
  2003de:   d3f3        bcc.n   2003c8 <ResetISR+0x64>

1 个答案:

答案 0 :(得分:2)

如果初始堆栈在建议的.bss部分中,您可以从反汇编中看到C代码失败的原因 - 它从堆栈加载当前指针,将增量指针保存回堆栈,将位置归零,然后为下一次迭代重新加载递增的指针。如果你在使用它们时将堆栈的内容归零,那么坏事就会发生。

在这种情况下,启用优化可能会解决它(如果实际尝试,智能编译器应该生成与汇编代码几乎相同)。但更一般地说,在做这样的事情时,考虑坚持使用汇编代码可能更安全,这通常是在C运行时环境以下的级别完成的 - 从C代码引导C环境,期望环境存在已经存在风险,因为你只能希望代码并没有尝试使用尚未设置的任何内容。

快速浏览一下(我并不过分熟悉Cortex-M开发的细节),似乎另一个/另外一个解决方案是调整链接器脚本以将堆栈移动到其他地方。