C 语言有 __cdecl、__stdcall、__fastcall、naked、__pascal。

C++ 语言有 __cdecl、__stdcall、__fastcall、naked、__pascal、__thiscall,比 C 语言多出一种 __thiscall 调用方式。

下面详细介绍如上六种调用方式:

1、__cdecl

__cdecl调用约定又称为 C 调用约定,是 C/C++ 语言缺省的调用约定。表示C语言默认的函数调用方法,参数按照从右至左的方式入栈,函数本身不清理栈,此工作由调用者负责,返回值在EAX中。由于由调用者清理栈,所以允许可变参数函数存在,如int sprintf(char* buffer,const char* format,...);。

 

2、__stdcall

__stdcall 很多时候被称为 pascal 调用约定。是StandardCall的缩写,是C++的标准调用方式。pascal 语言是早期很常见的一种教学用计算机程序设计语言。所有参数从右到左依次入栈,如果是调用类成员的话,最后一个入栈的是this指针。这些堆栈中的参数由被调用的函数在返回时清除,使用的指令是 retnX,X表示参数占用的字节数,CPU在ret之后自动弹出X个字节的堆栈空间。称为自动清栈。函数在编译的时候就必须确定参数个数,并且调用者必须严格的控制参数的生成,不能多,不能少,否则返回后会出错。返回值在EAX中

 

3、__fastcall

顾名思义,__fastcall 的特点就是快,因为它通过 CPU 寄存器来传递参数。他用 ECX 和 EDX 传送前两个双字(DWORD)或更小的参数,剩下的参数按照从右至左的方式入栈,函数自身清理堆栈,返回值在 EAX 中。

 

4、naked

naked 是一个很少见的调用约定,一般不建议使用。编译器不会给这种函数增加初始化和清理代码,更特殊的是,你不能用return返回返回值,只能用插入汇编返回结果,此调用约定必须跟 __declspec 同时使用。例如定义一个求和程序,如__declspec(naked) int  add(int a,int b);。

 

5、__pascal

这是 pascal 语言的调用约定,跟 __stdcall 一样,参数按照从右至左的方式入栈,函数自身清理堆栈,返回值在EAX中。VC 中已经废弃了这种调用方式,因此在写 VC 程序时,建议使用 __stdcall 代替。

 

6、__thiscall

这是 C++ 语言特有的一种调用方式,用于类成员函数的调用约定。如果参数确定,this 指针存放于 ECX 寄存器,函数自身清理堆栈;如果参数不确定,this指针在所有参数入栈后再入栈,调用者清理栈。__thiscall 不是关键字,程序员不能使用。参数按照从右至左的方式入栈。

注意

_fastcall 和 __thiscall涉及的寄存器由编译器决定,因此不能用作跨编译器的接口。所以Windows上的COM对象接口都定义为_stdcall调用方式。

针对参数列表类型的函数。即可变参数函数:

为什么只有__cdecl的调用约定支持可变参数,而__stdcall就不支持?

实际上__cdecl和__stdcall函数参数都是从右到左入栈,它们的区别在于由谁来清栈,__cdecl由外部调用函数清栈,而__stdcall由被调用函数本身清栈, 显然对于可变参数的函数,函数本身没法知道外部函数调用它时传了多少参数,所以没法支持被调用函数本身清栈(__stdcall), 所以可变参数只能用__cdecll.

另外还要理解函数参数传递过程中堆栈是如何生长和变化的,从堆栈低地址到高地址,依次存储 被调用函数局部变量,上一函数堆栈桢基址,函数返回地址,参数1, 参数2, 参数3..

参数传递顺序

1.从右到左依次入栈:__stdcall__cdecl,__thiscall,__fastcall
2.从左到右依次入栈:__pascal

调用堆栈清理

1.调用者清除栈。
2.被调用函数返回后清除栈。
 
X64下
调用约定简化了:一律使用__fastcall,前四个参数用 RCX、RDX、R8 和 R9传递,除了这四个外加RAX、R10、R11,其他寄存器都是非易失的。
https://msdn.microsoft.com/zh-cn/library/ms235286.aspx
 

