关于堆栈对齐的问题
程序中出现了一个奇怪的问题
char g_cpTask2Buffer[200];
void Task2(void *arg)
{
...
sprintf(g_cpTask2Buffer,"%.3f", ADCInfoArray[0].m_fVolt);
...
}
ADCInfoArray[0].m_fVolt是一个float值。
在执行完 sprintf 后,无论m_fVolt是多少,始终得到的g_cpTask2Buffer的内容都是"0.000"。
问题的根源竟然是ucos的堆栈需要以8字节对齐。
Task2是一个ucos的任务,Stack2 是Task2的任务堆栈。
如果是以下形式则出错:
Stack20x200084ac Data 804 main.o(.bss)
Stack30x200087d0 Data 800 main.o(.bss)
如果是以下形式则不出错:
Stack20x200084ac Data 800 main.o(.bss)
Stack30x200087cc Data 800 main.o(.bss)
为什么 sprintf在Task2 的中,但是执行结果的正确与否却看起来似乎与Task3的任务堆栈Stack3相关?
原因是,任务 Task2 的堆栈顶实际上位于Stack2 + (Stack2STKSIZE - 1),该值正好与Stack3相连。
为什么堆栈必须要8字节对齐?
因为在汇编中有这样的语句:
BIC r0,r2,#0x07
该句得到double型值(在处理过程中,m_fVolt先从float被转换为double型) 的存储地址。
该汇编的意思是把r2的最低一个字节的二进制最后3位清零,即把r2变为形如16进制xxxxxxx0或者xxxxxxx8,然后放入r0。
可以看到该地址必然是8字节对齐的。