【问题标题】:Write inline assembly without clobber lists?编写没有破坏列表的内联汇编?
【发布时间】:2020-02-16 17:40:47
【问题描述】:

是否可以使用 GCC 或 Clang 编写内联汇编(Intel 语法),而无需了解 clobber 列表“东西”?

我猜是“否”,因为 clobber 列表“stuff”确保您不会覆盖编译器写入的寄存器(就在您的内联汇编开始之前)?

【问题讨论】:

  • 是的,但这破坏了使用内联汇编的意义,即无缝集成到编译器生成的代码。您对变量的访问也将受到限制。请参阅basic asm section in the manual
  • 不需要开关,除非你为其他方言编写汇编(例如-masm=intel)。
  • 在 gcc 中使用内联 asm 不需要额外的开关。如果您遇到问题,请发布您的代码。
  • @fuz,虽然这个问题专门询问“clobber 列表”,但我认为它实际上也是在询问操​​作数列表。 (换句话说,我认为这个问题混淆了语法的哪一部分是clobber列表。)
  • 回答问题按书面形式(忽略可能对clobber list 含义的混淆):是的,几乎没有我的内联程序集使用clobber 列表,因为它只修改分配给输出操作数的寄存器。

标签: gcc assembly x86 clang inline-assembly


【解决方案1】:

除了__attribute__((naked)) 函数的主体之外,基本上不建议将 GNU C Basic 内联 asm 语句(无操作数/clobber 列表)用于任何内容。 Why can't local variable be used in GNU C basic inline asm statements?(也不能安全地使用全局变量。)

https://gcc.gnu.org/wiki/DontUseInlineAsm 说要查看ConvertBasicAsmToExtended,原因是不使用基本 asm 语句。在 Basic asm 中你不能真正安全地做任何事情;甚至asm("cli"); 也可以使用不是volatile 的任何内存访问重新排序。

如果你打算使用 inline asm(而不是在 asm 中编写一个独立的函数,或者用内在函数编写 C),你需要描述你的 asm 字符串以带有输入和/或输出操作数和/或破坏器的黑匣子的形式向编译器提供详细的指令。请参阅 https://stackoverflow.com/tags/inline-assembly/info 获取指南链接,包括一些关于使用输入/输出约束的 SO 答案。

在决定是否真的值得将 GNU C 内联汇编用于任何事情之前,请三思而后行。如果您可以让编译器以另一种方式发出相同的指令,那几乎总是更好。内在函数或纯 C 语言允许不断传播优化;内联 asm 不会(除非您执行 if(_builtin_constant_p(x)) { pure C version } else { inline asm version } 之类的操作)。


Intel 语法:在 GCC 中,使用 -masm=intel 编译,因此您的 asm 模板将成为 Intel 语法 .s 的一部分,并且编译器将替换 Intel 语法中的操作数。 (比如dword ptr [rsp] 而不是(%rsp) for "m"(my_int))。

在 clang 中,我不确定在正常的 asm 语句中是否有任何方便的方法来使用 Intel 语法。


如果您不关心高效的代码(但是为什么要使用 asm?),还有另一种选择:clang 支持 -fasm-blocks 以允许类似于 MSVC 低效的内联 asm 样式的语法。 是的,这使用了 Intel 语法。

Is there any way to complie a microsoft style inline-assembly code on a linux platform? 显示了生成的代码是多么低效:充满了编译器生成的指令,用于将输入变量存储到内存中,以便asm{} 块读取它们。因为 MSVC 样式的 asm 块不能在寄存器中进行输入或输出。 (Clang 不支持 leave-a-value-in-EAX 方法来获取单个值,因此还必须存储/重新加载输出。)

你不能为此指定clobbers,所以我假设一个asm块意味着一个"memory" clobber,以及你写的所有寄存器上的clobbers。 (或者甚至只是提及。)

我不会推荐这个;基本上不可能以这种方式有效地包装单个指令或少数指令。只有在编写整个循环时,才能分摊将输入输入到 asm{} 块中的开销。

【讨论】:

    猜你喜欢
    • 2011-09-16
    • 2018-07-09
    • 1970-01-01
    • 2012-08-12
    • 2012-10-20
    • 1970-01-01
    • 1970-01-01
    • 2013-07-23
    • 1970-01-01
    相关资源
    最近更新 更多