内联汇编有哪些 "real-life" 用途?

What are some "real-life" uses of inline assembly?

有什么我们可以在汇编中做而在原始 C 中不能做的事情吗?或者任何在组装中更容易做的事情?是否有任何现代代码实际上是使用内联汇编编写的,或者它只是作为遗留或教育功能实现的?

内联汇编(以及相关说明,调用纯汇编编写的外部函数)可能非常有用或绝对必要,原因包括编写设备驱动程序、直接访问硬件或语言中未定义的处理器功能,硬件支持的并行处理(相对于多线程),例如 CUDA、与 FPGA 的接口、性能等

这也很重要,因为有些事情只有通过“低于”标准(C++ 和 C)提供的抽象级别才能实现。

标准承认有些事情本质上是实现定义的,并且在整个标准中都允许这样做。这些津贴之一(也许是最低级别)是对 asm 的认可。嗯,“有点”认可:

在 C (N1256) 中,它位于“通用扩展”下的标准中:

J.5.10 The asm keyword
1 The asm keyword may be used to insert assembly language directly into the translator output (6.8). The most common implementation is via a statement of the form:

asm ( character-string-literal );

在 C++ (N3337) 中,它有类似的警告:

§7.4/1
An asm declaration has the form

asm-definition:

asm ( string-literal ) ;

asm声明是有条件支持的;它的含义是实现定义的。 [ 注意:通常它用于通过实现将信息传递给汇编器。 —尾注]

应该注意的是,近年来的一项重要发展是,尝试通过使用内联汇编来提高性能通常会适得其反,除非您确切地知道自己在做什么. Compiler/optimizer 注册使用决策、流水线意识和分支预测行为等,对于大多数用途几乎总是足够的。

另一方面,近年来的处理器增加了 CPU 级对更高级别操作(例如 Intel 的 AES 扩展)的支持,可以将专用应用程序的性能提高几个数量级。

所以:

遗留功能?一点也不。对于某些需求来说是绝对必要的。

教育特色?在一个理想的世界中,只有伴随着一系列的讲座来解释为什么你可能永远不需要它,以及如果你确实需要它,如何尽可能地将它的可见表面积限制在你的应用程序的其余部分。

您还需要使用内联 asm 进行编码 when:

  • 您需要使用一些在标准 C 中不可用的处理器功能;通常,带进位机器指令的加法在 bignum implementations like GMPlib

  • 中很有用
  • 在当前 optimizing compilers 的当今处理器上,出于性能原因,您通常不应该使用 asm,因为编译器比您优化得更好(一个旧示例正在实现 memcpy 与 x86 上的 rep stosw).

  • 当您使用或实现不同的 ABI. For example, the runtime system of some Ocaml or Common Lisp implementations have different calling conventions, and transitioning to them may require asm; but the current libffi(使用 asm)时,您需要一些 asm 可能会避免您使用 asm

  • 您的全新硬件可能有最近的 instruction set not fully implemented by your compiler (e.g. extensions like AVX512...),您可能需要 asm

  • 您想实现一些 C 语言无法实现的功能,例如backtrace

一般来说,使用asm前要三思而后行,如果真的要用,也应该用在极少数的地方。一般来说,避免使用 asm.....

GCC compiler introduced an extended asm feature which has nearly become a de facto standard supported by many other compilers (e.g. Clang/LLVM...) - but the evil is in the details. See also the GCC Inline Assembly HowTo

Linux kernel (and the many libc implementations, e.g. glibc or musl libc, etc...) is using asm (at least to make syscalls) 但很少有主要的自由软件也(直接)使用 asm 指令。

另请阅读Linux Assembly HowTo