系統堆疊的作業原理
1.記憶體的不同用途
簡單來說,緩沖區溢位就是在大緩沖區的資料復制到小緩沖區中,由于沒注意小緩沖區的邊界,”撐爆“了小緩沖區,從而沖掉了小緩沖區相鄰記憶體區域的資料,
根據不同的作業系統,一個行程可能被分配到不同記憶體區域中去執行,但是不管什么樣的系統,什么計算機架構,行程使用的記憶體都可以按照功能分為4部分:
代碼區:可執行指令
資料區:用于存盤全域變數
堆區: 行程可以在堆區動態的請求一定大小的記憶體,并在用完之后歸還給堆區,動態分配和回收是堆區的特點
堆疊區: 用于動態的存盤函式之間的呼叫關系,以保證被呼叫函式回傳時恢復到母函式中繼續執行
這只是簡單的記憶體劃分,如果想了解關于記憶體更詳細的論述,請參考《深入理解計算機系統》,windows下,PE檔案代碼段中包含的二進制機器代碼會被裝入記憶體的代碼區,處理器將到這里一條一條的取出指令和運算元,送入算術邏輯單元運算,如果代碼請求開辟動態記憶體,則會在記憶體的堆區分配一塊區域回傳給代碼區的代碼使用,當函式呼叫發生時,函式的呼叫關系等資訊會動態的保存在堆疊區,
程式中所使用的緩沖區可以是在堆區、堆疊區、資料區,不同地方的緩沖區利用方法不同,
2.堆疊與系統堆疊
堆疊是一種資料結構,是一種先進后出的資料表,用于標識堆疊的屬性兩個:堆疊頂、堆疊底 ,記憶體中的堆疊區指的就是系統堆疊,由系統自動維護,
3.函式呼叫時發生了什么
請看如下C代碼:
int B(int b1,int b2){ int var_b1=b1+b2; int var_b2=b1-b2; return var_b1*var_b2; } int A(int a1,int a2){ int var_a1; var_a=B(a1,a2)+a1; return a1; } int main(int argc,char **argv,char **envp){ int var_main; var_main=A(4,3); return var_main; }
根據作業系統的不同、編譯器和編譯選項的不同,同一檔案不同函式的代碼在記憶體代碼區中的分布可能相鄰,也可能不相鄰,可能有先后順序,也可能沒有,但他們都是在代碼所映射的節里
函式呼叫時,伴隨的系統堆疊中的操作如下:
在main函式呼叫A的時候,首先在自己的堆疊幀中壓入函式回傳地址,然后位A創建新堆疊幀并壓入系統堆疊 ,
在函式A呼叫B的時候,同樣先在自己的堆疊幀中壓入回傳地址,然后為B創建新堆疊幀并壓入系統堆疊
B回傳時,B的堆疊幀被彈出系統堆疊,A堆疊幀的回傳地址被露在堆疊頂,處理器跳到回傳地址處執行
在A回傳時,A的堆疊幀被彈出系統堆疊,main函式堆疊幀中的回傳地址被露在堆疊頂,處理器跳到回傳地址執行
4.暫存器與函式堆疊幀
每一個函式獨占自己的堆疊幀空間,當前正在運行的函式總是在堆疊頂,win32系統提供兩個暫存器用于標識位于系統堆疊頂端的堆疊幀
ESP:堆疊指標暫存器,存放一個指標,該指標永遠指向系統堆疊最上面的堆疊幀的堆疊頂
EBP:基址指標暫存器,該指標永遠指向系統堆疊最上面的堆疊幀的底部
函式堆疊幀:ESP和EBP之間記憶體空間為當前堆疊幀
在函式堆疊幀中一般包含以下幾種資訊:、
區域變數:為函式舉報變數開辟的記憶體空間
堆疊幀狀態值:保存前堆疊幀的頂部和底部(實際上只保存前堆疊幀的底部,前堆疊幀的頂部可以通過堆疊平衡得到)
函式回傳地址:保存當前函式呼叫前的“斷點”資訊,也就是函式呼叫前的指令位置
函式堆疊幀的大小不固定,一般和區域變數的多少有關
5.函式呼叫約定與相關指令
呼叫約定描述了函式傳遞引數的方式和堆疊協同作業的技術細節,下面列出幾種呼叫方式:
C Syscall Stdcall BASIC FORTRAN PASCAL
引數入堆疊順序 右→左 右→左 右→左 左→右 左→右 左→右
誰恢復堆疊平衡 母函式 子函式 子函式 子函式 子函式 子函式
對于Visual C++,支持3種函式呼叫約定:
呼叫約定宣告 引數入堆疊順序 誰恢復堆疊平衡
__cdecl 右→左 母函式
__fastcall 右→左 子函式
__stdcall 右→左 子函式
除了入堆疊方向和恢復平衡不同之外,引數傳遞有時也會有所不同,例如,每一個C++類成員函式都有一個this指標,在windows下,這個指標保存在ECX中
,但如果用GCC編譯,這個指標會作為最后一個引數入堆疊
函式呼叫大致包括以下幾個步驟:
引數入堆疊
回傳地址入堆疊
代碼區跳轉
堆疊幀調整:具體包括
保存當前堆疊幀狀態值(push ebp)
將當前堆疊幀切換到新堆疊幀(mov ebp,esp)
給新堆疊幀分配空間(把ESP減去所需空間大小,抬高堆疊頂)
函式回傳大致包括以下幾個步驟:
保存回傳值(通常保存在EAX中)
彈出當前堆疊幀,恢復上一個堆疊幀:具體包括
在堆疊平衡的基礎上給ESP加上堆疊幀的大小,降低堆疊頂,回收當前堆疊幀空間
將當前堆疊幀底部保存的前堆疊幀EBP值彈入EBP,恢復出上一個堆疊幀
將函式回傳地址彈給EIP
跳轉
轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/5359.html
標籤:其他
上一篇:單詞chalchiguite硬玉chalchiguite英語
下一篇:nginx配置訪問本地靜態資源
