2009-04-21 45 views
3

我入侵了一个下面的代码:如何制作跨平台的C++内联汇编语言?

unsigned long long get_cc_time() volatile { 
    uint64 ret; 
    __asm__ __volatile__("rdtsc" : "=A" (ret) : :); 
    return ret; 
} 

它适用于G ++而不是在Visual Studio中。 我该如何移植它? 什么是正确的宏检测VS/g ++?

回答

3
#if defined(_MSC_VER) 
// visual c 
#elif defined(__GCCE__) 
// gcce 
#else 
// unknown 
#endif 

我的内联汇编技能生疏,但它的工作原理是:

__asm 
{ 
// some assembler code 
} 

但只使用RDTSC你可以使用内部函数:

unsigned __int64 counter; 
counter = __rdtsc(); 

http://msdn.microsoft.com/en-us/library/twchhe95.aspx

+0

谢谢! 是否有intrinsics rdtsc的linux变种? – 2009-04-21 11:12:57

2

在VC++中有一个_MSC_VER宏,在MSDN中被描述为“Microsoft specific”,并且在其他编译器上编译代码时,可能没有定义它。您可以使用#ifdef来确定它是什么编译器,并为gcc和VC++编译不同的代码。

#ifdef _MSC_VER 
    //VC++ version 
#else 
    //gcc version 
#endif 
2

使用RDTSC指令直接有一些严重的缺陷:

  • 的TSC上无法保证所有CPU进行同步,因此,如果您的线程/进程从一个CPU核心迁移到另一个TSC可能会出现“ warp“,除非您使用线程/进程关联来防止迁移。
  • TSC不能保证以恒定速率前进,特别是在启用电源管理或“C1时钟上升”的PC上。使用多个CPU时,这可能会增加偏移量(例如,如果您有一个线程正在旋转,另一个线程正在休眠,则一个TSC可能比另一个更快)。
  • 直接访问TSC不允许您利用HPET

使用操作系统计时器界面较好,但仍可能有一些依赖于实现同样的弊端:

而且请注意,Microsoft Visual C++在针对64位处理器时不支持内联汇编,因此Virne指出的__rdtsc()内在。

+1

或者更好地使用像http://www.dre.vanderbilt.edu/Doxygen/Stable/ace/classACE__High__Res__Timer.html – lothar 2009-04-21 15:23:52

2

具体问题OP有题外话:我找到了一种方法来定义,对于这两种语法版本工作的宏:

#ifdef _MSC_VER 
# define ASM(asm_literal) \ 
     __asm { \ 
      asm_literal \ 
     }; 
#elif __GNUC__ || __clang__ 
# define ASM(asm_literal) \ 
     "__asm__(\"" \ 
      #asm_literal \ 
     "\" : :);" 
#endif 

不幸的是,因为预处理器strips newlines before macro expansion,你必须围绕这个宏观每个汇编语句。

float abs(float x) { 
    ASM(fld  dword ptr[x]); 
    ASM(fabs    ); 
    ASM(fstp dword ptr[x]); 

    return x; 
} 

但请注意,GCC和铛use AT&T/UNIX assembly synax但MSVC usees Intel汇编语法(找不到但任何官方消息)。幸好GCC/clang也可以是configured to use Intel syntax。使用__asm__(".intel_syntax noprefix");/__asm__(".att_syntax prefix");(确保重置更改,因为它会影响所有程序集从该点开始生成,甚至是由编译器从C源生成的程序集)。这将使我们有这样一个宏:

#ifdef _MSC_VER 
# define ASM(asm_literal) \ 
     __asm { \ 
      asm_literal \ 
     }; 
#elif __GNUC__ || __clang__ 
# define ASM(asm_literal) \ 
     "__asm__(\".intel_syntax noprefix\");" \ 
     "__asm__(\"" \ 
      #asm_literal \ 
     "\" : :);" \ 
     "__asm__(\".att_syntax prefix\");" 
#endif 

或者你也可以用GCC /铛使用-masm=intel标志,全球切换语法编译。