必須出棧!
你所需要的網站建設服務,我們均能行業靠前的水平為你提供.標準是產品質量的保證,主要從事做網站、網站建設、企業網站建設、手機網站開發、網頁設計、成都品牌網站建設、網頁制作、做網站、建網站。成都創新互聯公司擁有實力堅強的技術研發團隊及素養的視覺設計專才。
aa 和 bb 和c 都是函數內部的局部變量,函數返回后就被釋放,也就是在棧中沒有了,返回后就剩下圖中main()函數所對應的棧結構.
棧只能夠通過出棧來減少棧中數據的個數,從反面來講,如果不出棧,funcA()函數返回后,棧指針還是指向c那,這肯定是不對的,因為函數返回后棧指針就得指向man()的棧結構了。
程序的執行過程可看作連續的函數調用。當一個函數執行完畢時,程序要回到調用指令的下一條指令(緊接call指令)處繼續執行。函數調用過程通常使用堆棧實現,每個用戶態進程對應一個調用棧結構(call stack)。編譯器使用堆棧傳遞函數參數、保存返回地址、臨時保存寄存器原有值(即函數調用的上下文)以備恢復以及存儲本地局部變量。
不同處理器和編譯器的堆棧布局、函數調用方法都可能不同,但堆棧的基本概念是一樣的。
寄存器是處理器加工數據或運行程序的重要載體,用于存放程序執行中用到的數據和指令。因此函數調用棧的實現與處理器寄存器組密切相關。
AX(AH、AL):累加器。有些指令約定以AX(或AL)為源或目的寄存器。輸入/輸出指令必須通過AX或AL實現,例如:端口地址為43H的內容讀入CPU的指令為INAL,43H或INAX,43H。目的操作數只能是AL/AX,而不能是其他的寄存器。 [5]
BX(BH、BL): 基址寄存器 。BX可用作間接尋址的地址寄存器和 基地址寄存器 ,BH、BL可用作8位通用數據寄存器。 [5]
CX(CH、CL):計數寄存器。CX在循環和串操作中充當計數器,指令執行后CX內容自動修改,因此稱為計數寄存器。 [5]
DX(DH、DL):數據寄存器。除用作通用寄存器外,在 I/O指令 中可用作端口 地址寄存器 ,乘除指令中用作輔助累加器。 [5]
2.指針和 變址寄存器
BP( Base Pointer Register):基址指針寄存器。 [5]
SP( Stack Pointer Register): 堆棧指針寄存器 。 [5]
SI( Source Index Register):源變址寄存器。 [5]
DI( Destination Index Register):目的變址寄存器。 [5]
函數調用棧的典型內存布局如下圖所示:
圖中給出主調函數(caller)和被調函數(callee)的棧幀布局,"m(%ebp)"表示以EBP為基地址、偏移量為m字節的內存空間(中的內容)。該圖基于兩個假設:第一,函數返回值不是結構體或聯合體,否則第一個參數將位于"12(%ebp)" 處;第二,每個參數都是4字節大小(棧的粒度為4字節)。在本文后續章節將就參數的傳遞和大小問題做進一步的探討。 此外,函數可以沒有參數和局部變量,故圖中“Argument(參數)”和“Local Variable(局部變量)”不是函數棧幀結構的必需部分。
其中,主調函數將參數按照調用約定依次入棧(圖中為從右到左),然后將指令指針EIP入棧以保存主調函數的返回地址(下一條待執行指令的地址)。進入被調函數時,被調函數將主調函數的幀基指針EBP入棧,并將主調函數的棧頂指針ESP值賦給被調函數的EBP(作為被調函數的棧底),接著改變ESP值來為函數局部變量預留空間。此時被調函數幀基指針指向被調函數的棧底。以該地址為基準,向上(棧底方向)可獲取主調函數的返回地址、參數值,向下(棧頂方向)能獲取被調函數的局部變量值,而該地址處又存放著上一層主調函數的幀基指針值。本級調用結束后,將EBP指針值賦給ESP,使ESP再次指向被調函數棧底以釋放局部變量;再將已壓棧的主調函數幀基指針彈出到EBP,并彈出返回地址到EIP。ESP繼續上移越過參數,最終回到函數調用前的狀態,即恢復原來主調函數的棧幀。如此遞歸便形成函數調用棧。
EBP指針在當前函數運行過程中(未調用其他函數時)保持不變。在函數調用前,ESP指針指向棧頂地址,也是棧底地址。在函數完成現場保護之類的初始化工作后,ESP會始終指向當前函數棧幀的棧頂,此時,若
給你個例子:
#include
//寫好加法,以便調用
int sum(int x1,int x2)
{
int x3=x1+x2;
return x3;
}
void main()
{
int a=0;
int b=0;
int c=0;
printf("請輸入兩個整數\n");
scanf("%d%d",a,b);
c=sum(a,b);//傳遞參數給sum()函數,返回他們的和
printf("%d+%d的和是:%d\n",a,b,c);
}
總之:就是你把一種方法寫到單獨的塊,這里就是sum()函數,執行一個單一的功能,在main函數調用就是了!
其實想知道這些東西,單從C代碼上是看不出什么來的。反匯編后看匯編代碼一清二楚。當一個父函數調用子函數時,在父函數中先將子函數用到的參數壓入堆棧,然后再以一個call指令調用子函數。而call指令其實要做兩件事:將自己的EIP值壓入堆棧;以一個jmp跳轉到子函數代碼的開始位置。而在子函數內,首先就是這樣:
MOV EBP,ESP
SUB ESP,0x100
... ...
也就是要將當前ESP保存到EBP,然后用一個SUB指令開辟子函數所用的局部內存空間。子函數對父函數的參數的引用一般都是EBP+4,EBP+8這樣的,這樣剛好就能訪問父函數壓入堆棧的參數。而對自己申明的參數的訪問,就是EBP-0,EBP-4等等。對匯編不太熟悉的只從C代碼的邏輯上去分析這樣的問題,而實際情況是C代碼要轉換成機器代碼,機器代碼做的一些工作只有在匯編中能看到。堆棧就是一個傳遞參數的內存塊,編譯器在編譯代碼時,自動生成了子函數訪問父函數參數的代碼。
不知道這樣說能不能幫你解決問題。
分享題目:c語言main函數調用棧 c語言在main函數中調用函數
URL標題:http://www.yijiale78.com/article46/ddedphg.html
成都網站建設公司_創新互聯,為您提供面包屑導航、微信小程序、網頁設計公司、外貿建站、域名注冊、用戶體驗
聲明:本網站發布的內容(圖片、視頻和文字)以用戶投稿、用戶轉載內容為主,如果涉及侵權請盡快告知,我們將會在第一時間刪除。文章觀點不代表本網站立場,如需處理請聯系客服。電話:028-86922220;郵箱:631063699@qq.com。內容未經允許不得轉載,或轉載時需注明來源: 創新互聯