其實看雪的書中已經提到這個問題了,只不過少了thiscall和fastcall,而thiscall是VC++類成員預設的函式呼叫方式、fastcall是C++Builder預設的呼叫方式,所以我在這裡做一個補充,方便大家查閱。
例子:
假設我們的函式為:
int sumExample (int a, int b)
{
return a + b;
}
呼叫程式碼為: int c = sum (2, 3);
現在分別來看幾種不同的呼叫方式,呼叫者彙編程式碼和函式體彙編程式碼:
(1)_cdecl (C語言的呼叫方式) ---------------
呼叫者程式碼>>>:
; // push arguments to the stack, from right to left
push 3
push 2
; // call the function
call _sumExample
; // cleanup the stack by adding the size of the arguments to ESP register
add esp,8
; // copy the return value from EAX to a local variable (int c)
mov dword ptr [c],eax
函式體程式碼>>>:
; // function prolog
push ebp
mov ebp,esp
sub esp,0C0h
push ebx
push esi
push edi
lea edi,[ebp-0C0h]
mov ecx,30h
mov eax,0CCCCCCCCh
rep stos dword ptr [edi]
; //return a + b;
mov eax,dword ptr [a]
add eax,dword ptr [b]
; // function epilog
pop edi
pop esi
pop ebx
mov esp,ebp
pop ebp
ret
(2)__stdcall (Windows API 的呼叫方式)
-----------------------
呼叫者程式碼>>>:
; // push arguments to the stack, from right to left
push 3
push 2
; // call the function
call _sumExample@8
; // copy the return value
from EAX to a local variable (int c)
mov dword ptr [c],eax
函式體程式碼>>>:
; // function prolog goes here (the same code as in the __cdecl example)
; //return a + b;
mov eax,dword ptr [a]
add eax,dword ptr [b]
; // function epilog goes here
(the same code as in the __cdecl example)
; // cleanup the stack and
return
ret 8
(3)__fastcall(暫存器呼叫方式) -----------------------
呼叫者程式碼>>>:
; // put the arguments in the registers EDX and ECX
mov edx,3
mov ecx,2
; // call the function
call @fastcallSum@8
; // copy the return value from EAX to a local variable (int c)
mov dword ptr [c],eax
函式體程式碼>>>:
; // function prolog
push
ebp
mov ebp,esp
sub esp,0D8h
push ebx
push esi
push edi
push ecx
lea edi,[ebp-0D8h]
mov ecx,36h
mov eax,0CCCCCCCCh
rep stos dword ptr [edi]
pop ecx
mov dword ptr [ebp-14h],edx
mov dword ptr [ebp-8],ecx
; // return a + b;
mov eax,dword ptr [a]
add eax,dword ptr [b]
;// function epilog
pop edi
pop esi
pop ebx
mov esp,ebp
pop ebp
ret
(4)thiscall(C++類成員函式呼叫方式) -----------------------
這個比較特殊,函式是某個類的成員,所以我們這樣定義:
class CSum //類定義
{
int sum ( int a, int b) {return a+b;}
};
呼叫者程式碼>>>:
push 3
push 2
lea ecx,[sumObj]
call ?sum@CSum@@QAEHHH@Z; CSum::sum
mov dword ptr [s4],eax
函式體程式碼>>>:
push ebp
mov ebp,esp
sub esp,0CCh
push ebx
push esi
push edi
push ecx
lea edi,[ebp-0CCh]
mov ecx,33h
mov eax,0CCCCCCCCh
rep stos dword ptr [edi]
pop ecx
mov dword ptr [ebp-8],ecx
mov eax,dword ptr [a]
add eax,dword ptr [b]
pop edi
pop esi
pop ebx
mov esp,ebp
pop ebp
ret 8
總結: 這4種call基本上是C++程式(Visual C++ ,C++Builder)最常見的呼叫方式,熟練掌握這幾種call的呼叫者與函式體的彙編程式碼格式有助於更快分析演算法,寫序號產生器。所以我簡單列舉在這裡,不足的地方還請大家補充,錯誤的地方還請批評指正!
WinHack QQ: 85436 於2003-07-24
屬於:CCG,OCN,FCG,YCG,轉載請保持完整