基于ARM架構的處理器的C語言程序設計遵循ATPCS(ARM-THUMB procedure call standard)和AAPCS(ARM Application Procedure Call Standard)。ATPCS規(guī)定數(shù)據(jù)棧為FD(滿遞減Full Decrease)類型,并且對數(shù)據(jù)棧的操作是8字節(jié)對齊的。在我自己的輕量級的嵌入式操作系統(tǒng)tqOS中沒有考慮到線程工作棧的8字節(jié)對齊的問題,這樣從內存池中分配到的棧的起始地址可能是4字節(jié)對齊的也可能是8字節(jié)對齊的,如果運氣好每一個線程的棧式8字節(jié)對齊的則不會有什么問題出現(xiàn),如果運氣差線程的棧式4字節(jié)對齊的,那么就會導致種種錯誤......例如,最要命的是在線程函數(shù)中進行浮點數(shù)運算的時候,兩個浮點數(shù)初始化之后打印出來都是錯誤的數(shù)據(jù),進行算術運算之后也是錯誤的結果。因為浮點數(shù)double是8字節(jié)的,可能非8字節(jié)對齊的棧會導致運算出錯。為了解決這個問題,我在tqOS的任務創(chuàng)建函數(shù)中對任務??臻g的分配中做了調整,將棧的起始地址始終設置為8字節(jié)對齊,如果不為8字節(jié)對齊則將棧指針下移至8字節(jié)對齊處。另外,APTCS要求了對棧的操作必須是8字節(jié)對齊的,所以對任務棧的初始化也是有要求的,也就是說一次要入棧兩個數(shù)據(jù),或者說一次要入棧偶數(shù)個數(shù)據(jù),因為一次只入棧一個數(shù)據(jù)(4字節(jié)長度)的話就會導致棧的地址變成非8字節(jié)對齊了,這是不允許的!C語言程序會由ARM的C編譯器會做好8字節(jié)對齊工作,但是涉及匯編和操作系統(tǒng)的時候就需要自己把握好入棧的數(shù)據(jù)問題。為此我把棧初始化函數(shù)里面的一個小小的部分改了一下,就是為了保證初始化完棧之后棧頂指針依然為8字節(jié)對齊的(詳見tqOS的修改版的注釋)。
綜上,程序設計時需要保證棧指針為8字節(jié)對齊,使用操作系統(tǒng)是要保證每個任務的工作棧為8字節(jié)對齊的。詳細信息搜索ATPCS和AAPCS。
引例:http://bbs.elecfans.com/jishu_468500_1_1.html
1. 當堆棧為單字對齊時,將有可能導致lib c這樣嚴格按照AAPCS規(guī)范的庫函數(shù)使用異常。
2. 程序中MSP、PSP的地址應盡量雙字對齊(即地址能被8整除)。
由于編譯器在后續(xù)的反匯編中保證堆棧的雙字對齊,但為了應對極端情況,Cortex-M3and Cortex-M4中提供了一種硬件自動補齊功能。用戶可以通過將SCB->CCR[9]置1使能此項功能。(缺省為雙字對齊),當發(fā)生中斷時由硬件自動檢測堆棧是否雙字對齊,如果對齊了,則不進行任何操作,如果沒有對齊,則自動將SP減4這樣便對齊。同時將xPSR的第9位置位。詳細描述如下:
Another requirement 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 9 of 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.