首页 > 解决方案 > 编写没有破坏列表的内联汇编?

问题描述

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

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

标签: gccassemblyx86clanginline-assembly

解决方案


GNU C Basic 内联 asm 语句(无操作数/clobber 列表)基本上不推荐用于除了__attribute__((naked))函数体之外的任何内容。 为什么不能在 GNU C 基本内联 asm 语句中使用局部变量?(也不能安全地使用全局变量。)

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

如果您打算使用内联asm(而不是在 asm 中编写独立函数,或者使用内部函数编写 C),您需要向编译器详细描述您的 asm 指令字符串,用黑色带有输入和/或输出操作数和/或clobbers的盒子。有关指南的链接,请参阅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-syntax 的一部分.s,并且编译器将替换 Intel 语法中的操作数。(喜欢dword ptr [rsp]而不是(%rsp)for "m"(my_int))。

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


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

有没有办法在 linux 平台上编译微软风格的内联汇编代码?显示了生成的代码是多么低效:充满了编译器生成的指令,用于将输入变量存储到内存中,以便asm{}块读取它们。因为 MSVC 样式的 asm 块不能在寄存器中进行输入或输出。(Clang 不支持 leave-a-value-in-EAX 方法来获取单个值,因此也必须存储/重新加载输出。)

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

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


推荐阅读