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的更多相关文章

  1. 从栈不平衡问题 理解 calling convention

    最近在开发的过程中遇到了几个很诡异的问题,造成了栈不平衡从而导致程序崩溃. 经过几经排查发现是和调用规约(calling convention)相关的问题,特此分享出来. 首先,讲一下什么是调用规约. ...

  2. X86调用约定 calling convention

    http://zh.wikipedia.org/wiki/X86%E8%B0%83%E7%94%A8%E7%BA%A6%E5%AE%9A 这里描述了在x86芯片架构上的调用约定(calling con ...

  3. Calling Convention的总结

    因为经常需要和不同的Calling Convention打交道,前段时间整理了一下它们之间的区别,如下: 清理堆栈 参数压栈顺序 命名规则 (MSVC++) 备注 Cdecl 调用者 (Caller) ...

  4. C/C++:函数的调用约定(Calling Convention)和名称修饰(Decorated Name)以及两者不匹配引起的问题

    转自:http://blog.csdn.net/zskof/article/details/3475182 注:C++有着与C不同的名称修饰,主要是为了解决重载(overload):调用约定则影响函数 ...

  5. function calling convention

    这是2013年写的一篇旧文,放在gegahost.net上面 http://raison.gegahost.net/?p=31 February 19, 2013 function calling c ...

  6. 调用惯例Calling Convention (或者说:调用约定)

    调用惯例影响执行效率,参数的传递方式以及栈清除的方式.   调用惯例 参数传递顺序 谁负责清除参数 参数是否使用暂存器 register 从左到右 被调用者 是 pascal 从左到右 被调用者 否 ...

  7. JAVA calling convention

    http://stackoverflow.com/questions/28126082/where-does-the-jit-compiled-code-reside https://wiki.ope ...

  8. 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 ...

  9. 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 ...

随机推荐

  1. 洛谷 P5304 [GXOI/GZOI2019]旅行者(最短路)

    洛谷:传送门 bzoj:传送门 参考资料: [1]:https://xht37.blog.luogu.org/p5304-gxoigzoi2019-lv-xing-zhe [2]:http://www ...

  2. 分类器的评价指标-ROC&AUC

    ROC 曲线:接收者操作特征曲线(receiver operating characteristic curve),是反映敏感性和特异性连续变量的综合指标,roc 曲线上每个点反映着对同一信号刺激的感 ...

  3. Linux samba服务器的搭建

    目录 1. 安装samba 2. 配置smb.conf 3. 创建samba登陆用户 4. 创建samba共享文件夹 5. 重启samba服务 6. 访问samba共享文件夹 7. 参考资料 1. 安 ...

  4. Excel——使用INDEX和SMALL实现条件筛选

    如下图所示,如何实现Excel自带的筛选功能呢?(对的,就是软件自带的功能) 如何实现: B13的公式:=IFERROR(INDEX(B:B,SMALL(IF(A$1:A$10=B$12,ROW($1 ...

  5. 集智人工智能学习笔记Python#0

    1,学习基本Python语句规范: print('Hello world') print() 为函数 ‘Hello world’为字符串 2,表达式和语句的区别: 表达式有结果,运算就是表达式的一种: ...

  6. mysql:The user specified as a definer ('xxx'@'%') does not exist 解决方法

    发生这种问题.大概率是用户不存在或者是权限不够 用户不存在.用可视化工具新建一个. 权限不够 ,运行下面命令: 如:我的错误: The user specified as a definer ('mo ...

  7. WebRTC Precompiled 使用

    最近研究webrtc native code,但源码太大(10GB以上)又需要FQ,就找了个预编译的版本https://sourcey.com/precompiled-webrtc-libraries ...

  8. 2018-2019-2 20165237《网络对抗技术》Exp2 后门原理与实践

    2018-2019-2 20165237<网络对抗技术>Exp2 后门原理与实践 一.实践目标 使用netcat获取主机操作Shell,cron启动 使用socat获取主机操作Shell, ...

  9. iOS 集成百度地图 位置偏移问题

    iOS 集成百度SDK 请参考 百度地图官方文档 ,这里不就多啰嗦了 本文介绍的是在百度地图上根据经纬度,自定义气泡时,气泡位置的偏移,在我们天朝这种事是很常见的,也见怪不怪了,在项目中使用的百度地图 ...

  10. 2018-2019-2 20165231 王杨鸿永 Exp6 信息搜集与漏洞扫描

    实践目标 掌握信息搜集的最基础技能与常用工具的使用方法. 2.实践内容 (1)各种搜索技巧的应用 (2)DNS IP注册信息的查询 (3)基本的扫描技术:主机发现.端口扫描.OS及服务版本探测.具体服 ...