[英]Why is SP (apparently) stored on exception entry on Cortex-M3?
我正在使用带有SysTick中断的TI LM3S811(较旧的Cortex-M3)以10Hz触发。 这是情监侦的内容:
void SysTick_Handler(void)
{
__asm__ volatile("sub r4, r4, #32\r\n");
}
这将生成带有-O0
和带有-O0
-4.9.3的 -fomit-frame-pointer
的以下程序集。 STKALIGN
位为0,因此堆栈是4字节对齐的。
00000138 <SysTick_Handler>:
138: 4668 mov r0, sp
13a: f020 0107 bic.w r1, r0, #7
13e: 468d mov sp, r1
140: b401 push {r0}
142: f1ad 0420 sub.w r4, r4, #32
146: f85d 0b04 ldr.w r0, [sp], #4
14a: 4685 mov sp, r0
14c: 4770 bx lr
14e: bf00 nop
我不明白上面清单中r0
的情况。 特别:
1)好像我们要清除SP的低3位并将其存储在堆栈中。 是为了保持8字节对齐? 或者是别的什么?
2)异常退出程序是否同样令人困惑。 从我对ARM程序集的有限了解来看,它的功能如下: SP = SP + 4;
R0 = SP;
然后将其存储回SP。 在这一阶段之前,似乎都无法撤消这些操作。
3)为什么在无条件分支之后(在0x14E
)有一条nop
指令?
由于您正在使用-O0
,因此您应该期待大量的冗余和无用的代码。 编译器的一般工作方式是完全使用程序中任何地方可能使用的所有东西来生成代码,然后依靠优化器摆脱不必要的事情。
如果启用优化,它将消除堆栈框架(不需要),并且代码将变得更加简单。
ARM Procedure Calling Standard和C ABI期望堆栈的8字节(64位)对齐。 由于在压入/弹出单个字后可能发生中断,因此不能保证堆栈在中断输入时正确对齐。
如果设置了STKALIGN
位(默认值),则会通过有条件地将一个多余的(虚拟)字压入堆栈来强制硬件自动对齐堆栈。
函数上的interrupt
属性告诉gcc,OTOH堆栈可能未对齐,因此它添加了强制对齐的前同步码/后同步码。
因此,两者实际上都是一样的。 一种是硬件,一种是软件。 如果只能使用字对齐的堆栈,则应从函数声明中删除interrupt
属性,并清除STKALIGN
位。
确保这样的“未对齐”堆栈没有问题(我不希望有任何问题,因为这是纯32位CPU)。 OTOH,除非您确实需要确保额外的条件时钟和字(不太可能),否则应保持原样。
警告:根据《 ARM体系结构参考手册》,不建议设置STKALIGN == 0。 简要地说:不要将此位设置为0
!
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.