WINAPI識別符號在WINDEF.H定義,語句如下:
#define WINAPI __stdcall
讓我們說說這個__stdcall
stdcall呼叫約定
stdcall很多時候被稱為pascal呼叫約定,因為pascal是早期很常見的一種教學用計算機程式設計語言,其語法嚴謹,使用的函式呼叫約定就是stdcall。在Microsoft C++系列的C/C++編譯器中,常常用PASCAL宏來宣告這個呼叫約定,類似的宏還有WINAPI和CALLBACK。
stdcall呼叫約定宣告的語法為(以前文的那個函式為例):
int __ stdcall function(int a,int b)
stdcall的呼叫約定意味著:1)引數從右向左壓入堆疊,2)函式自身修改堆疊 3)函式名自動加前導的下劃線,後面緊跟一個@符號,其後緊跟著引數的尺寸
以上述這個函式為例,引數b首先被壓棧,然後是引數a,函式呼叫function(1,2)呼叫處翻譯成組合語言將變成:
push 2 第二個引數入棧 push 1 第一個引數入棧 call function 呼叫引數,注意此時自動把cs:eip入棧
而對於函式自身,則可以翻譯為: push ebp 儲存ebp暫存器,該暫存器將用來儲存堆疊的棧頂指標,可以在函式退出時恢復 mov ebp,esp 儲存堆疊指標 mov eax,[ebp + 8H] 堆疊中ebp指向位置之前依次儲存有ebp,cs:eip,a,b,ebp +8指向a add eax,[ebp + 0CH] 堆疊中ebp + 12處儲存了b mov esp,ebp 恢復esp pop ebp ret 8
而在編譯時,這個函式的名字被翻譯成_function@8
注意不同編譯器會插入自己的彙編程式碼以提供編譯的通用性,但是大體程式碼如此。其中在函式開始處保留esp到ebp中,在函式結束恢復是編譯器常用的方法。
從函式呼叫看,2和1依次被push進堆疊,而在函式中又透過相對於ebp(即剛進函式時的堆疊指標)的偏移量存取引數。函式結束後,ret 8表示清理8個位元組的堆疊,函式自己恢復了堆疊。
常見的呼叫約定還有:
cdecl
fastcall
thiscall
naked call
其中cdecl呼叫約定的引數壓棧順序是和stdcall是一樣的,但是函式本身不清理堆疊,呼叫者負責清理堆疊。由於這種變化,C呼叫約定允許函式的引數的個數是不固定的,這也是C語言的一大特色。
好了,能不能加點分,呵呵
WINAPI識別符號在WINDEF.H定義,語句如下:
#define WINAPI __stdcall
讓我們說說這個__stdcall
stdcall呼叫約定
stdcall很多時候被稱為pascal呼叫約定,因為pascal是早期很常見的一種教學用計算機程式設計語言,其語法嚴謹,使用的函式呼叫約定就是stdcall。在Microsoft C++系列的C/C++編譯器中,常常用PASCAL宏來宣告這個呼叫約定,類似的宏還有WINAPI和CALLBACK。
stdcall呼叫約定宣告的語法為(以前文的那個函式為例):
int __ stdcall function(int a,int b)
stdcall的呼叫約定意味著:1)引數從右向左壓入堆疊,2)函式自身修改堆疊 3)函式名自動加前導的下劃線,後面緊跟一個@符號,其後緊跟著引數的尺寸
以上述這個函式為例,引數b首先被壓棧,然後是引數a,函式呼叫function(1,2)呼叫處翻譯成組合語言將變成:
push 2 第二個引數入棧 push 1 第一個引數入棧 call function 呼叫引數,注意此時自動把cs:eip入棧
而對於函式自身,則可以翻譯為: push ebp 儲存ebp暫存器,該暫存器將用來儲存堆疊的棧頂指標,可以在函式退出時恢復 mov ebp,esp 儲存堆疊指標 mov eax,[ebp + 8H] 堆疊中ebp指向位置之前依次儲存有ebp,cs:eip,a,b,ebp +8指向a add eax,[ebp + 0CH] 堆疊中ebp + 12處儲存了b mov esp,ebp 恢復esp pop ebp ret 8
而在編譯時,這個函式的名字被翻譯成_function@8
注意不同編譯器會插入自己的彙編程式碼以提供編譯的通用性,但是大體程式碼如此。其中在函式開始處保留esp到ebp中,在函式結束恢復是編譯器常用的方法。
從函式呼叫看,2和1依次被push進堆疊,而在函式中又透過相對於ebp(即剛進函式時的堆疊指標)的偏移量存取引數。函式結束後,ret 8表示清理8個位元組的堆疊,函式自己恢復了堆疊。
常見的呼叫約定還有:
cdecl
fastcall
thiscall
naked call
其中cdecl呼叫約定的引數壓棧順序是和stdcall是一樣的,但是函式本身不清理堆疊,呼叫者負責清理堆疊。由於這種變化,C呼叫約定允許函式的引數的個數是不固定的,這也是C語言的一大特色。
好了,能不能加點分,呵呵