1. 程式人生 > >硬體堆疊和軟體堆疊在AVR中的理解

硬體堆疊和軟體堆疊在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