我正在修改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>
答案 0 :(得分:2)
如果初始堆栈在建议的.bss
部分中,您可以从反汇编中看到C代码失败的原因 - 它从堆栈加载当前指针,将增量指针保存回堆栈,将位置归零,然后为下一次迭代重新加载递增的指针。如果你在使用它们时将堆栈的内容归零,那么坏事就会发生。
在这种情况下,启用优化可能会解决它(如果实际尝试,智能编译器应该生成与汇编代码几乎相同)。但更一般地说,在做这样的事情时,考虑坚持使用汇编代码可能更安全,这通常是在C运行时环境以下的级别完成的 - 从C代码引导C环境,期望环境存在已经存在风险,因为你只能希望代码并没有尝试使用尚未设置的任何内容。
快速浏览一下(我并不过分熟悉Cortex-M开发的细节),似乎另一个/另外一个解决方案是调整链接器脚本以将堆栈移动到其他地方。