您好,登錄后才能下訂單哦!
本篇內容主要講解“C語言堆棧幀的介紹與創建方式”,感興趣的朋友不妨來看看。本文介紹的方法操作簡單快捷,實用性強。下面就讓小編來帶大家學習“C語言堆棧幀的介紹與創建方式”吧!
堆棧幀(stack frame)是一塊堆棧保留區域,用于存放被傳遞的實際參數,子程序的返回值、局部變量以及被保存的寄存器。
(1)被傳遞的實際參數。如果有,則壓入堆棧;
(2)當子程序被調用時,使該子程序的返回值壓入堆棧。如果使用寄存器保存返回值,則跳過此步;
(3)子過程返回地址入棧;
(4)子程序開始執行時,EBP被壓入堆棧;
(5)設置EBP等于ESP。從現在開始,EBP就變成了該子程序所有參數的引用基址;
(6)如果有局部變量,修改ESP以便在堆棧中為這些變量預留空間;
(7)如果需要保存寄存器,則將它們入棧;
我們來看一段code?
#include<stdio.h> int print_string(const char * str) { /* EBP被壓入堆棧,對應上述步驟(4) */ //00FE18A0 push ebp /* 設置EBP等于ESP,對應上述步驟(5) */ //00FE18A1 mov ebp,esp /* 雖然我們沒有局部變量,但是編譯器還是預留了空間,對應上述步驟(6) */ //00FE18A3 sub esp,0C0h /* 保存寄存器,對應上述步驟(7) */ //00FE18A9 push ebx //00FE18AA push esi //00FE18AB push edi printf("%s\n", str); /* 將printf函數的入參壓入堆棧 */ //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; /* 使用寄存器存儲返回值 */ //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壓棧,對應上述步驟(1) */ //00FE186F push eax /* 這里我們使用寄存器存儲返回值,所以沒有步驟(2) */ /* call指令會自動將返回地址壓棧,對應上述步驟(3) */ //00FE1870 call _print_string (0FE13B1h) /* 清空 print_string函數的入參空間 */ //00FE1875 add esp,4 return 0; //00FE1878 xor eax,eax }
我們再通過一張圖來解釋一下:
//我們的匯編code如下 print_string PROC push ebp // 保存基址寄存器 mov ebp,esp // 堆棧幀基址 push ecx push edx // 保存寄存器 mov eac,[ebx+8] // 取堆棧參數 . . pop edx // 恢復被保存的寄存器 pop ecx pop ebp // 恢復基址指針 ret // 清除堆棧 print_string ENDP
函數print_string() 對應的堆棧幀如下圖?
到此,相信大家對“C語言堆棧幀的介紹與創建方式”有了更深的了解,不妨來實際操作一番吧!這里是億速云網站,更多相關內容可以進入相關頻道進行查詢,關注我們,繼續學習!
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。