[C++] Calling convention 调用约定

参数传递和命名约定

Microsoft 专用**
利用 Visual C++ 编译器,你可以指定约定规则用于参数传递以及调用函数和被调函数之间返回值。 并非所有的约定都在所有支持的平台上可用,某些约定使用平台特定的实现。 在大多数情况下, 在特定平台上使用关键字或编译器开关指定的不受支持的约定将会被忽略,平台默认约定将会被使用。

在 x86平台上,所有参数在传递时都将加宽到32位。 返回值也将加宽到32位,并通过 EAX寄存器返回。仅例外的是8字节结构,它通过EDX:EAX 寄存器对返回。更大的结构将在EAX寄存器中以指向隐藏返回结构的指针的形式返回。 参数从右到左压栈。 非POD 的结构不会在寄存器中返回。

编译器将生成prolog和epilog代码来保存和恢复 ESI、EDI、EBX 和 EBP 寄存器(如果它们在函数中被用到)。

当一个structunionclass从函数通过值返回时,该类型的所有定义必须相同,否则程序可能在运行时失败。

__stdcall 是什么?

__stdcall是用于函数的调用约定,它告诉编译器用于建栈,参数压栈以及获得返回值的规则。

有一些其他的调用约定如:__cdecl, __thiscall, __fastcall以及名字奇特的 __naked. __stdcall 是 Win32 系统调用的标准调用约定.

维基:

调用约定很关键的主要场合: 当你调用你的代码外的函数 (例如OS API) 或者OS在调用你,如果编译器不知道正确的调用约定,它就不会正确地管理栈,你的程序有可能出现非常奇怪的crash。

调用函数和被调函数必须使用相同的调用约定,否则程序会出现非常难以寻找到的bug.

Microsoft 的C和C++ 编译器为了有意提高函数调用的速度,为应用程序内的C和C++函数提供了各种不同的调用约定。在任何情况下,调用函数和被调函数使用的calling vonvention必须一致。现在windows自己提供了已经编译过的API,调用它们时,必须按要求调用。任何对Windows API的调用,以及来自于Windows API的回调,都必须使用 __stdcall调用约定。

C 或 C++自身并没有定义那些标识符,它们是编译器扩展,代表了某些调用约定。它们决定以何种顺序在何处放置参数,被调函数在何处能找到返回地址等等。例如,__fastcall 意思是,函数的参数通过寄存器传递。

以上是各大网站的翻译。


[1] https://msdn.microsoft.com/en-us/library/984x0h58.aspx
[2] https://stackoverflow.com/questions/297654/what-is-stdcall
[3] https://en.wikipedia.org/wiki/X86_calling_conventions

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值