當前位置:首頁 > 單片機 > 單片機
[導讀]一.為什么要保證堆棧8字節(jié)對齊AAPCS規(guī)則要求堆棧保持8字節(jié)對齊。如果不對齊,調用一般的函數(shù)也是沒問題的。但是當調用需要嚴格遵守AAPCS規(guī)則的函數(shù)時可能會出錯。例如調用sprintf輸出一個浮點數(shù)時,棧必須是8字節(jié)對齊

一.為什么要保證堆棧8字節(jié)對齊
AAPCS規(guī)則要求堆棧保持8字節(jié)對齊。如果不對齊,調用一般的函數(shù)也是沒問題的。但是當調用需要嚴格遵守AAPCS規(guī)則的函數(shù)時可能會出錯。
例如調用sprintf輸出一個浮點數(shù)時,棧必須是8字節(jié)對齊的,否則結果可能會出錯。

實驗驗證:
#include "stdio.h"
#include "string.h"
float fff=1.234;
char buf[128];
int main(void)
{
sprintf(buf,"%.3fnr",fff);//A
while(1);
}

1.在A處設置斷點,讓程序全速運行至A
2.在MDK中修改MSP的值使MSP滿足8字節(jié)對齊
3.全速運行程序,觀察buf中的字符為 1.234 結果正確
4.回到第2步,修改MSP使之只滿足4字節(jié)對齊而不滿足8字節(jié)對齊
5.全速運行程序,觀察buf中的字符為 -2.000 結果錯誤

該實驗證明了調用sprintf輸出一個浮點數(shù)必須要保證棧8字節(jié)對齊。


二.編譯器為我們做了什么
先看一個實驗
#include "stdio.h"
#include "string.h"
float fff=1.234;
char buf[128];

void fun(int a,int b,int c,int d)
{
int v;
v=v;
}
void test(void)
{}

int main(void)
{
fun(1,2,3,4);
test();//A
//sprintf(buf,"%.3fnr",fff);
while(1);
}

0.保證初始的時候堆棧是8字節(jié)對齊的
1.在A處設置斷點
2.全速運行至A,觀察MSP=0x2000025c,沒有8字節(jié)對齊
3.略微修改一下main函數(shù)代碼如下,其他部分代碼不變

int main(void)
{
fun(1,2,3,4);
//test();
sprintf(buf,"%.3fnr",fff);//A
while(1);
}

4.同樣在A處設置斷點
5.全速運行至A,觀察MSP=0x200002d8,這次8字節(jié)對齊了

這個實驗說明了如果編譯器發(fā)現(xiàn)了某個函數(shù)需要調用浮點庫時會自動調整編譯生成的匯編
代碼,從而保證調用這些浮點庫函數(shù)時堆棧是8字節(jié)對齊的。換句話說如果我們保證了棧
初始的時候是8字節(jié)對齊的,那么編譯器可以保證以后調用浮點庫時堆棧仍是8字節(jié)對齊的。

三.os下應該怎樣設置任務堆棧
由上面的討論可知給任務分配棧時需要保證棧是8字節(jié)對齊的,不然在該任務中凡是調用sprintf的函數(shù)
均會出錯,因為棧一開始就是不對齊的。

四.中斷中的棧對齊問題
是否保證了棧初始是8字節(jié)對齊了就萬事大吉了呢。no!大家請看一種特殊的情況:
#include "stdio.h"
#include "string.h"
float fff=1.234;
char buf[128];
void fun(int a,int b,int c,int d)
{
int v;
v=v;
}
int main(void)
{
fun(1,2,3,4);
while(1);
}
void SVC_Handler(void)
{
sprintf(buf,"%.3fnr",fff);//B
}
mian函數(shù)的反匯編如下:
0x080001DC B500 PUSH {lr}
0x080001DE 2304 MOVS r3,#0x04 ;A
0x080001E0 2203 MOVS r2,#0x03
0x080001E2 2102 MOVS r1,#0x02
0x080001E4 2001 MOVS r0,#0x01
0x080001E6 F7FFFFF5 BL.W fun (0x080001D4)
0x080001EA BF00 NOP
0x080001EC E7FE B 0x080001EC

0.保證初始的時候堆棧是8字節(jié)對齊的
1.在A處設置斷點
2.全速運行至A,觀察此時MSP=0x200002e4 未對齊
3.在MDK中將SVC的掛起位置1
4.在B處設置斷點
5.全速運行至B,觀察此時MSP=0x200002b4 未對齊
6.繼續(xù)全速執(zhí)行,觀察buf中的字符為:-2.000 出錯了

這個實驗說明了即使保證棧初始是8字節(jié)對齊的,編譯器也只能保證在調用sprintf那個時刻棧是8字節(jié)對齊的
但不能保證任意時刻棧都是8字節(jié)對齊的,如果恰巧在MSP沒有8字節(jié)對齊的時刻發(fā)生了中斷,而中斷中又調用
了sprintf,這種情況下仍會出錯

五.Cortex-M3內核為我們做了什么
Cortex-M3內核提供了一種硬件機制來解決上述這種中斷中棧不對齊問題。
CM3中可以把NVIC配置控制寄存器的STKALIGN置位,來保證中斷中的棧8字節(jié)對齊,
具體實現(xiàn)過程如下:
當發(fā)生中斷時由硬件自動檢測MSP是否8字節(jié)對齊,如果對齊了,則不進行任何操作,
如果沒有對齊,則自動將MSP減4這樣便對齊了,同時將xPSR的第9位置位來記錄這個
MSP的非正常的變化,在中斷返回若發(fā)現(xiàn)xPSR的第9位是置位的則自動將MSP加4調整
回原來的值。

