CM3、CM4堆栈双字对齐问题,欢迎
根据AAPCS《ProcedureCall Standard for the ARM? Architecture》规定,堆栈指针必须双字对齐,否则将导致部分严格遵守AAPCS规范的函数出现异常,例证:
#include "stdio.h"
#include "string.h"
__asm __inline void svc_init(void)
{
LDR R0,=0xE000ED14
LDR R1,[R0]
BIC R1,R1,#0x200 //堆栈单字对齐
// ORRR1,R1,#0x200 // 堆栈双字对齐
STR R1,[R0]
MRS R0, MSP // 强制使堆栈单字对齐
SUB R0,R0,#4
MSR MSP,R0
SVC 0
BX LR
}
int main(void)
{
svc_init();
while(1);
}
float fff=1.234;
char buf[128];
void SVC_Handler(void)
{
sprintf(buf,"%.3f\n\r",fff);
while(1);
}
结论:
1. 当堆栈为单字对齐时,将有可能导致lib c这样严格按照AAPCS规范的库函数使用异常。
2. 程序中MSP、PSP的地址应尽量双字对齐(即地址能被8整除)。
由于编译器在后续的反汇编中保证堆栈的双字对齐,但为了应对极端情况,Cortex-M3and Cortex-M4中提供了一种硬件自动补齐功能。用户可以通过将SCB->CCR[9]置1使能此项功能。(缺省为双字对齐),当发生中断时由硬件自动检测堆栈是否双字对齐,如果对齐了,则不进行任何操作,如果没有对齐,则自动将SP减4这样便对齐。同时将xPSR的第9位置位。详细描述如下:
Anotherrequirement of the AAPCS is that the stack pointer value should be double-wordaligned at function entry or exit boundary. As a result, the Cortex-M3 and Cortex-M4processors can insert an additional word of padding space in the stackautomatically if the stack pointer was not aligned to double-word location whenthe interrupt happened. In this way, we can guarantee that the stack pointer willbe at the beginning of the exception handler. This “double-word stack alignment”feature is programmable, and can be turned off if the exception handlers do notneed full AAPCS compliance.
The bit 9of the stacked xPSR is used to indicate if the valueof the stack pointer has been adjusted. In Figure8.2, the stack pointer was aligned to double-word address location,so no padding was inserted and bit 9 of the stack xPSR is set to 0. The samestack frame behavior can also be found when the double-word stack alignmentfeature is turned off, even if the value of stack pointer wasn’t aligned
to double-word boundary.
但在双堆栈模式下:
#include"stdio.h"
#include"string.h"
__asm __inlinevoid svc_init(void)
{
LDR R0,=0xE000ED14
LDR R1,[R0]
// BIC R1,R1,#0x200
ORR R1,R1,#0x200
STR R1,[R0]
MRS R0, MSP
SUB R0,R0,#4
MSR MSP,R0
LDR R0,=0x20001004
MSR PSP,R0
LDR R0,=3
MSR CONTROL,R0
BX LR
}
__asm __inlinevoid svc_call(void)
{
SVC 0
}
int main(void)
{
svc_init();
svc_call();
while(1);
}
float fff=1.234;
char buf[128];
voidSVC_Handler(void)
{
sprintf(buf,"%.3f\n\r",fff);
while(1);
}
进入中断前:(MSP、PSP非双字对齐)
MSP:0x200006E4
PSP :0x20001004
SP :0x20001004
进入中断后:(MSP未补齐,PSP被补齐)
MSP:0x200006E4
PSP :0x20000FE0
SP :0x200016E4
难道双堆栈模式下,需要用户进行手动补齐?求具体补齐方法
看来小编很厉害啊,俺都是写代码,从来没有考虑过这方面的东西,赞一个。
可以给你一个讨论贴http://www.openedv.com/posts/list/11308.htm,,,太深奥我也不是太懂,你参考一下。