在C++中嵌入汇编程序可以接受吗

Embedding assembler within C++ acceptable?

本文关键字:汇编程序 C++      更新时间:2023-10-16

如果你正在编写一个对延迟非常敏感的应用程序,那么在C++函数中嵌入汇编程序的限制是什么(通常使用C++函数调用),比如:

inline __int64 GetCpuClocks()
{
// Counter
struct { int32 low, high; } counter;
// Use RDTSC instruction to get clocks count
__asm push EAX
__asm push EDX
__asm __emit 0fh __asm __emit 031h // RDTSC
__asm mov counter.low, EAX
__asm mov counter.high, EDX
__asm pop EDX
__asm pop EAX
// Return result
return *(__int64 *)(&counter);
}

(以上功能来自我看到的另一个SO帖子)

您能像对待黑盒那样对待汇编程序内联函数吗?您能很容易地从汇编程序中进行的计算中检索结果吗?是否存在您不知道寄存器等中当前存在哪些变量的危险?它是造成的问题多于解决的问题,还是对于特定的小任务来说可以接受?

(假设您的体系结构是固定的,并且是已知的)

编辑:我刚刚发现了这个,这就是我所暗示的:

http://www.codeproject.com/Articles/15971/Using-Inline-Assembly-in-C-C

EDIT2这更针对Linux和x86——这只是一个通用的C++/汇编程序问题(或者我是这么认为的)。

我想回答子问题:

它是造成的问题多于解决的问题,还是适用于特定的小任务?

确实如此!使用内联汇编程序,您可以从编译器获得优化代码的能力。它不能进行部分表达式替换或任何其他奇特的优化。生成比编译器使用-O3发出的代码更好的代码真的非常困难。另外,下一个编译器版本的代码会变得更好(假设下一个编译版本不会破坏它;)。

编译器通常比人脑掌握的范围更广(或者应该掌握的范围,以确保理智),能够在正确的位置内联正确的函数,进行部分表达式替换,从而提高代码的效率。在ASM中你永远不会做的事情,因为你的代码变得无法读取。

作为一个轶事参考,我想参考Linus Torvalds的这篇文章,它涉及SHA1的git实现,它在libcrypt中优于手工优化的SHA1。

实际上,我认为现在内联汇编程序的唯一合理用途是调用处理器指令,而这些指令在其他情况下是不可用的(你引用的指令是可用的,例如在linux上作为clock_gettime,至少如果你只在追求高分辨率的时间计数器),或者如果你必须做一些需要欺骗编译器的事情(例如在实现外部函数接口的过程中)。


关于片段和其他人所说的内容。尤其是使用这样的函数,您将受到性能惩罚。在内联asm中,您必须非常小心地将寄存器保持在编译器假设的状态(如上所述,推送/弹出)。如果你正常地编写代码,编译器可以小心地将那些有意义的变量和那些不适合堆栈的变量保留在寄存器中。

相信你的编译器。这很聪明。大多数时候。通过不使用内联汇编程序来思考智能、快速算法和学习相关的编译器开关(例如启用SSE优化等),可以节省时间。

如果有问题的asm在顶部推送它使用的任何寄存器,然后在底部弹出它们,我认为你不用担心。

在您的示例中,这些是__asm push EAX__asm pop EAX指令。

我想,真正的答案是,你需要足够了解asm的作用,才能确保你能把它当作一个黑匣子。:)