實驗驗證:
#include "stdio.h"
#include "string.h"
float fff=1.234;
char buf[128];
void fun(int a,int b,int c,int d)
{
int v;
v=v;
}
int main(void)
{
fun(1,2,3,4);
while(1);
}
void SVC_Handler(void)
{
sprintf(buf,"%.3fnr",fff);//B
}
mian函數(shù)的反匯編如下:
0x080001DC B500 PUSH {lr}
0x080001DE 2304 MOVS r3,#0x04 ;A
0x080001E0 2203 MOVS r2,#0x03
0x080001E2 2102 MOVS r1,#0x02
0x080001E4 2001 MOVS r0,#0x01
0x080001E6 F7FFFFF5 BL.W fun (0x080001D4)
0x080001EA BF00 NOP
0x080001EC E7FE B 0x080001EC

1.在A處設置斷點
2.全速運行至A,觀察此時MSP=0x200002e4 未對齊
3.在MDK中將SVC的掛起位置1,同時將0xE000ED14處的值由0x00000000改為0x00000200
(即將NVIC配置控制寄存器的STKALIGN置位)
4.在B處設置斷點
5.全速運行至B,觀察此時MSP=0x200002b0 對齊了
6.觀察中斷返回時的MSP=0x200002e4 調整回來了
7.繼續(xù)全速執(zhí)行,觀察buf中的字符為:1.234 正確

這個實驗說明了將NVIC配置控制寄存器的STKALIGN置位可以保護中斷時棧仍是8字節(jié)對齊


六.總結
綜上所述,為了能夠安全的使用嚴格遵守AAPCS規(guī)則的函數(shù)(比如sprintf)需要做到以下幾點:
1.保證MSP在初始的時候是8字節(jié)對齊的
2.如果用到OS的話需要保證給每個任務分配的棧是保持8字節(jié)對齊的
3.如果用的是基于CM3內核的處理器需將NVIC配置控制寄存器的STKALIGN置位

本站聲明: 本文章由作者或相關機構授權發(fā)布,目的在于傳遞更多信息,并不代表本站贊同其觀點,本站亦不保證或承諾內容真實性等。需要轉載請聯(lián)系該專欄作者,如若文章內容侵犯您的權益,請及時聯(lián)系本站刪除。
換一批
延伸閱讀

9月2日消息,不造車的華為或將催生出更大的獨角獸公司,隨著阿維塔和賽力斯的入局,華為引望愈發(fā)顯得引人矚目。

關鍵字: 阿維塔 塞力斯 華為

加利福尼亞州圣克拉拉縣2024年8月30日 /美通社/ -- 數(shù)字化轉型技術解決方案公司Trianz今天宣布,該公司與Amazon Web Services (AWS)簽訂了...

關鍵字: AWS AN BSP 數(shù)字化

倫敦2024年8月29日 /美通社/ -- 英國汽車技術公司SODA.Auto推出其旗艦產(chǎn)品SODA V,這是全球首款涵蓋汽車工程師從創(chuàng)意到認證的所有需求的工具,可用于創(chuàng)建軟件定義汽車。 SODA V工具的開發(fā)耗時1.5...

關鍵字: 汽車 人工智能 智能驅動 BSP

北京2024年8月28日 /美通社/ -- 越來越多用戶希望企業(yè)業(yè)務能7×24不間斷運行,同時企業(yè)卻面臨越來越多業(yè)務中斷的風險,如企業(yè)系統(tǒng)復雜性的增加,頻繁的功能更新和發(fā)布等。如何確保業(yè)務連續(xù)性,提升韌性,成...

關鍵字: 亞馬遜 解密 控制平面 BSP

8月30日消息,據(jù)媒體報道,騰訊和網(wǎng)易近期正在縮減他們對日本游戲市場的投資。

關鍵字: 騰訊 編碼器 CPU

8月28日消息,今天上午,2024中國國際大數(shù)據(jù)產(chǎn)業(yè)博覽會開幕式在貴陽舉行,華為董事、質量流程IT總裁陶景文發(fā)表了演講。

關鍵字: 華為 12nm EDA 半導體

8月28日消息,在2024中國國際大數(shù)據(jù)產(chǎn)業(yè)博覽會上,華為常務董事、華為云CEO張平安發(fā)表演講稱,數(shù)字世界的話語權最終是由生態(tài)的繁榮決定的。

關鍵字: 華為 12nm 手機 衛(wèi)星通信

要點: 有效應對環(huán)境變化,經(jīng)營業(yè)績穩(wěn)中有升 落實提質增效舉措,毛利潤率延續(xù)升勢 戰(zhàn)略布局成效顯著,戰(zhàn)新業(yè)務引領增長 以科技創(chuàng)新為引領,提升企業(yè)核心競爭力 堅持高質量發(fā)展策略,塑強核心競爭優(yōu)勢...

關鍵字: 通信 BSP 電信運營商 數(shù)字經(jīng)濟

北京2024年8月27日 /美通社/ -- 8月21日,由中央廣播電視總臺與中國電影電視技術學會聯(lián)合牽頭組建的NVI技術創(chuàng)新聯(lián)盟在BIRTV2024超高清全產(chǎn)業(yè)鏈發(fā)展研討會上宣布正式成立。 活動現(xiàn)場 NVI技術創(chuàng)新聯(lián)...

關鍵字: VI 傳輸協(xié)議 音頻 BSP

北京2024年8月27日 /美通社/ -- 在8月23日舉辦的2024年長三角生態(tài)綠色一體化發(fā)展示范區(qū)聯(lián)合招商會上,軟通動力信息技術(集團)股份有限公司(以下簡稱"軟通動力")與長三角投資(上海)有限...

關鍵字: BSP 信息技術
關閉
關閉