zoukankan      html  css  js  c++  java
  • C/C++中几种函数调用方式的比较

    1. cdecl: C的函数默认调用方式, 适用可变参数,这种方式由于是 函数调用者清理堆栈,所以又导致了生成代码增长(因为每次函数调用之后都是实现清理功能的代码,如果是函数自己清理,则只需要一份清理代码就可以了)

    2. stdcall:  函数清理堆栈,不可用于可变参数

    3. fastcall:  类似stdcall, 但把因为它是通过寄存器 传送参数的(实际上,它用ECX和EDX传送前两个单字(DWORD)或更小的参数,剩下的参数仍旧自右向左压栈传送,被调用的函数在返回前清理传送参数的内存栈 )。
     
    基于在不同函数调用方式下的汇编生成代码作比较:(用VS反汇编生成,看标红代码即可)
    int func(int val1,int val2,int val3)
    {
    	int a;
    	a=val1;
    	return a;		
    }
    
    b=func(1,2,3);  //调用语句

    --------cdecl------------
    func:
    .........
    004113BE  mov         eax,dword ptr [val1] 
    004113C1  mov         dword ptr [a],eax 
    004113C4  mov         eax,dword ptr [a] 
    .........
    004113CD   ret         

    b=func(1,2,3):
    004113FE  push        3    
    00411400  push        2    
    00411402  push        1    
    00411404  call        func (411028h) 
    00411409   add         esp,0Ch 
    0041140C  mov         dword ptr [b],eax 


    说明: cdecl是函数调用者清理参数(add esp,0Ch,把栈指针加3个int长度的偏移,实现参数的清理,如果是类对象还要析构
    --------cdecl------------



    --------stdcall------------
    func:
    .........
    004113BE  mov         eax,dword ptr [val1] 
    004113C1  mov         dword ptr [a],eax 
    004113C4  mov         eax,dword ptr [a] 
    ......... 
    004113CD   ret         0Ch 

    b=func(1,2,3):
    004113FE  push        3    
    00411400  push        2    
    00411402  push        1    
    00411404  call        func (411028h) 
    00411409  mov         dword ptr [b],eax


    说明: stdcall是函数自己清理参数(注意此时堆栈指针esp是指向返回地址的,返回地址下面是参数,指令 ret OCh使 函数返回再给 esp加上3个int长度的偏移来清理参数
    --------stdcall------------



    --------fastcall------------
    func:
    .........
    004113BF   pop         ecx   
    004113C0   mov         dword ptr [ebp-14h],edx 
    004113C3   mov         dword ptr [ebp-8],ecx 
    004113C6  mov         eax,dword ptr [val1] //这里val1==ebp-8
    004113C9  mov         dword ptr [a],eax 
    004113CC  mov         eax,dword ptr [a] 
    .........  
    004113D5   ret         4 

    b=func(1,2,3):
    0041140E  push        3    
    00411410   mov         edx,2 
    00411415   mov         ecx,1 
    0041141A  call        func (4110B4h) 
    0041141F  mov         dword ptr [b],eax


    说明: fastcall是通过ecx和edx来传递前 两个单字(DWORD)或更小的参数 ,如这里用ecx传递1( mov ecx,1 ),edx传递2(mov edx,2 ), 它的栈中参数清理工作是跟stdcall一样的,只是这里只需要清理一个参数就可以了(ret   4 
    --------fastcall------------


    总结:
    1.cdecl和stdcall好理解,如果不需要可变参数的话,stdcall是好的选择。
    2.fastcall的作用有点不好理解,从上面的代码看,看不出有多么快速。。

    待续。。   
  • 相关阅读:
    <转>WCF中出现死锁或者超时
    无连接服务器与面向连接的服务器
    Linux系统调用
    vim文本删除方法 Linux
    深入了解C指针
    linux下c语言实现双进程运行
    *p++、(*p)++、*++p、++*p 的区别
    快速了解yuv4:4:4 yuv4:2:2 yuv 4:1:1 yuv 4:2:0四种YUV格式区别
    文件通过svn updata更新不到,并且svn st显示被删除的解决办法
    [非常重要的总结] Linux C相关函数
  • 原文地址:https://www.cnblogs.com/javawebsoa/p/3098030.html
Copyright © 2011-2022 走看看