• 标 题:C++程序中不同函数调用方式的汇编码比较 
  • 作 者:windcbf
  • 时 间:2003/07/25 00:44am
  • 链 接:http://bbs.pediy.com

其实看雪的书中已经提到这个问题了,只不过少了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,转载请保持完整