2009-04-21 75 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標誌,全球切換語法編譯。