将堆栈指针与ARM组件中的4字节对齐8字节
如何将堆栈指针对齐到8字节,现在在ARM中对齐4字节。根据我的理解,如果堆栈指针指向某个地址(如0x4,0x8,0x12和0x16等),则堆栈指针为4字节对齐。
因此,将堆栈指针与8字节对齐意味着它应指向0x8,0x16,0x24和0x32等地址,依此类推。
现在我如何将4字节堆栈指针与8字节对齐指针对齐?
由于堆栈减少
bic sp, sp, #7
应该足够了。 使用EABI,您可以使用r12
或r0-r3
(重新)存储先前的值。
所有这一切只能在集会中完成; 在C中你可以依赖正确对齐的堆栈指针并尝试更改它可能会导致程序崩溃。
编译器注意正确对齐; 调用中断时可能会发生未对齐的堆栈。 某些CPU(例如Cortex-M3)具有特殊寄存器(STKALIGN),可用于输入具有8位堆栈对齐的irq。
不要尝试自己手动对齐sp
,而是push
一个寄存器以获得对齐。 例如,而不是
push {r3, r4, lr}
在列表中再添加一个寄存器,以便轻松地与8对齐。
push {r1, r3, r4, lr}
这可能感觉像额外的内存访问,但通常缓存使用比本机字大小更宽的位向量。
另外需要注意的是,如果您不进行外部呼叫或接收,则无需强制自己进行堆栈对齐。 因此,如果你有一个封闭的盒子组装例程,它不会调用外部世界或者接收一些东西,只要它不会咬你自己的负载就可以使用破坏的堆栈对齐。
要将指针移动到最近的8字节边界,但如果它已经是8的倍数,则保持不变(伪代码 – 如果在C中执行此操作,则需要添加一些强制转换):
p = (p + 7) & ~7;
或类似地将其向下移动到最近的8字节边界:
p = p & ~7;
如果您正在编写叶函数(没有子程序调用),请不要打扰。
对于4字节对齐的SP,你完全没问题,因为这个要求是由于ldrd和strd指令需要地址是8的倍数。 因此,如果您正在编写的函数没有调用任何您不知道的子例程,则根本不需要这样做。 (无论如何,ldrd和strd很少使用)
无论如何,当您从更高级别的语言调用函数时,SP已经是8字节对齐的。
如果您希望SP为8字节对齐,请不要触摸它,或仅保留偶数个寄存器。