armcm3权威指南笔记----arm编程中地址未对齐方面的影响

P152当使用C开发程序时,推荐开启CM3的双字对齐管理机制(在NVIC配置与控制寄存器中,把STKALIGN置位),代码形如:

#define NVIC_CCR ((volatile unsigned long *)(0xE000ED14))

*NVIC_CCR = *NVIC_CCR | 0x200; //设置STKALIGN

STKALIGN 的名词解释P306

在响应异常的自动入栈操作时,强制SP对齐到双字地址上(为什么要设置STKALIGN,是因为即使保证栈初始是8字节对齐的,编译器也只能保证在调用sprintf那个时刻栈是8字节对齐的但不能保证任意时刻栈都是8字节对齐的,如果恰巧在MSP没有8字节对齐的时刻发生了中断,而中断中又调用了sprintf,这种情况下仍会出错

)。修订版
0无此功能 ,位于配置与控制寄存器0xE000_ED14中。

 

这是用于确保系统能严格遵守AAPCS过程调用标准,个中细节请参阅第12章P181

上面这段话专门有我的book子目录下armcm3项目资料子目录里的Cortex M3内核版本和堆栈8字节对齐对uT-Kernel内核移植的影响资料,可以看一下。

ut-kernel中也有在创建任务时,或者

knl_setup_context强制将栈8字节对齐。

       ssp = tcb->isstack;

 

       /* 8 Byte align ( stack ) */

       if ( ((UW)ssp & 0x7) != 0 ) {

              ssp = (SStackFrame*)((UW)(ssp)-0x4);

       }

 

因为之前栈已经是4字节对齐了,所以这个地方做这个操作就可以保证它是8字节对齐了。

 为什么ut-kernel要在创建新任务时保持任务栈的8字节对齐啊?因为如果我们保证了栈初始的时候是8字节对齐的,那么编译器可以保证以后调用浮点库时堆栈仍是8字节对齐的。而调用浮点库函数如在程序中执行以下语句:

sprintf(buf,"%.3f\n\r",fff);前,栈没八字节对齐的话,屏幕上显示打印的浮点数据不正确。

R13MSP,PSP的使用:R13总是32位的。但是在CM3中,末2位被强制为0。因此,如果偶尔遇到使用R13作为基址的场合(强烈反对使用),必须更改代码,因为末2位的信息已经丢失了。 P251

 

还有个对ARM对齐思想的认识:

在这个例子里,我们使用了.ascii和.byte指示字来创建一个零结尾的字符串。在定义了字符串之后,我们又使用了.align来确保下一条指令会以正确的位置开始。如果不使用.align,汇编器则可能把下一条指令放到未对齐的地址P259

 

 

双字堆栈对齐方式与异常堆栈帧 P241

在缺省情况下,异常堆栈帧会自动对齐到双字存储器位置(修订版2。早期为修订版0/1写的汇编程序,如果要通过堆栈来把数据传送给异常服务程序,可能会受到影响。为了准确判定堆栈帧的起始位置是否往下挪移了一个字,异常服务例程要先读取入栈PSR的比特9如果不想动旧的程序,也可以手工把STKALIGN比特清除这样就与以前的一样了。与EABI标准兼容的应用程序不会受影响。这些程序通常是C程序,并且使用与EABI兼容的编译器编译

 

你可能感兴趣的:(C/C++编程经验)