假设组合 C 和 x86 汇编时的调用约定
我有一些由 C 函数调用并从 C 函数获取参数的汇编例程。现在,我假设这些参数以 cdecl 顺序在堆栈上传递。这是一个合理的假设吗?
编译器(GCC)会检测到这一点并确保参数正确传递,还是我应该手动去声明它们cdecl?如果是这样,如果我指定更高的优化级别,该属性是否仍然有效?
I have some assembly routines that are called by and take arguments from C functions. Right now, I'm assuming those arguments are passed on the stack in cdecl order. Is that a fair assumption to make?
Would a compiler (GCC) detect this and make sure the arguments are passed correctly, or should I manually go and declare them cdecl? If so, will that attribute still hold if I specify a higher optimisation level?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
调用约定不仅仅意味着参数排序。有一个很好的 pdf 解释了所有细节,由 Agner Fog 编写: 不同 C++ 编译器和操作的调用约定系统。
Calling conventions mean much more than just argument ordering. There is a good pdf explaining all the details, written by Agner Fog: Calling conventions for different C++ compilers and operating systems.
这是您为其编写代码的平台的 ABI 问题。几乎所有平台都遵循 Unix System V ABI for C 调用约定和其他 ABI 问题,其中包括详细说明所有 CPU 架构中常见 ABI 特征的通用 ABI (gABI) 文档,以及特定于处理器的 ABI (psABI) 文档。特定的 CPU 架构/系列。当涉及到 x86 时,这与您所说的“cdecl”相匹配。因此,从实际角度来看,从 C 调用的 x86 程序集应该编写为假定“cdecl”。基本上,这种调用约定的普遍性的唯一例外是 Windows API 函数,由于遗留的 Win16 dll thunk 兼容性问题,它们使用自己的非标准“stdcall”调用约定;尽管如此,x86 Windows 上的“默认”调用约定仍然是“cdecl”。
当编写从 C 调用的汇编语言时,一个更重要的问题是符号名称是否应该以下划线作为前缀。这在平台之间差异很大,总体趋势是基于 ELF 的平台不使用前缀,而大多数其他平台则...
This is a matter of the ABI for the platform you're writing code for. Almost all platforms follow the Unix System V ABI for C calling convention and other ABI issues, which includes both a general ABI (gABI) document detailing the common ABI characteristics across all CPU architectures, and a processor-specific ABI (psABI) document specific to the particular CPU architecture/family. When it comes to x86, this matches what you refer to as "cdecl". So from a practical standpoint, x86 assembly meant to be called from C should be written to assume "cdecl". Basically the only exception to the universality of this calling convention is Windows API functions, which use their own nonstandard "stdcall" calling convention due to legacy Win16 dll thunk compatibility issues; nonetheless, the "default" calling convention on x86 Windows is still "cdecl".
A more important concern when writing asm to be called from C is whether symbol names should be prefixed with an underscore or not. This varies widely between platforms, with the general trend being that ELF-based platforms don't use the prefix, and most other platforms do...
快速而肮脏的方法是创建一个与您想要实现的 asm 函数相匹配的虚拟 C 函数,使用传入的参数在虚拟 C 函数中执行一些操作,以便您可以区分它们,编译然后反汇编。并非万无一失,但经常有效。
The quick and dirty way to do it is create a dummy C function that matches the asm function you want to implement, do a few things in the dummy C function with the passed in parameters so you can tell them apart, compile then disassemble. Not foolproof but works often.