我正在为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复制)的代码如下所示,并且工作正常。
// 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>发布于 2014-06-22 16:56:31
如果初始堆栈按建议位于.bss部分,您可以从反汇编中看到C代码失败的原因--它正在从堆栈加载当前指针,将增量指针保存回堆栈,对位置进行归零,然后为下一次迭代重新加载增量指针。如果在使用堆栈时将堆栈的内容调零,就会发生不好的事情。
在这种情况下,打开优化可能会修复它(智能编译器在实际尝试时应该生成与程序集代码几乎相同的内容)。不过,更普遍的情况是,在执行通常在C运行时环境以下的级别时,考虑坚持使用汇编代码可能更安全一些--从C代码中引导C环境,而C代码期望环境已经存在,充其量是有风险的,因为您只能希望代码不会尝试使用尚未设置的任何内容。
快速浏览一下(我不太熟悉Cortex-M开发的具体细节)之后,似乎有一种替代的/额外的解决方案可能正在调整链接器脚本,以便将堆栈移到其他地方。
https://stackoverflow.com/questions/24352082
复制相似问题