C++程序中不同函数调用方式的汇编码比较(转载)
2008-09-03 21:37
351 查看
其实看雪的书中已经提到这个问题了,只不过少了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的调用者与函数体的汇编代码格式有助于更快分析算法,写注册机。所以我简单列举在这里,不足的地方还请大家补充,错误的地方还请批评指正!
例子:
假设我们的函数为:
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的调用者与函数体的汇编代码格式有助于更快分析算法,写注册机。所以我简单列举在这里,不足的地方还请大家补充,错误的地方还请批评指正!
相关文章推荐
- C/C++不同函数调用方式(在汇编下调试)总结
- (转载)函数调用方式比较
- 直接调用类成员函数地址(用汇编取类成员函数的地址,各VS版本还有所不同)
- 函数调用的原理4点:函数产生名不同,压栈顺序不同,不应由客户清理,客户清理则可执行文件大小更大(许多参考文章,有汇编解释)
- lazarus中不同模式下自定义函数的调用方式区别
- VC 6中使用不同调用规范的函数在符号文件里的表示方式
- 为何C语言(的函数调用)需要堆栈,而汇编语言却不需要堆栈(转载)
- 不同远程调用方式的性能比较
- 汇编展示函数调用方式
- 三种调用虚函数的方式比较
- C++程序中不同的函数调用方式
- JavaScript 与jquery 之间不同的函数调用方式
- C/C++中几种函数调用方式的比较
- 函数调用的本质以及和不同语言间的比较
- VC6中使用不同调用规范的函数在符号文件里的表示方式
- 为何C语言(的函数调用)需要堆栈,而汇编语言却不需要堆栈
- 编写c51程序调用汇编函数的一种方法
- C语言函数和汇编函数相互调用(转)
- C++中函数调用的方式
- Go语言中三种不同md5计算方式的性能比较