码迷,mamicode.com
首页 > 其他好文 > 详细

3种调用约定的区别与联系

时间:2015-06-04 13:44:53      阅读:168      评论:0      收藏:0      [点我收藏+]

标签:

由C代码到汇编代码来看看cdecl、stdcall、fastcall三个调用约定的区别:

int __stdcall add1(int x,int y)
{
    return x + y;
}
int __cdecl add2(int x, int y)
{
    return x + y;
}
int __fastcall add3(int x, int y,int z)
{
    return x + y +z;
}


int _tmain(int argc, _TCHAR* argv[])
{
    add1(1,2);
    add2(1, 2);
    add3(1, 2, 3);
    return 0;
}

main函数里面的反汇编代码:

int _tmain(int argc, _TCHAR* argv[])
{
001B14A0  push        ebp  
001B14A1  mov         ebp,esp  
001B14A3  sub         esp,0C0h  
001B14A9  push        ebx  
001B14AA  push        esi  
001B14AB  push        edi  
001B14AC  lea         edi,[ebp-0C0h]  
001B14B2  mov         ecx,30h  
001B14B7  mov         eax,0CCCCCCCCh  
001B14BC  rep stos    dword ptr es:[edi]  
    add1(1,2);
001B14BE  push        2  
001B14C0  push        1  
001B14C2  call        add1 (01B1032h)  
    add2(1, 2);
001B14C7  push        2  
001B14C9  push        1  
001B14CB  call        add2 (01B102Dh)  
001B14D0  add         esp,8  
    add3(1, 2, 3);
001B14D3  push        3  
001B14D5  mov         edx,2  
001B14DA  mov         ecx,1  
001B14DF  call        add3 (01B100Ah)  
    return 0;
001B14E4  xor         eax,eax  
}
001B14E6  pop         edi  
001B14E7  pop         esi  
001B14E8  pop         ebx  
001B14E9  add         esp,0C0h  
001B14EF  cmp         ebp,esp  
001B14F1  call        __RTC_CheckEsp (01B114Fh)  
001B14F6  mov         esp,ebp  
001B14F8  pop         ebp  
001B14F9  ret

对照源码,从表面上看,stdcall和fastcall传递参数方式为从右至左,由自身清理堆栈。

int __stdcall add1(int x,int y)
{
001B13D0  push        ebp  
001B13D1  mov         ebp,esp  
001B13D3  sub         esp,0C0h  
001B13D9  push        ebx  
001B13DA  push        esi  
001B13DB  push        edi  
001B13DC  lea         edi,[ebp-0C0h]  
001B13E2  mov         ecx,30h  
001B13E7  mov         eax,0CCCCCCCCh  
001B13EC  rep stos    dword ptr es:[edi]  
    return x + y;
001B13EE  mov         eax,dword ptr [x]  
001B13F1  add         eax,dword ptr [y]  
}
001B13F4  pop         edi  
001B13F5  pop         esi  
001B13F6  pop         ebx  
001B13F7  mov         esp,ebp  
001B13F9  pop         ebp  
001B13FA  ret         8        //自身清理堆栈

而cdecl为从右至左传递参数,由调用者清理堆栈。

001B14C7  push        2  
001B14C9  push        1  
001B14CB  call        add2 (01B102Dh)  
001B14D0  add         esp,8

fastcall传递参数很快,适合大程序的优化,前两个由EDX和ECX来传递,多出来的用push方式传递参数:

001B14D3  push        3  
001B14D5  mov         edx,2  
001B14DA  mov         ecx,1  
001B14DF  call        add3 (01B100Ah)
int __fastcall add3(int x, int y,int z)
{
001B1450  push        ebp  
001B1451  mov         ebp,esp  
001B1453  sub         esp,0D8h  
001B1459  push        ebx  
001B145A  push        esi  
001B145B  push        edi  
001B145C  push        ecx          
001B145D  lea         edi,[ebp-0D8h]  
001B1463  mov         ecx,36h  
001B1468  mov         eax,0CCCCCCCCh  
001B146D  rep stos    dword ptr es:[edi]  
001B146F  pop         ecx          //由于先借由ecx来初始化,所以先push保存,后pop恢复
001B1470  mov         dword ptr [y],edx  
001B1473  mov         dword ptr [x],ecx  
    return x + y + z;
001B1476  mov         eax,dword ptr [x]  
001B1479  add         eax,dword ptr [y]  
001B147C  add         eax,dword ptr [z]  
}
001B147F  pop         edi  
001B1480  pop         esi  
001B1481  pop         ebx  
001B1482  mov         esp,ebp  
001B1484  pop         ebp  
001B1485  ret         4      //由自身清理堆栈

3种调用约定的区别与联系

标签:

原文地址:http://www.cnblogs.com/code4st/p/4551484.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!