【问题标题】:Assuming a calling convention when combining C and x86 Assembly结合 C 和 x86 程序集时假设调用约定
【发布时间】:2012-03-09 19:34:29
【问题描述】:

我有一些汇编例程,它们被 C 函数调用并从 C 函数中获取参数。现在,我假设这些参数以 cdecl 顺序在堆栈上传递。这是一个公平的假设吗?

编译器 (GCC) 会检测到这一点并确保参数正确传递,还是我应该手动去声明它们 cdecl?如果是这样,如果我指定更高的优化级别,该属性是否仍然有效?

【问题讨论】:

  • 不,您的汇编代码直到链接时才符合您的 C 代码。让 C 编译器对您采用的任何调用约定变得聪明为时已晚。内联汇编流行的原因之一。

标签: c assembly arguments calling-convention cdecl


【解决方案1】:

调用约定不仅仅意味着参数排序。有一个很好的 pdf 解释了所有细节,由 Agner Fog 撰写:Calling conventions for different C++ compilers and operating systems

【讨论】:

    【解决方案2】:

    这是您为其编写代码的平台的 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 调用的 asm 时,一个更重要的问题是符号名称是否应该带有下划线前缀。这在平台之间差异很大,总体趋势是基于 ELF 的平台不使用前缀,而大多数其他平台都使用...

    【讨论】:

      【解决方案3】:

      快速而肮脏的方法是创建一个与您要实现的 asm 函数匹配的虚拟 C 函数,使用传入的参数在虚拟 C 函数中做一些事情,以便您可以区分它们,然后编译拆卸。不是万无一失,但经常工作。

      【讨论】:

        猜你喜欢
        • 2016-09-24
        • 2017-01-18
        • 1970-01-01
        • 2013-03-31
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多