摘要:當(dāng)函數(shù)返回時(shí),系統(tǒng)棧會(huì)彈出該函數(shù)所對(duì)應(yīng)的棧幀。四寄存器與函數(shù)棧幀每一個(gè)函數(shù)獨(dú)占自己的棧幀空間。棧幀調(diào)整具體包括。
棧是函數(shù)執(zhí)行的內(nèi)存區(qū)域,是C語(yǔ)言運(yùn)行時(shí)最重要的元素之一
寄存器是CPU內(nèi)部用來(lái)存放數(shù)據(jù)的一些小型存儲(chǔ)區(qū)域,用來(lái)暫時(shí)存放參與運(yùn)算的數(shù)據(jù)和運(yùn)算結(jié)果。
寄存器有eax,ebx,ecx,edx,還有ebp,esp。本文主要介紹最后兩個(gè),由于寄存器不是本次博客的重點(diǎn),其他請(qǐng)自行了解!
ESP | 棧指針寄存器(extended stack pointer),其內(nèi)存放著一個(gè)指針,該指針永遠(yuǎn)指向系統(tǒng)棧最上面一個(gè)棧幀的棧頂 |
---|---|
EBP | 基址指針寄存器(extended base pointer),其內(nèi)存放著一個(gè)指針,該指針永遠(yuǎn)指向系統(tǒng)棧最上面一個(gè)棧幀的底部 |
想要了解函數(shù)棧幀,就必須先了解好這兩個(gè)地址。
ebp,esp這兩個(gè)寄存器中存放的是地址,且這兩個(gè)地址是用來(lái)維護(hù)函數(shù)棧幀的
棧區(qū):
用于動(dòng)態(tài)地存儲(chǔ)函數(shù)之間的調(diào)用關(guān)系,以保證被調(diào)用函數(shù)在返回時(shí)恢復(fù)到母函數(shù)中繼續(xù)執(zhí)行。
棧的最常見操作有兩種:
壓棧(push)
彈棧(pop)
用于標(biāo)識(shí)棧的屬性也有兩個(gè):
棧頂(top)
棧底( base)。
什么意思?
可以把棧想象成一摞撲克牌。
push | 為棧增加一個(gè)元素的操作叫做推,相當(dāng)于在這摞撲克牌的最上面再放上一張。 |
---|---|
pop | 從棧中取出一個(gè)元素的操作叫做流行,相當(dāng)于從這摞撲克牌取出最上面的一張。 |
pop | 從棧中取出一個(gè)元素的操作叫做流行,相當(dāng)于從這摞撲克牌取出最上面的一張。 |
---|---|
base | 標(biāo)識(shí)棧底位置,它記錄著撲克牌最下面一張的位置。base用于防止??蘸罄^續(xù)彈棧(牌發(fā)完時(shí)就不能再去揭了)。很明顯,一般情況下,base是不會(huì)變動(dòng)的。 |
以下面代碼為例:
#define _CRT_SECURE_NO_WARNINGS 1#include int Add(int x, int y){ int z = 0; z = x + y; return z;}int main(){ int a = 10; int b = 20; int c = 0; c = Add(a, b); printf("%d/n", c); return 0;}
當(dāng)中央處理器在執(zhí)行調(diào)用Add函數(shù)的時(shí)候,會(huì)從代碼區(qū)中
主要函數(shù)對(duì)應(yīng)的機(jī)器指令的區(qū)域跳轉(zhuǎn)到Add函數(shù)對(duì)應(yīng)的機(jī)器指令區(qū)域,在那里取指并執(zhí)行;當(dāng)Add函數(shù)執(zhí)行完閉,需要返回的時(shí)候,又會(huì)跳回到主要函數(shù)對(duì)應(yīng)的指令區(qū)域,緊接著調(diào)用Add后面的指令繼續(xù)執(zhí)行主要函數(shù)的代碼。
如下圖:
那么中央處理器是怎么知道要去Add函數(shù)的代碼區(qū)取指,
在執(zhí)行完Add后又是怎么知道跳回到主要函數(shù)(而不是其他未知的代碼區(qū))的呢?
這是因?yàn)?/p>
當(dāng)函數(shù)被調(diào)用時(shí),系統(tǒng)棧會(huì)為這個(gè)函數(shù)開辟一個(gè)新的棧幀,并把它壓入棧中。這個(gè)棧幀中的內(nèi)存空間被它所屬的函數(shù)獨(dú)占,正常情況下是不會(huì)和別的函數(shù)共享的。當(dāng)函數(shù)返回時(shí),系統(tǒng)棧會(huì)彈出該函數(shù)所對(duì)應(yīng)的棧幀。
每一個(gè)函數(shù)獨(dú)占自己的棧幀空間。當(dāng)前正在運(yùn)行的函數(shù)的棧幀總是在棧頂。
函數(shù)棧幀:
esp和ebp之間的內(nèi)存空間為當(dāng)前棧幀,esp標(biāo)識(shí)了當(dāng)前棧幀的頂部,ebp標(biāo)識(shí)了當(dāng)前棧幀的底部。
函數(shù)調(diào)用大致包括以下幾個(gè)步驟。
(1)參數(shù)入棧:將參數(shù)從右向左依次壓入系統(tǒng)棧中。 (2)返回地址入棧:將當(dāng)前代碼區(qū)調(diào)用指令的下一條指令地址壓入棧中,供函數(shù)返回時(shí)繼續(xù)執(zhí)行。
(3)代碼區(qū)跳轉(zhuǎn):處理器從當(dāng)前代碼區(qū)跳轉(zhuǎn)到被調(diào)用函數(shù)的入口處。
(4)棧幀調(diào)整:具體包括。保存當(dāng)前棧幀狀態(tài)值,已備后面恢復(fù)本棧幀時(shí)使用(ebp入棧);將當(dāng)前棧幀切換到新棧幀(將esp值裝入ebp,更新棧幀底部);給新棧幀分配空間(把esp減去所需空間的大小,抬高棧頂);
將上面的代碼轉(zhuǎn)到反匯編模式查看
對(duì)應(yīng)觀察:
1.函數(shù)返回過程
(1)保存返回值:通常將函數(shù)的返回值保存在寄存器EAX中。
(2)彈出當(dāng)前棧幀,恢復(fù)上一個(gè)棧幀。
1.在堆棧平衡的基礎(chǔ)上,給esp加上棧幀的大小,降低棧頂,回收當(dāng)前棧幀的空間。
2.將當(dāng)前棧幀底部保存的前棧幀ebp值彈入ebp寄存器,
復(fù)出上一個(gè)棧幀。
3.將函數(shù)返回地址彈給ebi寄存器。
(3)跳轉(zhuǎn):按照函數(shù)返回地址跳回母函數(shù)中繼續(xù)執(zhí)行。
本文內(nèi)容來(lái)自于《oday安全軟件漏洞分析技術(shù)》第2版與自己學(xué)習(xí)筆記所,本文僅記述自己學(xué)習(xí)歷程與僅供自己學(xué)習(xí),復(fù)習(xí)用,不做任何商業(yè)用途。
若有興趣深入了解函數(shù)棧幀,請(qǐng)自行查閱王清主編的《Oday安全:軟件漏洞分析技術(shù)(第2版)》一書。
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/121674.html
摘要:這里分塊講解六函數(shù)棧幀的銷毀過程一解析的作用是將棧頂?shù)臄?shù)據(jù)彈出,彈出數(shù)據(jù)儲(chǔ)存到相應(yīng)寄存器中。 ?前言? 讀完這篇博客,你可以明白什么? ①局部變量到底是怎么在棧上創(chuàng)建的? ②為什么局部變量不初始化為隨機(jī)值? ③函數(shù)是怎么傳參的?傳參的先后順序是什么? ④形參和實(shí)參是什么關(guān)系? ⑤函數(shù)調(diào)用是怎...
摘要:是那些可能在虛擬機(jī)正常運(yùn)行期間拋出的異常的超類。運(yùn)行時(shí)異常定義及其子類都被稱為運(yùn)行時(shí)異常。對(duì)于語(yǔ)言中的關(guān)鍵字和,虛擬機(jī)中并沒有特殊的字節(jié)碼指令去支持它們,都是通過編譯器生成字節(jié)碼片段以及不同的異常處理器來(lái)實(shí)現(xiàn)。 前言 在一些傳統(tǒng)的編程語(yǔ)言,如C語(yǔ)言中,并沒有專門處理異常的機(jī)制,程序員通常用方法的特定返回值來(lái)表示異常情況,并且程序的正常流程和異常流程都采用同樣的流程控制語(yǔ)句。Java語(yǔ)言...
摘要:函數(shù)棧幀的銷毀匯編語(yǔ)言了解函數(shù)傳參函數(shù)返回值如何返回函數(shù)中變量如何初始化和賦值函數(shù)執(zhí)行結(jié)束后系統(tǒng)進(jìn)行了什么操作 文章目錄 一、什么是函數(shù)棧幀 1.寄存器2.函數(shù)棧幀3.棧幀的作用和維護(hù)4.棧幀結(jié)構(gòu)二、函數(shù)棧幀的創(chuàng)建? 1.匯編2.main函數(shù)3.Add函數(shù)的創(chuàng)建三、函數(shù)...
閱讀 2077·2021-11-24 09:39
閱讀 795·2021-09-30 09:48
閱讀 986·2021-09-22 15:29
閱讀 2421·2019-08-30 14:17
閱讀 1895·2019-08-30 13:50
閱讀 1351·2019-08-30 13:47
閱讀 989·2019-08-30 13:19
閱讀 3427·2019-08-29 16:43