2009-05-18 53 views
2

我們最近將代碼從gcc4.2.4升級到gcc4.3.3彙編編譯錯誤(gcc4.2.4 = win,gcc4.3.3 = fail)

void testAndSet( volatile int* s, int* val) 
{ 
    __asm__ __volatile__ ("btsl $0, %0\n " 
      "jc bitSet\n " 
      "movl $0, %1\n " 
      "jmp returnVector\n" 
      "bitSet:\n " 
      "movl $1, %1\n" 
      "returnVector: " : "=m"(*s), "=m"(*val)); 
} 

我們的代碼現在失敗,出現以下錯誤,

lock.cxx: Assembler messages: 
lock.cxx:59: Error: symbol `bitSet' is already defined 
lock.cxx:61: Error: symbol `returnVector' is already defined 
lock.cxx:59: Error: symbol `bitSet' is already defined 
lock.cxx:61: Error: symbol `returnVector' is already defined 

這些符號,未發現其他地方。 (重命名它們會導致與新名稱相同的錯誤)。

這是怎麼回事?爲什麼我會錯誤兩次?

回答

9

可能是優化程序發生了變化,現在將testAndSet()函數內聯到2個位置。因爲您正在爲標籤使用全局名稱,所以這不起作用。您應該使用本地名稱。例如:

__asm__ __volatile__ ("btsl $0, %0\n " 
      "jc 0f\n " 
      "movl $0, %1\n " 
      "jmp 1f\n" 
      "0:\n " 
      "movl $1, %1\n" 
      "1: " : "=m"(*s), "=m"(*val)); 

本地標籤只是數字;要消除多個名爲「0」的標籤的情況,您需要使用「jmp 0f」作爲前向跳轉,而「jmp 0b」作爲向後跳轉。

+0

很好。就是這樣。有趣的是,使用gcc選項-02失敗,但使用-O – user48956 2009-05-18 17:40:12

5

這無關你的錯誤,但你可以提高你的代碼,避免分支機構只需使用setCC instruction

__asm__ __volatile__ ("btsl $0, %0\n " 
     "mov $0, %1\n" 
     "setc %1\n" : "=m"(*s), "=m"(*val)); 

setCC指令(其中CC是條件碼標誌之一,類似於jCC指令)根據給定條件是否滿足將字節設置爲0或1。由於目的地是一個4字節的值,就需要或者與0預加載它,或使用MOVZX instruction使上3個字節0

1

您也可以通過後的各局部加入%=使用本地標籤名稱標籤:

「loop%=」「\ n \ t」