2013-02-09 83 views
10

免責聲明:無法用言語形容我有多討厭AT & T型語法哪個內聯彙編代碼對於rdtscp是正確的?

我有,我希望是由寄存器重挫造成的問題。如果不是,我有一個更大的問題。

我使用的第一個版本是

static unsigned long long rdtscp(void) 
{ 
    unsigned int hi, lo; 
    __asm__ __volatile__("rdtscp" : "=a"(lo), "=d"(hi)); 
    return (unsigned long long)lo | ((unsigned long long)hi << 32); 
} 

我注意到沒有「重挫」的東西,在這個版本。無論這是否是一個問題,我不知道......我想這取決於編譯器是否內聯函數。使用這個版本會導致我的問題不總是可複製

下一個版本,我發現是

static unsigned long long rdtscp(void) 
{ 
    unsigned long long tsc; 
    __asm__ __volatile__(
     "rdtscp;" 
     "shl $32, %%rdx;" 
     "or %%rdx, %%rax" 
     : "=a"(tsc) 
     : 
     : "%rcx", "%rdx"); 

    return tsc; 
} 

這是令人放心的讀取和官方政策,但就像我說我的問題並不總是重複性,所以我只是想排除一個可能的原因我問題。

原因我認爲第一個版本是一個問題是它覆蓋了一個先前保存了函數參數的寄存器。

什麼是正確的......版本1或版本2或兩者兼而有之?

+7

分享你對語法的討厭。當我到達這一點時,我尋找編譯器的內部函數,或者只是把函數放在一個.s文件中,然後自己將它們組合起來...... – 2013-02-09 01:04:55

+0

@MichaelDorgan不幸的是VC++提供了一個可愛的內在的gcc。 – James 2013-02-09 01:07:10

+8

+1只是'憎恨AT&T風格的語法' – 2013-02-09 09:05:28

回答

18

這裏的C++代碼,將返回TSC和存儲輔助32位爲參考參數

static inline uint64_t rdtscp(uint32_t & aux) 
{ 
    uint64_t rax,rdx; 
    asm volatile ("rdtscp\n" : "=a" (rax), "=d" (rdx), "=c" (aux) : :); 
    return (rdx << 32) + rax; 
} 

這是更好地做shiftadd在C++中的語句合併這兩個32位的一半,而比inline,這允許編譯器安排這些指令,因爲它認爲合適。

+0

這不也是clobber ECX嗎?如果不是,我會刪除我的答案,並稱你的好。 – 2013-02-09 01:21:48

+2

是的,「= c」規範告訴編譯器ECX將保存輸出,這意味着它被破壞 – amdn 2013-02-09 01:22:50

+0

謝謝。第一個版本並沒有將'ecx'標記爲被破壞。該寄存器初始地保存了一個參數值,該參數值在一個條件中使用,如果失敗,該條件稱爲「std :: terminate()」。當這種情況發生時,情況顯然是在檢查錯誤的東西! – James 2013-02-09 16:25:09

1

根據this,此操作使EDX和ECX變得臃腫。你需要將這些寄存器標記爲第二個所做的操作。順便說一句,這是你有上面的代碼的鏈接,或者你在別處找到它嗎?它也顯示了一些其他的時間變化,以及相當整潔。

+0

錯誤的指令。它是'rdtscp',而不是'rdtsc',並且任何輸出已知會被破壞,因此不需要列出。問題是'rdtscp' *也會銷燬ecx,版本2標記爲破壞版本,但版本1不會。 – ughoavgfhw 2013-02-09 01:13:56

+0

因此,我們爲他提供了一個答案。我會清理它... – 2013-02-09 01:14:54

+0

在這裏留下這個爲其他SO鏈接可能有用 - 雖然上面的答案更好。 – 2013-02-09 01:25:15

2

我認爲你可以非常安全地參考this document,不僅要驗證,而且要更深入地分析一下RDTSCRDTSCP的準確性。

我希望這會有所幫助。