zoukankan      html  css  js  c++  java
  • cdecl、pascal、stdcall、fastcall

    Directive Parameter order   Clean-up Passes parameters in registers?
    register   Left-to-right         Routine        Yes
    pascal    Left-to-right           Routine     No
    cdecl    Right-to-left             Caller        No
    stdcall    Right-to-left           Routine     No
    safecall   Right-to-left          Routine     No

    调用约定           压参数入栈顺序     把参数弹出栈者         函数修饰名 
    (Calling convention) 
    --------------------------------------------------------------------------------------------------------
    __cdecl                 右->左             调用者                                 _function     
    __fastcall             右->左              被调用者                           @function@nnn      
    __stdcall             右->左               被调用者                           _function@nnn
    __pascal             左->右               被调用者                           _function@nnn
        
    -----------------------------------------------------------------------------------------------------------

    __cdecl是C/C++和MFC程序默认使用的调用约定,也可以在函数声明时加上__cdecl关键字来手工指定。采用__cdecl约定时,函数参数按照从右到左的顺序入栈,并且由调用函数者把参数弹出栈以清理堆栈。因此,实现可变参数的函数只能使用该调用约定。由于每一个使用__cdecl约定的函数都要包含清理堆栈的代码,所以产生的可执行文件大小会比较大。__cdecl可以写成_cdecl。
             __stdcall调用约定用于调用Win32 API函数。采用__stdcal约定时,函数参数按照从右到左的顺序入栈,被调用的函数在返回前清理传送参数的栈,函数参数个数固定。由于函数体本身知道传进来的参数个数,因此被调用的函数可以在返回前用一条ret n指令直接清理传递参数的堆栈。__stdcall可以写成_stdcall。
             __fastcall约定用于对性能要求非常高的场合。__fastcall约定将函数的从左边开始的两个大小不大于4个字节(DWORD)的参数分别放在ECX和EDX寄存器,其余的参数仍旧自右向左压栈传送,被调用的函数在返回前清理传送参数的堆栈。__fastcall可以写成_fastcall。 
    ·特别说明
    1. 在默认情况下,采用__cdecl方式,因此可以省略.
    2. WINAPI一般用于修饰动态链接库中导出函数
    3. CALLBACK仅用于修饰回调函数

    便于更好理解, 看下面例子(函数调用的过程以汇编代码表示):      
        
    void cdecl fun1(int x,int y); 
    void stdcall    fun2(int x,int y); 
    void pascal fun3(int x,int y);   
        

        
    **************************************** 

    void cdecl fun1(int x,int y); 

    fun1(x,y); 

    调用 fun1 的汇编代码 

    push y 
    push x 
    call fun1 
    add sp,sizeof(x)+sizeof(y) ;跳过参数区(x,y) 

    fun1 的汇编代码: 

    fun1 proc 
    push bp 
    mov bp,sp 
    …… 
     
    pop bp 
    ret ;返回,但不跳过参数区 
    fun1 endp 

    **************************************** 

    void stdcall fun2(int x,int y); 

    fun2(x,y); 

    调用 fun2 的汇编代码 

    push y 
    push x 
    call fun2 

    fun2 的汇编代码: 

    fun2 proc 
    push bp 
    mov bp,sp 
    …… 
     
    pop bp 
    ret sizeof(x)+sizeof(y) ;返回并跳过参数区(x,y) 
    fun2 endp 

    ***************************************** 

    void pascal fun3(int x,int y); 

    fun3(x,y); 

    调用 fun3 的汇编代码 

    push x 
    push y 
    call fun3 

    fun3 的汇编代码: 

    fun3 proc 
    push bp 
    mov bp,sp 
    …… 
     
    pop bp 
    ret sizeof(x)+sizeof(y) ;返回并跳过参数区(x,y) 
    fun3 endp  

  • 相关阅读:
    javaweb消息中间件——rabbitmq入门
    virtual box 桥接模式(bridge adapter)下无法获取ip(determine ip failed)的解决方法
    Apache Kylin本地启动
    git操作
    Java学习总结
    Java中同步的几种实现方式
    hibernate exception nested transactions not supported 解决方法
    vue 中解决移动端使用 js sdk 在ios 上一直报invalid signature 的问题解决
    cookie 的使用
    vue 专门为了解决修改微信标题而生的项目
  • 原文地址:https://www.cnblogs.com/lidabo/p/3274706.html
Copyright © 2011-2022 走看看