C語(yǔ)言堆棧幀的介紹與創(chuàng)建
什么是堆棧幀?
堆棧幀(stack frame)是一塊堆棧保留區(qū)域,用于存放被傳遞的實(shí)際參數(shù),子程序的返回值、局部變量以及被保存的寄存器。
堆棧幀的創(chuàng)建方法🐱👤【32bit Windows】
(1)被傳遞的實(shí)際參數(shù)。如果有,則壓入堆棧;
(2)當(dāng)子程序被調(diào)用時(shí),使該子程序的返回值壓入堆棧。如果使用寄存器保存返回值,則跳過(guò)此步;
(3)子過(guò)程返回地址入棧;
(4)子程序開始執(zhí)行時(shí),EBP被壓入堆棧;
(5)設(shè)置EBP等于ESP。從現(xiàn)在開始,EBP就變成了該子程序所有參數(shù)的引用基址;
(6)如果有局部變量,修改ESP以便在堆棧中為這些變量預(yù)留空間;
(7)如果需要保存寄存器,則將它們?nèi)霔#?/p>
我們來(lái)看一段code👇
#include<stdio.h> int print_string(const char * str) { /* EBP被壓入堆棧,對(duì)應(yīng)上述步驟(4) */ //00FE18A0 push ebp /* 設(shè)置EBP等于ESP,對(duì)應(yīng)上述步驟(5) */ //00FE18A1 mov ebp,esp /* 雖然我們沒有局部變量,但是編譯器還是預(yù)留了空間,對(duì)應(yīng)上述步驟(6) */ //00FE18A3 sub esp,0C0h /* 保存寄存器,對(duì)應(yīng)上述步驟(7) */ //00FE18A9 push ebx //00FE18AA push esi //00FE18AB push edi printf("%s\n", str); /* 將printf函數(shù)的入?yún)喝攵褩?*/ //00FE18C1 mov eax,dword ptr [str] //00FE18C4 push eax //00FE18C5 push offset string "%s\n" (0FE7B30h) //00FE18CA call _printf (0FE10CDh) //00FE18CF add esp,8 return 1; /* 使用寄存器存儲(chǔ)返回值 */ //00FE18D2 mov eax,1 } int main() { char* str = "Hello World"; /* 將"Hello World"的地址存在str變量中 */ //00FE1865 mov dword ptr [str],offset string "Hello World" (0FE7B34h) print_string(str); /* 將str 中的值存在eax寄存器中 */ //00FE186C mov eax,dword ptr [str] /* eax壓棧,對(duì)應(yīng)上述步驟(1) */ //00FE186F push eax /* 這里我們使用寄存器存儲(chǔ)返回值,所以沒有步驟(2) */ /* call指令會(huì)自動(dòng)將返回地址壓棧,對(duì)應(yīng)上述步驟(3) */ //00FE1870 call _print_string (0FE13B1h) /* 清空 print_string函數(shù)的入?yún)⒖臻g */ //00FE1875 add esp,4 return 0; //00FE1878 xor eax,eax }
我們?cè)偻ㄟ^(guò)一張圖來(lái)解釋一下:
//我們的匯編code如下 print_string PROC push ebp // 保存基址寄存器 mov ebp,esp // 堆棧幀基址 push ecx push edx // 保存寄存器 mov eac,[ebx+8] // 取堆棧參數(shù) . . pop edx // 恢復(fù)被保存的寄存器 pop ecx pop ebp // 恢復(fù)基址指針 ret // 清除堆棧 print_string ENDP
函數(shù)print_string() 對(duì)應(yīng)的堆棧幀如下圖👇
總結(jié)
到此這篇關(guān)于C語(yǔ)言堆棧幀的文章就介紹到這了,更多相關(guān)C語(yǔ)言堆棧幀內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
C++使用sort對(duì)容器排序的實(shí)現(xiàn)
C++ STL 標(biāo)準(zhǔn)庫(kù)中的sort()函數(shù)專門用來(lái)對(duì)容器或普通數(shù)組中指定范圍內(nèi)的元素進(jìn)行排序,本文就詳細(xì)的介紹一下怎么實(shí)現(xiàn),需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2021-05-05利用Matlab實(shí)現(xiàn)圖像亮度分布統(tǒng)計(jì)圖
這篇文章主要介紹了如何利用Matlab實(shí)現(xiàn)圖像亮度分布統(tǒng)計(jì)圖的繪制,文中的示例代碼講解詳細(xì),對(duì)我們學(xué)習(xí)Matlab有一定的幫助,感興趣的可以了解一下2022-05-05C語(yǔ)言中fopen()函數(shù)的使用方法示例詳解
這篇文章主要介紹了C語(yǔ)言中fopen()函數(shù)的使用方法,本文結(jié)合實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2023-06-06C++ 中消息隊(duì)列函數(shù)實(shí)例詳解
這篇文章主要介紹了C++ 中消息隊(duì)列函數(shù)實(shí)例詳解的相關(guān)資料,需要的朋友可以參考下2017-06-06VScode搭建OpenCV環(huán)境的詳細(xì)步驟
用vscode來(lái)寫opencv代碼需要自己編譯OpenCV,主要用到MinGW-w64和CMake工具。接下來(lái)通過(guò)本文給大家介紹VScode搭建OpenCV環(huán)境的相關(guān)知識(shí),需要的朋友可以參考下2021-11-11