__stdcall/__fastcall/__cdecl/nakedcall的主要区别在于两点:
1:汇编角度时传入参数的先后顺序
2:汇编代码中函数的栈的初始化和清理由谁处理
等等
简单实例解析一下:
unsigned int __stdcall/__fastcall/__cdecl printPara(int x1, int x2,int x3,int x4,int x5,int x6)
{
cout << x1 << x2 << x3 << x4 << x5 << x6 << endl;
return 0;
}
int main()
{
printPara(4, 5, 6, 7, 8, 9);
system("pause");
return 0;
}
第一种:__stdcall声明:
1:表明参数入参顺序由右到左的方式
unsigned int __stdcall printPara(int x1, int x2,int x3,int x4,int x5,int x6)
{
cout << x1 << x2 << x3 << x4 << x5 << x6 << endl;
return 0;
}
调用处汇编代码如下:由此可以断定传入参数的顺序
printPara(4, 5, 6, 7, 8, 9); // C++调用接口
010254DE push 9 // 压栈顺序,倒序压栈
010254E0 push 8
010254E2 push 7
010254E4 push 6
010254E6 push 5
010254E8 push 4
010254EA call printPara (010213C0h)
2:函数内部的栈的初始化和清理由printPara自己完成
unsigned int __stdcall printPara(int x1, int x2,int x3,int x4,int x5,int x6)
{
010251F0 push ebp
010251F1 mov ebp,esp
010251F3 sub esp,0D4h //开辟栈空间大小,扩展d4空间的栈
010251F9 push ebx
010251FA push esi
010251FB push edi
010251FC lea edi,[ebp-0D4h]
01025202 mov ecx,35h
01025207 mov eax,0CCCCCCCCh
0102520C rep stos dword ptr es:[edi]
.....
return 0;
010252E2 xor eax,eax
}
010252E4 pop edi
010252E5 pop esi
010252E6 pop ebx
010252E7 add esp,0D4h //回收d4空间的栈大小,所有的函数的栈的构造和清理都有printPara完成
010252ED cmp ebp,esp
010252EF call __RTC_CheckEsp (010212EEh)
010252F4 mov esp,ebp
010252F6 pop ebp
010252F7 ret 18h
第二种:__fastcall声明:
1:函数入参顺序还是从右向左,但是最多只能压栈4个,其余左边的参数使用寄存器方式传入
printPara(4, 5, 6, 7, 8, 9);
009F54DE push 9
009F54E0 push 8
009F54E2 push 7
009F54E4 push 6
009F54E6 mov edx,5 //差异点,5和4通过寄存器的方式压栈
009F54EB mov ecx,4
009F54F0 call printPara (09F1447h)
2:函数内部的栈的初始化和清理由printPara自己完成,与__stdcall相同
第三种:__cdecl声明:
1:函数入参顺序相同,依然为从右向左,
printPara(4, 5, 6, 7, 8, 9);
011554DE push 9 //参数顺序压栈
011554E0 push 8
011554E2 push 7
011554E4 push 6
011554E6 push 5
011554E8 push 4
011554EA call printPara (0115144Ch)
2:vc2013汇编代码依然是自己提升栈顶和恢复栈底
第四种:naked call声明:
1:入参顺序与前者一致
void __declspec(naked) printPara(int x1, int x2, int x3, int x4, int x5, int x6)
2:编译器不做任何的栈顶提升动作,由开发者自行写提升栈空间指令
012551DF int 3 //函数头无任何提升栈的操作和初始化
012551E0 int 3
012551E1 int 3
012551E2 int 3
012551E3 int 3
012551E4 int 3
012551E5 int 3
012551E6 int 3
012551E7 int 3
012551E8 int 3
012551E9 int 3
012551EA int 3
012551EB int 3
012551EC int 3
012551ED int 3
012551EE int 3
012551EF int 3
cout << x1 << x2 << x3 << x4 << x5 << x6 << endl;
012551F0 mov esi,esp
012551F2 push 1251398h