2013-03-12 53 views
1

我想編譯另一個項目的代碼,我一直在收到Error: invalid instruction suffix for 'cmpxchg'。的錯誤持續指着這行代碼是:錯誤:無效的`cmpxchg'指令後綴

inline bool CAS(long *ptr, long oldv, long newv) { 
    unsigned char ret; 
    /* Note that sete sets a 'byte' not the word */ 
    __asm__ __volatile__ (
       " lock\n" 
       " cmpxchgq %2,%1\n" 
       " sete %0\n" 
       : "=q" (ret), "=m" (*ptr) 
       : "r" (newv), "m" (*ptr), "a" (oldv) 
       : "memory"); 
    return ret; 
} 

我,不知道是否有人知道這可能是錯誤的原因是什麼可能的解決方案?

+3

你正在編譯一個64位程序嗎? – nneonneo 2013-03-12 23:01:49

+0

我下載了從學術團體的項目,他們不提它是64位或不 – Hank 2013-03-12 23:03:14

+0

'q'後綴意味着四字 - 64位數量。我懷疑它會在32位模式下編譯。嘗試編譯程序作爲64位(GCC'-m64'編譯器標誌) – nneonneo 2013-03-12 23:03:56

回答

2

正如評論者所說,問題在於cmpxchg末尾的'q'。彙編程序使用指令後綴字符來表示位寬,否則它會不明確。

此代碼編譯細用gcc對於一個64位的目標。你得到這個輸出爲你的cmpxchgq指令。

f0 48 0f b1 16   lock cmpxchg %rdx,(%rsi) 

f0是LOCK前綴,48是REX.W前綴。真正的操作碼是0f b1。

編譯32位目標(gcc選項-m32)會導致後綴錯誤。

如果您需要此代碼以在32位機器上工作,那麼您在此處有一個移植頭痛的問題。 sizeof(long)在64位機器上爲8,在Linux上爲32位機器上爲4。 如果這是一個很大的假設,整個程序足夠靈活以容忍從8字節到4字節的「長」,只要將'q'後綴更改爲'l'情況L)。這給你「0F B1」的指令,在它的32位形式:

f0 0f b1 16    lock cmpxchg %edx,(%esi) 

如果沒有,那麼你可以嘗試重寫大會的32位目標使用CMPXCHG8B這是一個不同的指令有不同註冊觸摸行爲。 CMPXCHG8B不是替代品!

+0

你沒有移植頭痛 - 只是嘗試,改變指令'cmpxchg'與'GCC -m64'和'GCC編譯-m32'既看個究竟。不,在這種情況下它不是不明確,因爲操作數大小是32位和64位的完整寄存器寬度,這是使用內聯彙編的方式--32位/ 64位上的「sizeof(long)」是不同的。 – 2013-03-13 09:43:23

+0

誠然,雖然,這個代碼不_perfectly_移植到所有可想到的操作系統的ABI因爲對於32位和64位在'long'的大小差異,不能保證(通過C/C++語言標準)。對於x86/64上的UN * X來說是這樣的,它使用ILP32/LP64(意思是「int」,「long」和「... *」在32位模式下是32位,但在64位模式下是「長」 '... *'是64位)。它在Windows上與ILP32/IL32P64不同,所以在64位模式下,'int'和'long'是32位,而指針是64位。 – 2013-03-13 09:53:31