5

如果您正在编写一个对延迟非常敏感的应用程序,那么在 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-CC

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

4

2 回答 2

3

我想回答子问题:

它导致的问题多于解决的问题,或者对于特定的小任务是否可以接受?

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

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

作为一个轶事参考,我想看看 Linus Torvalds 的这篇文章,它与 SHA1 的 git 实现有关,它优于 libcrypt 中手动优化的 SHA1。

事实上,我认为现在内联汇编器的唯一合理用途是调用处理器指令,否则这些指令是不可用的(你引用的指令是可用的,例如在 linux 上clock_gettime,至少如果你只在高分辨率时间计数器之后)或者如果您必须做一些需要欺骗编译器的事情(例如在实现外部函数接口期间)。


关于片段和其他人所说的话。尤其是使用此类功能,您将获得性能损失。在 inline asm 中,您必须非常小心将寄存器保持在编译器假定它们的状态(如上所示)。而如果您正常编写代码,编译器可以小心并准确地保留那些在寄存器中有意义的变量以及那些不适合堆栈的变量。

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

于 2012-12-11T20:39:16.647 回答
1

如果有问题的 asm 将它使用的任何寄存器推送到顶部,然后将它们弹出到底部,我认为您可以放心,不必担心。

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

我想,真正的答案是,您需要对 asm 的功能有足够的了解,以确保您可以将其视为黑匣子。:)

于 2012-12-11T20:20:59.533 回答