繁体   English   中英

为什么将SP(显然)存储在Cortex-M3的异常条目上?

[英]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 ,因此您应该期待大量的冗余和无用的代码。 编译器的一般工作方式是完全使用程序中任何地方可能使用的所有东西来生成代码,然后依靠优化器摆脱不必要的事情。

  1. 是的,这是在进行8字节对齐。 即使您没有局部变量,它也分配一个堆栈框架来容纳局部变量。
  2. 出口是相反的,取消分配堆栈帧。
  3. 最后的nop是在代码中保持4字节对齐,因为您有时可能希望与非拇指代码链接。

如果启用优化,它将消除堆栈框架(不需要),并且代码将变得更加简单。

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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM