在經典的組合語言教程中,函式呼叫時堆疊的使用都是著重講解的問題。如今隨著高階語言的越來越完善,單純使用彙編開發的程式已經不多了。但對函式呼叫時堆疊動向的了解仍有助於我們明晰程式的執行流程,從而在程式編寫和除錯的過程中有乙個清晰的思路。
一.呼叫約定
在win32中,有關函式的呼叫主要有兩種約定。
1._stdcall
以__stdcall方式呼叫的函式有以下特徵:
• 引數由右至左壓棧
• 呼叫返回時,堆疊由被調函式調整
2.__cdecl
__cdecl約定是c/c++函式的預設呼叫約定。它有以下特徵:
• 引數由右至左壓棧
• 呼叫返回時,堆疊由呼叫者調整
二.win32函式呼叫過程
1. 壓入引數
這裡依據以上的呼叫方式將呼叫者給出的引數一一壓入堆疊。
2. 壓入斷點
當程式執行到call指令的時候,當前語句的位址作為斷點位址壓入堆疊。
3. 跳轉
eip的值被重新設定為被調函式的起始位址。
4. mov ebp, esp
這裡ebp被用來在堆疊中尋找呼叫者壓入的引數,同時作為呼叫者堆疊指標的乙個備份。在此前還應該執行一條:
push ebp
把ebp中原來的數值儲存。
5. sub esp,n
這裡n是函式內區域性變數的總位元組數加上乙個整數,一般為40。此後esp即為被調函式的堆疊指標了。
6. 初始化esp ~ esp-n之間的n位元組空間
這是對堆疊中已分配給區域性變數使用的記憶體空間的初始化,一般全部設定為0xcc。
7. 順序執行函式內語句。
此時函式的堆疊位於所有區域性變數的記憶體空間之後,二者之間一般有40位元組的隔離帶。
8.返回
為保障呼叫的正常返回,函式內應當保證規範使用堆疊,使即將返回的時候esp的值恢復為執行第一條語句前的狀態。說明白點,就是每一條push都要有相應的pop。
呼叫返回的過程如下:
mov esp, ebp
執行後,esp恢復為呼叫者的堆疊指標,棧頂除斷點位址外,還存有原ebp的值和呼叫時壓入的引數。
然後依次彈出ebp的值和斷點位址。如果是__cdecl約定則直接返**用者,呼叫者將負責調整堆疊,丟棄調先前壓入的引數。如果是__stdcall則這個工作由被調函式來執行。
程式樣例如下:
……0040b8e8 push 1 ;壓入引數
0040b8ea call 00401028 ;呼叫函式
……00401028 jmp 0040b7c0 ;跳轉到函式入口
……0040b7c0 push ebp ;儲存ebp
0040b7c1 mov ebp,esp
0040b7c3 sub esp,44h ;設定函式的堆疊指標,此函式中有4
;位元組的區域性變數
0040b7c6 push ebx
0040b7c7 push esi
0040b7c8 push edi
0040b7c9 lea edi,[ebp-44h]
0040b7cc mov ecx,11h
0040b7d1 mov eax,0cccccccch
0040b7d6 rep stos dword ptr [edi] ;初始化區域性變數空間
0040b7d8 mov eax,dword ptr [ebp+8]
0040b7db mov dword ptr [ebp-4],eax
……0040b7de pop edi ;彈出曾壓棧的資料
0040b7df pop esi
0040b7e0 pop ebx
0040b7e1 mov esp,ebp ;恢復呼叫者的堆疊
0040b7e3 pop ebp ;彈出原ebp值
0040b7e4 ret 4 ;返回並將堆疊向上調整4位元組。
;此處為__stdcall約定,所以由函式調
;整堆疊
相應的c**如下:
void __stdcall fun(int);
int main(void)
void __stdcall fun(int para)
UWP 呼叫Win32 關機
原文 uwp 呼叫win32 關機 話說最近程式需要個晚上自動關機的功能 原則上 uwp 應該是沒有關機許可權的 上網搜尋之 有人說只要這樣就可以了 var psi new processstartinfo shutdown s t 0 psi.createnowindow true psi.use...
Win32應用程式入口函式
include int winapi winmain hinstance hinstance,hinstance hprevinstance,lpstr lpcmdline,int ncmdshow 1.windows.h是開發window應用程式必須要包含 2.hinstance是當前程式例項控制...
C開發win32程式
1,先建立乙個空的win32工程,再建立乙個c 原始檔到此工程 2,編輯原始檔 include 標頭檔案宣告 int winapi winmain hinstance hinstance,hinstance hprevinstance,pstr szcmdline,int icmdshow 主函式為...