__stdcall/__fastcall/__cdecl/nakedcall区别

__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  

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值