我有一些汇编例程,它们由 C 函数调用并从 C 函数中获取参数。现在,我假设这些参数以 cdecl 顺序在堆栈上传递。这是一个公平的假设吗?
编译器 (GCC) 会检测到这一点并确保参数正确传递,还是我应该手动去声明它们 cdecl?如果是这样,如果我指定更高的优化级别,该属性是否仍然有效?
我有一些汇编例程,它们由 C 函数调用并从 C 函数中获取参数。现在,我假设这些参数以 cdecl 顺序在堆栈上传递。这是一个公平的假设吗?
编译器 (GCC) 会检测到这一点并确保参数正确传递,还是我应该手动去声明它们 cdecl?如果是这样,如果我指定更高的优化级别,该属性是否仍然有效?
调用约定不仅仅意味着参数排序。有一个很好的 pdf 解释了所有细节,由 Agner Fog 编写:不同 C++ 编译器和操作系统的调用约定。
这是您为其编写代码的平台的 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”调用约定;尽管如此,“默认”
在编写要从 C 调用的 asm 时,一个更重要的问题是符号名称是否应该带有下划线前缀。这在平台之间差异很大,总的趋势是基于 ELF 的平台不使用前缀,而大多数其他平台...
快速而肮脏的方法是创建一个与您要实现的 asm 函数匹配的虚拟 C 函数,使用传入的参数在虚拟 C 函数中做一些事情,以便您可以区分它们,编译然后反汇编。不是万无一失的,但经常工作。