X86/X64 函数调用约定的更多相关文章

  1. Windows x64汇编函数调用约定

    最近在写一些字符串函数的优化,用到x64汇编,我也是第一次接触,故跟大家分享一下. x86:又名 x32 ,表示 Intel x86 架构,即 Intel 的32位 80386 汇编指令集. x64: ...

  2. 『开源重编译』System.Data.SQLite.dll 自适应 x86 x64 AnyCPU 重编译

    背景: > System.Data.SQLite.dll 程序集 不能良好的支持 AngCPU 格式 System.Data.SQLite.dll 在 适应 x86 和 x64 有三个方案: & ...

  3. c++中的几种函数调用约定(转)

    C++中的函数调用约定(调用惯例)主要针对三个问题: 1.参数传递的方式(是否采用寄存器传递参数.采用哪个寄存器传递参数.参数压桟的顺序等): 参数的传递方式,最常见的是通过栈传递.函数的调用方将参数 ...

  4. 数据库管理工具GUI - PremiumSoft Navicat Premium Enterprise 11.2.15 x86/x64 KEY

    转载自: 数据库管理工具GUI - PremiumSoft Navicat Premium Enterprise 11.2.15 x86/x64 KEY Navicat Premium(数据库管理工具 ...

  5. [原创] 【2014.12.02更新网盘链接】基于EasySysprep4.1的 Windows 7 x86/x64 『视频』封装

    [原创] [2014.12.02更新网盘链接]基于EasySysprep4.1的 Windows 7 x86/x64 『视频』封装 joinlidong 发表于 2014-11-29 14:25:50 ...

  6. 关于VS项目平台的x86,x64,Any CPU以及Debug和Release的区别

    相信对于很多刚接触打包程序的同志来说,关于x86,x64,Any CPU这三个项目平台,以及解决方案配置Debug和Release有什么区别?这个问题一定有许多的困惑,甚至不乏一些已经工作了很久的老程 ...

  7. SQL Server 2008 R2 Developer (x86, x64, ia64) – DVD (Chinese-Simplified)

    http://blog.sina.com.cn/s/blog_4aedf6370101j9tz.html 1. SQL Server 2008 R2 Developer (x86, x64, ia64 ...

  8. System Address Map Initialization in x86/x64 Architecture Part 2: PCI Express-Based Systems

      原文  http://resources.infosecinstitute.com/system-address-map-initialization-x86x64-architecture-pa ...

  9. VOL.2 IE6,7,8(windows vista/7 x86/x64 )单文件版三连发,欢迎大家分享

    在上期 VOL.1 利用vmware ThinApp 制作非XP下可以运行的IE6 [无插件版](windows vista/7/8  x86/x64 )中,简要介绍了如何利用vmware Thina ...

随机推荐

  1. java websocket中的ping-pong 机制

    参考源码: https://github.com/TooTallNate/Java-WebSocket/blob/master/src/main/java/org/java_websocket/cli ...

  2. C#面向对象三大特性之三:多态

    比起前面的封装和继承,多态这个概念不是那么好理解.我们还是从一个事例开始: 公司最近为了陶冶情操,养了几种动物(Animal),有猫(Cat).狗(Dog).羊(Sheep),这些动物都有共同的特性, ...

  3. 浅谈JavaScript--闭包

    闭包的概念 由于在Javascript语言中,只有函数内部的子函数才能读取局部变量,因此可以把闭包简单理解成"定义在一个函数内部的函数". 变量的作用域 要理解闭包,首先必须理解J ...

  4. 置换群(本蒟蒻瞎BB的)(未完)

    置换群(本蒟蒻瞎BB的)(未完) 群的定义 给定一个集合\(G=\{a, b, c...\}\)和集合\(G\)上的二元运算*,并满足: 封闭性:\(\forall a, b \in G, \exis ...

  5. C#线程入门(一)

    入门 概述与概念 创建和开始使用多线程 线程同步基础 同步要领 锁和线程安全 Interrupt 和 Abort 线程状态 等待句柄 同步环境 使用多线程 单元模式和Windows Forms Bac ...

  6. OnclickListener

    https://developer.android.com/reference/android/view/View.OnClickListener.html# https://blog.csdn.ne ...

  7. iOS获取手机型号、iOS获取当前app的名称和版本号

    NSDictionary *infoDictionary = [[NSBundle mainBundle] infoDictionary]; CFShow(infoDictionary); // ap ...

  8. [Leetcode]011. Container With Most Water

    public class Solution { public int maxArea(int[] height) { int left = 0, right = height.length - 1; ...

  9. Oracle存储过程实例分析总结(代码)

    1.存储过程结构 1.1 第一个存储过程 ? 1 2 3 4 5 6 7 8 9 10 11 12 CREATE OR REPLACE PROCEDURE proc1 (     para1 varc ...

  10. c#spinLock使用

        版权声明:本文为博主原创文章,未经博主允许不得转载. https://blog.csdn.net/u011915028/article/details/53011811 一下解释摘自msdn  ...