C&C++ Calling Convention
tkorays(tkorays@hotmail.com)
调用约定(Calling Convention) 是计算机编程中一个比较底层的设计,它主要涉及:
- 函数参数通过寄存器传递还是栈?
- 函数参数从左到右还是从右到左压栈?
- 是否支持可变参数函数(vararg function or variadic function)。
- 是否需要函数原型?
- 怎么修饰函数名,唯一标识函数?
- 调用者(caller)还是被调用者(called or callee)清理堆栈?
1. Calling Conventions
在C和C++中有几种调用约定:__cdecl, __stdcall, __fastcall, __thiscall, __clrcall, __vectorcall。下面首先介绍几种调用约定。
1.1 __cdecl
C Declaration Calling Convention,C声明调用约定。它是C和C++默认的调用约定。特点:
- 堆栈由调用者清除(手动清除)。
- 参数从右到左压栈。
- 支持可变参数(函数自己并不知道自己有多少个参数,因此需要调用者来清除)。
- 编译后函数名改编为:“_函数名”。如_funcname。
1.2 __stdcall
Standard Calling Convention,标准调用约定。又称为Pascal Convention。特点:
- 被调用函数自动将参数弹出栈。
- 参数从右到坐压栈(和__cdecl一样),如果调用类的成员函数,最后压入this指针。
- 需要一个函数原型,不支持变参函数。
- 函数名改编:“_函数名@参数字节大小十进制”。如_funcname@8。
1.3 __fastcall
Fast Calling Convention,快速调用约定。通过使用寄存器解决效率问题。特点:
- 函数参数部分通过寄存器传递,函数中最左的两个DWORD(寄存器大小是双字)或者更小的参数,通过寄存器传递。剩下的从右到左堆栈传递。
- 函数名改编:“@函数名@函数参数字节大小十进制”。
- 返回方式同__stdcall。
1.4 __thiscall
主要用于x86系统中C++的类的成员函数调用,使用寄存器ecx来传递this指针。参数从右往左压栈,返回方式同__stdcall,由被调用者自己清除堆栈。
1.5 __clrcall
__clrcall是C++ .Net里面的。
1.6 __vectorcall
要求尽可能在寄存器中传递参数。函数名改编为”@@函数名@参数字节数十进制”。这是微软自己添加的标准。 总结
除了__cdecl(以及__clrcall),其他的都是被调用者清除堆栈。
2. 函数名修饰
2.1 C++中函数名修饰
在C语言中不存在重载,因此不需要担心同名函数问题,但是在C++中,使用C中的函数名修饰方式就存在问题。对于重载的函数,仅仅凭函数名和参数内存大小无法完全区分;类的成员函数表示并没有说明。所以在C++中,对于函数名改编需要一套策略。函数名格式大致如?FuncName@@YGXZ这种形式。
- 修饰名以
?开始,后面接函数名。 - 函数名后为
@@YG、@@YA、@@YI,分别代表stdcall、cdecl、fastcall。 - @@YG等后面接着参数类型字符,第一个表示返回值类型。
- 字符串以
@Z结束,如果函数没有参数,则直接以Z结束。
参数符号如下:
- X: void
- D: char
- E: unsigned char
- F: short
- H: int
- I: unsigned int
- J: long
- K: unsigned long
- M: float
- N: double
- _N: bool
- PA: 指针
- PB: const指针
- U: struct
所以int __stdcall fa();可以改编为:?fa@@YGHXZ;char* fb(int,bool);改编为?fb@@YAPADH_N@Z。
所以在C++中函数名改编和C不同,如果需要遵循C中的改编方式,可以使用extern "C"{}。
2.2 C++成员函数名修饰
类的成员函数的调用方式为thiscall,其函数名修饰方式和普通函数有些差别。成员函数名改编需在函数名和参数中间插入类名。且需要指定函数一些性质,如
- public为@@QAE,protected为@@IAE,private为@@AAE
- 如果函数声明为const,则public为@QBE,protected为@@IBE,private为@@ABE。
- 如果参数类型是类实例的引用,则使用“AAV1”,const引用则为
ABV1。
如:
?FuncA@ClassA@@QAEXH@Z表示void ClassA::FuncA(int);。?FuncB@ClassA@@QAEXABV1@Z表示void ClassA::FuncB(const ClassA&);
C&C++ Calling Convention的更多相关文章
- 从栈不平衡问题 理解 calling convention
最近在开发的过程中遇到了几个很诡异的问题,造成了栈不平衡从而导致程序崩溃. 经过几经排查发现是和调用规约(calling convention)相关的问题,特此分享出来. 首先,讲一下什么是调用规约. ...
- X86调用约定 calling convention
http://zh.wikipedia.org/wiki/X86%E8%B0%83%E7%94%A8%E7%BA%A6%E5%AE%9A 这里描述了在x86芯片架构上的调用约定(calling con ...
- Calling Convention的总结
因为经常需要和不同的Calling Convention打交道,前段时间整理了一下它们之间的区别,如下: 清理堆栈 参数压栈顺序 命名规则 (MSVC++) 备注 Cdecl 调用者 (Caller) ...
- C/C++:函数的调用约定(Calling Convention)和名称修饰(Decorated Name)以及两者不匹配引起的问题
转自:http://blog.csdn.net/zskof/article/details/3475182 注:C++有着与C不同的名称修饰,主要是为了解决重载(overload):调用约定则影响函数 ...
- function calling convention
这是2013年写的一篇旧文,放在gegahost.net上面 http://raison.gegahost.net/?p=31 February 19, 2013 function calling c ...
- 调用惯例Calling Convention (或者说:调用约定)
调用惯例影响执行效率,参数的传递方式以及栈清除的方式. 调用惯例 参数传递顺序 谁负责清除参数 参数是否使用暂存器 register 从左到右 被调用者 是 pascal 从左到右 被调用者 否 ...
- JAVA calling convention
http://stackoverflow.com/questions/28126082/where-does-the-jit-compiled-code-reside https://wiki.ope ...
- ARM 调用约定 calling convention
int bar( int a, int b, int c, int d, int e, int f, int g ) { ]; array2[ ] = a + b; array2[ ] = b + c ...
- sparc v8 stack frame calling convention
main.c ; int main() { int a, b; int sum; a = ; b = ; sum = add(a, b); ; } int add(int a, int b) { in ...
随机推荐
- easyUI文本框获得焦点,失去焦点
easyUI帮助文档对于文本框的操作没有提供直接获得焦点,或者失去焦点的方法,我们可以采用以下写法来实现. 获得焦点: $('input',$('#文本框Id').next('span')).focu ...
- 贝叶斯A/B测试 - 一种计算两种概率分布差异性的方法过程
1. 控制变量 0x1:控制变量主要思想 科学中对于多因素(多变量)的问题,常常采用控制因素(变量)的方法,吧多因素的问题变成多个单因素的问题.每一次只改变其中的某一个因素,而控制其余几个因素不变,从 ...
- 机器学习中模型泛化能力和过拟合现象(overfitting)的矛盾、以及其主要缓解方法正则化技术原理初探
1. 偏差与方差 - 机器学习算法泛化性能分析 在一个项目中,我们通过设计和训练得到了一个model,该model的泛化可能很好,也可能不尽如人意,其背后的决定因素是什么呢?或者说我们可以从哪些方面去 ...
- JMeter二次开发环境配置
本文主要介绍如何在Eclipse中配置JMeter开发环境. 一.下载JMeter源码 1.在JMeter官网下载二进制包和源码包: 解压备用: 二进制解压后文件夹名称为“jmeter_release ...
- Java虚拟机—垃圾回收算法(整理版)
1.概述 由于垃圾收集算法的实现涉及大量的程序细节.因此本节不打算过多地讨论算法的实现,只是介绍几种算法的思想及其发展过程.主要涉及的算法有标记-清除算法.复制算法.标记-整理算法.分代收集算法. 2 ...
- elasticsearch 6.2.4添加用户密码认证
elasticsearch 6.3版本之前的添加认证需安装x-pack插件,6.3之后貌似去掉了这个. 1.安装x-pack 先切换到elastic用户下,在执行以下命令 $cd /data/elas ...
- 在页面加载前先出现加载loading,页面加载完成之后再显示页面
在此加入一个关于页面加载成功之前先展现一个loading的案例: 如下代码写入js里放在html头部即可实现需求:添加的可以自己在css文件设置宽高,也可以放入一个background的gif的loa ...
- BZOJ4314 倍数?倍数!
好神仙啊.... 题意 在$ [0,n) $中选$ k$个不同的数使和为$ n$的倍数 求方案数 $ n \leq 10^9, \ k \leq 10^3$ 题解 k可以放大到1e6的 先不考虑$ k ...
- PLSQL DEVELOPER编辑器的自动替换文件
PLSQL DEVELOPER的编辑器的自动替换文件: s=Select * From w=Where ins=Insert Into sc=Select Count(*) From pb=Parti ...
- TCP 和UDP协议的应用考虑
linux uboot烧写采用的是TFTP协议,是基于UDP的不可靠需要自定义包头包围的网络升级方式. 代码比较简单,容易实现单片机的移植和使用,倒是可以考虑实现一种远程升级的方式. 但是事实上,对于 ...