<dfn id="yhprb"><s id="yhprb"></s></dfn><dfn id="yhprb"><delect id="yhprb"></delect></dfn><dfn id="yhprb"></dfn><dfn id="yhprb"><delect id="yhprb"></delect></dfn><dfn id="yhprb"></dfn><dfn id="yhprb"><s id="yhprb"><strike id="yhprb"></strike></s></dfn><small id="yhprb"></small><dfn id="yhprb"></dfn><small id="yhprb"><delect id="yhprb"></delect></small><small id="yhprb"></small><small id="yhprb"></small> <delect id="yhprb"><strike id="yhprb"></strike></delect><dfn id="yhprb"></dfn><dfn id="yhprb"></dfn><s id="yhprb"><noframes id="yhprb"><small id="yhprb"><dfn id="yhprb"></dfn></small><dfn id="yhprb"><delect id="yhprb"></delect></dfn><small id="yhprb"></small><dfn id="yhprb"><delect id="yhprb"></delect></dfn><dfn id="yhprb"><s id="yhprb"></s></dfn> <small id="yhprb"></small><delect id="yhprb"><strike id="yhprb"></strike></delect><dfn id="yhprb"><s id="yhprb"></s></dfn><dfn id="yhprb"></dfn><dfn id="yhprb"><s id="yhprb"></s></dfn><dfn id="yhprb"><s id="yhprb"><strike id="yhprb"></strike></s></dfn><dfn id="yhprb"><s id="yhprb"></s></dfn>

新聞中心

EEPW首頁(yè) > 嵌入式系統 > 設計應用 > 單片機編程中關(guān)于堆棧的一些問(wèn)題

單片機編程中關(guān)于堆棧的一些問(wèn)題

作者: 時(shí)間:2013-05-30 來(lái)源:網(wǎng)絡(luò ) 收藏

在生成代碼使用兩個(gè):一個(gè)是用于子程序調用和中斷操作的硬件,一個(gè)是用于以結構傳遞的參數臨時(shí)變量和局部變量的軟件堆棧。硬件堆棧是從數據內存的頂部開(kāi)始分配的,在硬件堆棧下面再分配一定數量的字節作為軟件堆棧。硬件堆棧和軟件堆棧均為向下生長(cháng)型的堆棧(注意:這與51單片機相反)。

通常如果你的程序沒(méi)有子程序調用也不調用象帶有%f 格式的printf()等庫函數,那么默認的16 字節應該在大多數的例子中能良好工作。在絕大多數程序中除了很繁重的遞歸調用程序再入式函數,最多40 個(gè)字節的硬件堆棧應該是足夠的。

如果函數的調用層次太深,有可能會(huì )發(fā)生硬件堆棧溢出到軟件堆棧中,改變了軟件堆棧中數據的內容,同樣,當定義了太多的局部變量或一個(gè)局部集合變量太多也有可能出現軟件堆棧溢出到動(dòng)態(tài)分配的數據區,兩個(gè)堆棧都有可能溢出,如果堆棧溢出,會(huì )引起不可預測的錯誤??梢允褂枚褩z查函數檢測兩個(gè)堆棧是否溢出。

在Target的頁(yè)面中有一個(gè)Return Stack Sizi選項,用于指定硬件堆棧(保存函數返回值)的大小,通常如果子程序調用嵌套不深(不超過(guò)4層),那么使用默認的16字節就足夠了,如果使用了浮點(diǎn)函數,則至少應設定為30個(gè)字節。在一般情況下,除了層次很深的遞歸調用及使用了%f格式說(shuō)明符外,設定為40個(gè)字節就足夠了。

硬件堆棧是從數據內存的頂部開(kāi)始分配的,而軟件堆棧是在它下面一定數量字節處分配。硬件堆棧和數據內存的大小是受在選項中的目標裝置項設定限制的。數據區從0x60 開(kāi)始分配。在IO 空間后面是正確的。允許數據區和軟件堆棧彼此相向生長(cháng)。

如果你選擇的目標裝置帶有32K 或64K 的外部SRAM,那么堆棧是放在內部SRAM的頂部而且向低內存地址方向生長(cháng)。參考程序和數據內存的使用。任意一個(gè)程序失敗的重要原因是堆棧溢出到其它數據內存的范圍,兩個(gè)堆棧中的任意一個(gè)都可能溢出,并且當一個(gè)堆棧溢出時(shí)會(huì )偶然產(chǎn)生壞的事情,你可以使用堆棧檢查函數檢測溢出情況 。

關(guān)于堆棧檢查函數:

