日本黄色一级经典视频|伊人久久精品视频|亚洲黄色色周成人视频九九九|av免费网址黄色小短片|黄色Av无码亚洲成年人|亚洲1区2区3区无码|真人黄片免费观看|无码一级小说欧美日免费三级|日韩中文字幕91在线看|精品久久久无码中文字幕边打电话

當前位置:首頁 > 單片機 > 單片機
[導讀]一.為什么要保證堆棧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內(nèi)核為我們做了什么
Cortex-M3內(nèi)核提供了一種硬件機制來解決上述這種中斷中棧不對齊問題。
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內(nèi)核的處理器需將NVIC配置控制寄存器的STKALIGN置位

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

數(shù)據(jù)結構是抽象的概念,沒有語言之別,就像是設計模式一樣,是一種抽象的思想,用任何語言的代碼都能構建出來。而我們的python中的字符串,列表,字典,元祖,集合都是基本數(shù)據(jù)類型,他們是依附于語言存在的,不同的語言有不同的基...

關鍵字: 數(shù)組 堆棧

堆棧和隊列在數(shù)據(jù)結構中是最基礎,但同時也是最重要的概念,很多小伙伴對兩者不是很了解,本文就言簡意賅的帶大家了解一下堆棧和隊列。

關鍵字: 堆棧 隊列

隨著嵌入式計算設備基礎硬件性能的提升,在通信、工業(yè)制造、交通運輸?shù)阮I域,嵌入式系統(tǒng)逐漸承擔起更加綜合化和關鍵的任務,這也導致嵌入式軟件在結構愈加復雜的同時,其安全性問題也越來越受到重視。堆棧是嵌入式軟件中的重要存儲結構,...

關鍵字: 嵌入式軟件 堆棧

這些軟件可作為開源和雙重許可提供,并附有大量文檔

關鍵字: 軟件 堆棧 微控制器

隨著越來越多的嵌入式產(chǎn)品連接到外部網(wǎng)絡,嵌入式產(chǎn)品的信息安全性(Security)越來越多地被人們關注。其中既包括直接連接到外部網(wǎng)絡,比如通過Wi-Fi連接;也包括間接連接到外部網(wǎng)絡,比如汽車中的ECU通過CAN總線與T...

關鍵字: IAR Systems 堆棧 嵌入式

運算密度跟不上因特網(wǎng)流量增加速度,數(shù)據(jù)中心分析之數(shù)據(jù)量的成長速度前所未有;要解決這個問題,需要更大的內(nèi)存帶寬,而這是3D芯片堆棧技術展現(xiàn)其承諾的一個領域。

關鍵字: 堆棧 3D芯片 處理器

用C語言進行MCS51系列單片機程序設計是單片機開發(fā)和應用的必然趨勢。Keil公司的C51編譯器支持經(jīng)典8051和8051派生產(chǎn)品的版本,通稱為Cx51。應該說,Cx51是C語言在MCS51單片機上的擴展,既有C語言的共...

關鍵字: MCS51 單片機 堆棧

堆??臻g分配 這部分很重要,如果選擇的單片機RAM比較吃緊,那就要精打細算了。

關鍵字: 堆棧 單片機 RAM

堆棧對于程序來說非常重要,程序能夠快速運行,堆棧起到非常大的作用,但你了解堆棧嗎?

關鍵字: 堆棧 嵌入式
關閉