win32-C++调用约定

1. __cdecl调用约定

c++代码:

int __cdecl Function(int x, int y) {
    return x + y;
}

int main()
{
    Function(2, 3);
}

 

 汇编代码:

00251881  push        3  
00251883  push        2  
00251885  call        Function (02513DEh)  
0025188A  add         esp,8

通过汇编代码可以看到__cdecl调用约定是通过从右向左压栈将参数压入堆栈中,最后进行外平栈,将堆栈平衡。

2.__stdcall调用约定

c++代码:

int __stdcall Function(int x, int y) {
    return x + y;
}

int main()
{
    Function(2, 3);
}

汇编代码:

00F01881  push        3  
00F01883  push        2  
00F01885  call        Function (0F013E3h)  
复制代码
int __stdcall Function(int x, int y) {
00F01790  push        ebp  
00F01791  mov         ebp,esp  
00F01793  sub         esp,0C0h  
00F01799  push        ebx  
00F0179A  push        esi  
00F0179B  push        edi  
00F0179C  mov         edi,ebp  
00F0179E  xor         ecx,ecx  
00F017A0  mov         eax,0CCCCCCCCh  
00F017A5  rep stos    dword ptr es:[edi]  
00F017A7  mov         ecx,offset _6235DE03_Practice@cpp (0F0C068h)  
00F017AC  call        @__CheckForDebuggerJustMyCode@4 (0F0132Ah)  
    return x + y;
00F017B1  mov         eax,dword ptr [x]  
00F017B4  add         eax,dword ptr [y]  
}
00F017B7  pop         edi  
00F017B8  pop         esi  
00F017B9  pop         ebx  
00F017BA  add         esp,0C0h  
00F017C0  cmp         ebp,esp  
00F017C2  call        __RTC_CheckEsp (0F01249h)  
00F017C7  mov         esp,ebp  
00F017C9  pop         ebp  
00F017CA  ret         8  
复制代码

通过汇编代码我们可以看到stdcall调用约定和cdecl调用约定的入参方式是相同的,都是从右到左将参数压栈,但是在最后进行堆栈平衡的时候,stdcall是通过内平衡的方式。

3.__fastcall调用约定

c++代码:

int __fastcall Function(int x, int y) {
    return x + y;
}

int main()
{
    Function(2, 3);
}

汇编代码:

00531881  mov         edx,3  
00531886  mov         ecx,2  
0053188B  call        Function (05313E8h)

通过汇编代码我们可以看到__fastcall传递参数的方式是通过edx和ecx寄存器进行传递,从而不需要进行堆栈平衡,那如果我们的参数超过两个呢,再来看看,这次我们传递四个参数

c++代码:

int __fastcall Function(int x, int y, int z, int k) {
    return x + y + z + k;
}

int main()
{
    Function(2, 3,4,5);
}

汇编代码:

00D41881  push        5  
00D41883  push        4  
00D41885  mov         edx,3  
00D4188A  mov         ecx,2  
00D4188F  call        Function (0D413EDh)  
复制代码
int __fastcall Function(int x, int y, int z, int k) {
00D41790  push        ebp  
00D41791  mov         ebp,esp  
00D41793  sub         esp,0D8h  
00D41799  push        ebx  
00D4179A  push        esi  
00D4179B  push        edi  
00D4179C  push        ecx  
00D4179D  lea         edi,[ebp-18h]  
00D417A0  mov         ecx,6  
00D417A5  mov         eax,0CCCCCCCCh  
00D417AA  rep stos    dword ptr es:[edi]  
00D417AC  pop         ecx  
00D417AD  mov         dword ptr [y],edx  
00D417B0  mov         dword ptr [x],ecx  
00D417B3  mov         ecx,offset _6235DE03_Practice@cpp (0D4C068h)  
00D417B8  call        @__CheckForDebuggerJustMyCode@4 (0D4132Ah)  
    return x + y + z + k;
00D417BD  mov         eax,dword ptr [x]  
00D417C0  add         eax,dword ptr [y]  
00D417C3  add         eax,dword ptr [z]  
00D417C6  add         eax,dword ptr [k]  
}
00D417C9  pop         edi  
00D417CA  pop         esi  
00D417CB  pop         ebx  
00D417CC  add         esp,0D8h  
00D417D2  cmp         ebp,esp  
00D417D4  call        __RTC_CheckEsp (0D41249h)  
00D417D9  mov         esp,ebp  
00D417DB  pop         ebp  
00D417DC  ret         8 
复制代码

我们可以看到参数是从左到右的方式进行压栈,最后两个参数的时候是通过寄存器进行传递,平衡堆栈的方式是通过内平栈的方式。

以上就是__cdecl,__stdcall,__fastcall三种不同调用约定的区别。

 

posted @   Dear黑色  阅读(25)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
点击右上角即可分享
微信分享提示