硬體堆疊和軟體堆疊在AVR中的理解
關於棧和堆的一些資料。
首先是從理論上的東西。。網上轉載來的,後面是看AVR程式碼時得出的一些東西。
硬體堆疊:或許也可以稱作系統堆疊,是位於片內RAM區。有人說,只要能使用PUSH,POP指令的微控制器,都可以說含有硬體堆疊。這樣的說法我個人覺得不是很全面。通過指令進行壓棧和出棧操作只是系統堆疊中的一種操做。系統堆疊還可以被隱含呼叫。例如,當呼叫子程式時,系統會主動把返回地址壓入堆疊,並不需要使用者通過指令操作。通常,棧底設在記憶體的高階,也就是把記憶體的最高一段空間劃作棧區。這些都是向下生長棧。棧指標可能是專用的暫存器,也可能借用一通用暫存器。也有微控制器是在資料區裡劃一塊作棧區,可能是向上生長,也可能是向下生長。
硬體堆疊:是通過暫存器SPH,SPL做為索引指標的地址,是呼叫了CALL,RCALL等函式呼叫指令後硬體自動填充的堆疊!
軟體堆疊:是編譯器為了處理一些引數傳遞而做的堆疊,會由編譯器自動產生和處理,可以通過相應的編譯選項對其進行編輯。
簡單一點說,硬體堆疊主要做為地址堆疊用,而軟體堆疊主要會被分配成資料堆疊!
---摘自《AVR微控制器C語言開發入門指導》- P169---
ICCAVR 使用兩個堆疊:一個用於子程式呼叫和中斷操作的硬體堆疊,一個用於傳遞引數、臨時變數和區域性變數的軟體堆疊。可以使用堆疊檢測函式檢測兩個堆疊是否溢位。
如果沒有硬堆疊,你可以選定一個暫存器作堆疊指標,通過軟體實現堆疊操作。移植μC/OS-II也不一定要硬堆疊。ARM就很難說它的堆疊是軟的還是硬的。32位的ARM指令中沒有PUSH、POP指令。ARM習慣上用R13作堆疊指標(SP),但用別的暫存器作堆疊指標也未常不可。ARM習慣上用LDM/STM(多暫存器載入/儲存指令)來操作堆疊,壓多少,按什麼順序都能選擇。應該說ARM是軟硬結合的堆疊
C程式碼(AVR-GCC編譯,優化等級-00):
#include <avr/io.h>
int add(int a,int b)
{
int c;
c=a+b;
returnc;
}
int main(void)
{
inta=2,b=3,c=0;
c=add(a,b);
//c=sub(a,b);
}
彙編程式碼:
(省略一些boot程式碼)
。。。。。。。
00000054 <__ctors_end>:
54: 1124 eor r1,r1
56: 1fbe out 0x3f,r1 ;63
58: cfe5 ldi r28,0x5F ;95 //此處Y指標和SP都指到了SRAM最高階
5a: d4e0 ldi r29,0x04 ;4
5c: debf out 0x3e,r29 ;62
5e: cdbf out 0x3d,r28 ; 61
。。。
0000008e <add>:
#include <avr/io.h>
int add(int a,int b)
{
8e: cf93 push r28
90: df93 push r29 //儲存了Y指標,此時SP已經-2,這裡再減2
92: cdb7 in r28,0x3d ;61 //重新定位Y指標跟SP一樣。
94: deb7 in r29,0x3e ;62
96: 2697 sbiw r28,0x06 ;6 //減掉6,即向下開了6位元組的區域,存放3變數
98: 0fb6 in r0,0x3f ;63
9a: f894 cli
9c: debf out 0x3e,r29 ;62
9e: 0fbe out 0x3f,r0 ; 63
a0: cdbf out 0x3d,r28 ;61
a2: 9a83 std Y+2,r25 ;0x02
a4: 8983 std Y+1,r24 ;0x01
a6: 7c83