c++的4种调用方式
文章目录__cdecl__stdcall__fastcall__thiscall代码验证__cdeclc默认的函数调用方法。参数从右到左入栈调用者清栈(手动清栈),add esp, xxx所以,参数由调用者维护,可变参数函数只能用此约定。输出函数名前会加上一个下划线前缀。__stdcallc++标准调用方式。参数从右到左入栈,成员方法this最后入栈;被调用者清栈(自动清...
·
__cdecl
c默认的函数调用方法。
- 参数从右到左入栈
- 调用者清栈(手动清栈),
add esp, xxx
所以,参数由调用者维护,可变参数函数只能用此约定。
输出函数名前会加上一个下划线前缀。
__stdcall
c++标准调用方式。
- 参数从右到左入栈,成员方法
this
最后入栈; - 被调用者清栈(自动清栈),
retn x
,x是参数占用的字节数
函数编译时必须确定并控制参数个数,否则返回出错。
函数名格式:_funcname@参数字节数
__fastcall
ecx和edx传送两个dword参数,其余参数仍然用栈。
被调用者清栈,retn x
。
函数名格式:@funcname@参数字节数
__thiscall
仅用于c++成员函数。__thiscall
不是关键字,所以不能被程序员指定。
传参和返回与stdcall一样。只是this用ecx传递。
Borland c++编译器使用eax存储this。
代码验证
#include <iostream>
class C
{
public:
void func()
{
std::cout << this << std::endl;
}
};
void func_c(char arg)
{
int a;
}
void __stdcall func_std(char arg0, int arg1)
{
int a;
}
void __fastcall func_fast(char arg0, int arg1, int arg2, int arg3)
{
int a;
}
int main()
{
C c;
c.func();
func_c(0);
func_std(1, 2);
func_fast(3, 4, 5, 6);
return 0;
}
C c;
c.func();
009742D8 8D 4D F7 lea ecx,[c]
009742DB E8 3E CD FF FF call C::func (097101Eh)
func_c(1);
009742E0 6A 01 push 0
009742E2 E8 50 CD FF FF call func_c (0971037h)
009742E7 83 C4 04 add esp,4
func_std(1, 2);
009742EA 6A 02 push 2
009742EC 6A 01 push 1
009742EE E8 87 D0 FF FF call func_std (097137Ah)
func_fast(3, 4, 5, 6);
009742F3 6A 06 push 6
009742F5 6A 05 push 5
009742F7 BA 04 00 00 00 mov edx,4
009742FC B1 03 mov cl,3
009742FE E8 81 D0 FF FF call func_fast (0971384h)
func_std汇编代码:
void __stdcall func_std(char arg0, int arg1)
{
009718D0 55 push ebp
009718D1 8B EC mov ebp,esp
009718D3 81 EC CC 00 00 00 sub esp,0CCh
009718D9 53 push ebx
009718DA 56 push esi
009718DB 57 push edi
009718DC 8D BD 34 FF FF FF lea edi,[ebp-0CCh]
009718E2 B9 33 00 00 00 mov ecx,33h
009718E7 B8 CC CC CC CC mov eax,0CCCCCCCCh
009718EC F3 AB rep stos dword ptr es:[edi]
int a;
}
009718EE 5F pop edi
int a;
}
009718EF 5E pop esi
009718F0 5B pop ebx
009718F1 8B E5 mov esp,ebp
009718F3 5D pop ebp
009718F4 C2 08 00 ret 8
func_fast汇编代码
void __fastcall func_fast(char arg0, int arg1, int arg2, int arg3)
{
009718A0 55 push ebp
009718A1 8B EC mov ebp,esp
009718A3 81 EC E4 00 00 00 sub esp,0E4h
009718A9 53 push ebx
009718AA 56 push esi
009718AB 57 push edi
009718AC 51 push ecx
009718AD 8D BD 1C FF FF FF lea edi,[ebp-0E4h]
009718B3 B9 39 00 00 00 mov ecx,39h
009718B8 B8 CC CC CC CC mov eax,0CCCCCCCCh
009718BD F3 AB rep stos dword ptr es:[edi]
009718BF 59 pop ecx
009718C0 89 55 EC mov dword ptr [arg1],edx
009718C3 88 4D F8 mov byte ptr [arg0],cl
int a;
}
009718C6 5F pop edi
009718C7 5E pop esi
009718C8 5B pop ebx
009718C9 8B E5 mov esp,ebp
009718CB 5D pop ebp
009718CC C2 08 00 ret 8
如果没有arg2和arg3的话,最后依据就是ret,而不是ret 8.
更多推荐
已为社区贡献1条内容
所有评论(0)