从GCC 4.5后的版本开始,现在同时支持MSVCthe 100 intrinsic和GCC.
但是所需的包含内容是不同的:
#ifdef _WIN32
#include <intrin.h>
#else
#include <x86intrin.h>
#endif
以下是GCC 4.5之前的原始答案.
直接从我的一个项目中提取:
#include <stdint.h>
// Windows
#ifdef _WIN32
#include <intrin.h>
uint64_t rdtsc(){
return __rdtsc();
}
// Linux/GCC
#else
uint64_t rdtsc(){
unsigned int lo,hi;
__asm__ __volatile__ ("rdtsc" : "=a" (lo), "=d" (hi));
return ((uint64_t)hi << 32) | lo;
}
#endif
这GNU C Extended asm告诉编译器:
volatile
:输出不是输入的纯函数(所以它每次都必须重新运行,而不是重用旧结果).
"=a"(lo)
和"=d"(hi)
:输出操作数为固定寄存器:EAX和EDX.(x86 machine constraints).x86rdtsc
指令将其64位结果放在edX:EAX中,因此让编译器 Select 带"=r"
的输出是行不通的:没有办法要求CPU将结果转到其他任何地方.
((uint64_t)hi << 32) | lo
-零-将两个32位的一半扩展到64位(因为lo和hi是unsigned
),并将它们一起逻辑Shift+OR运算为单个64位C变量.在32位代码中,这只是一种重新解释;值仍然只保留在一对32位寄存器中.在64位代码中,您通常会得到实际的Shift+OR ASM指令,除非高半部分被优化掉.
(编者按:如果您使用unsigned long
而不是unsigned int
,这可能会更有效率.那么编译器将知道lo
已经被零扩展到RAX.它不会知道上半部分是零,所以如果它想要以不同的方式合并,|
和+
是等价的.从理论上讲,只要让优化器做好工作,内在机制应该给您带来两全其美的效果.)
如果你能避免的话.但是,如果您需要了解使用内联asm的旧代码,以便可以使用intrinsic重写它,那么希望本节很有用.另见https://stackoverflow.com/tags/inline-assembly/info