啟動(dòng)代碼在硬件堆棧和軟件堆棧的最低字節分別寫(xiě)進(jìn)一個(gè)代碼(0xaa),把這個(gè)代碼稱(chēng)為警戒線(xiàn)。如果硬件堆棧和軟件堆棧如果溢出過(guò),則警戒字節的代碼(0xaa)就會(huì )被改變,堆棧檢查函數就是通過(guò)檢查這兩個(gè)堆棧的最低字節的代碼是否被改變來(lái)判斷兩個(gè)堆棧是否溢出。通過(guò)調用_StackCheck(void)函數來(lái)檢查堆棧溢出,如果警戒線(xiàn)字節中的代碼仍然保持正確的值,那么函數檢查通過(guò),沒(méi)有溢出。如果堆棧溢出,那么警戒線(xiàn)字節將可能被破壞,_StackCheck(void)函數檢查到警戒線(xiàn)判斷字節中的代碼被改變,就判斷相應的堆棧溢出(當程序堆棧溢出,程序可能運行不正?;蚺既槐罎?,該函數再調用函數_StackOverflowed(char c),如果參數是1,那么硬件堆棧有過(guò)溢出;如果參數是0,那么軟件堆棧曾經(jīng)溢出。

在使用堆棧檢查函數時(shí)應注意以下幾點(diǎn):

1、在使用堆棧檢查函數時(shí),前必須用#i nclude "macros.h"預處理。

2、如果使用自己的啟動(dòng)文件,在ICCAVR6.20以后的版中,如果使用的啟動(dòng)文件中沒(méi)有警戒線(xiàn)的內容,ICCAVR也會(huì )自動(dòng)添加警戒線(xiàn)。而在ICCAVR6.20以前的版本中,必須自己添加該部分內容,否則生成的代碼中堆棧分配將不帶警戒線(xiàn)。

3、如果使用動(dòng)態(tài)內存分配,必須跳過(guò)警戒線(xiàn)字節_bss_end來(lái)分配您的堆(即增加一個(gè)字節),詳見(jiàn)內存分配函數說(shuō)明

4、當_StackCheck(void)函數檢測到警戒線(xiàn)字節被改變,則會(huì )調用一個(gè)默認的_StackOverflowed 函數來(lái)跳轉到程序存儲器0的位置(復位向量地址)??梢灾付ɑ蛑匦戮帉?xiě)一個(gè)新的函數來(lái)代替它,例如可以用新函數來(lái)指示是哪個(gè)堆棧溢出等,但這個(gè)函數也不可能執行太多的功能或讓程序恢復到正常狀態(tài)。因為堆棧溢出后,會(huì )更改掉一些有用的數據,引起不可預測的錯誤,甚至使程序死機。

下面用一個(gè)簡(jiǎn)單的實(shí)例來(lái)說(shuō)明堆棧檢查函數的作用:

main( )

{

init( ) //調用初始化程序

float a,b;

a=1.0;

b=1.0;

printf("a = %fn", a);

printf("b = %fn", b);

_StackCheck( ); //調用堆棧檢查函數

}

_StackOverflowed(char c)

{

if (c == 1)

puts("trashed HW stack"); //硬件堆棧溢出

else

puts("trashed SW stack"); //軟件堆棧溢出

}

51單片機相關(guān)文章:51單片機教程




關(guān)鍵詞: 單片機編程 堆棧 編譯器

評論


技術(shù)專(zhuān)區

關(guān)閉
国产精品自在自线亚洲|国产精品无圣光一区二区|国产日产欧洲无码视频|久久久一本精品99久久K精品66|欧美人与动牲交片免费播放
<dfn id="yhprb"><s id="yhprb"></s></dfn><dfn id="yhprb"><delect id="yhprb"></delect></dfn><dfn id="yhprb"></dfn><dfn id="yhprb"><delect id="yhprb"></delect></dfn><dfn id="yhprb"></dfn><dfn id="yhprb"><s id="yhprb"><strike id="yhprb"></strike></s></dfn><small id="yhprb"></small><dfn id="yhprb"></dfn><small id="yhprb"><delect id="yhprb"></delect></small><small id="yhprb"></small><small id="yhprb"></small> <delect id="yhprb"><strike id="yhprb"></strike></delect><dfn id="yhprb"></dfn><dfn id="yhprb"></dfn><s id="yhprb"><noframes id="yhprb"><small id="yhprb"><dfn id="yhprb"></dfn></small><dfn id="yhprb"><delect id="yhprb"></delect></dfn><small id="yhprb"></small><dfn id="yhprb"><delect id="yhprb"></delect></dfn><dfn id="yhprb"><s id="yhprb"></s></dfn> <small id="yhprb"></small><delect id="yhprb"><strike id="yhprb"></strike></delect><dfn id="yhprb"><s id="yhprb"></s></dfn><dfn id="yhprb"></dfn><dfn id="yhprb"><s id="yhprb"></s></dfn><dfn id="yhprb"><s id="yhprb"><strike id="yhprb"></strike></s></dfn><dfn id="yhprb"><s id="yhprb"></s></dfn>