2013-01-24 30 views
2

我在Xcode(4.5.2)中有一個使用Debug配置生成良好的項目。但是,現在我已經切換到構建Release配置,我遇到了一個問題:我的一個內聯彙編函數出現錯誤Invalid symbol redefinition。用谷歌搜索那個錯誤信息發現我有幾個人得到了編譯器錯誤,但沒有關於它的含義的信息。這裏的功能,帶註釋的錯誤行:LLVM上的內聯ASM中的「無效的符號重定義」

inline int MulDivAdd(int nNumber, 
       int nNumerator, 
       int nDenominator, 
       int nToAdd) 
{ 
    int nRet; 

    __asm__ __volatile__ (
     "mov %4,  %%ecx \n" 
     "mov %1,  %%eax \n" 
     "mull %2    \n" 
     "cmp $0,  %%ecx \n" 
     "jl  __sub   \n" 
     "addl %%ecx, %%eax \n" 
     "adc $0,  %%edx \n" 
     "jmp __div   \n" 
    "__sub:      \n" // "Invalid symbol redefinition" 
     "neg %%ecx   \n" 
     "subl %%ecx, %%eax \n" 
     "sbb $0,  %%edx \n" 
    "__div:      \n" // "Invalid symbol redefinition" 
     "divl %3    \n" 
     "mov %%eax, %0  \n" 

     : "=m" (nRet) 
     : "m"  (nNumber), 
      "m"  (nNumerator), 
      "m"  (nDenominator), 
      "m"  (nToAdd) 
     : "eax", "ecx", "edx" 

    ); 

    return nRet; 
} 

我試着__sbt更換__sub,因爲我認爲__sub可能是一個受保護的名字,但事實並非如此。我不明白爲什麼這隻發生在發佈雖然 - 可能是由於優化?

+0

如果你用C編寫(使用'int64_t'),你會得到更好的代碼。該分支是完全不必要的(它應該是一個符號擴展和添加)。我也對使用帶符號數據的無符號乘法指令('mull')感到困擾。雖然對於有問題的程序可能無關緊要,但這可能是一個錯誤。 –

+0

@StephenCanon那麼這個俏皮話是如何與這個問題相關的呢? –

回答

11

使用局部標籤,如1:2:jxx 1fjxx 1b。跳轉的方向(f轉發或b向後)是必需的。所以,你的代碼應該是這樣的:

由純數字
__asm__ __volatile__ (
    "mov %4,  %%ecx \n" 
    "mov %1,  %%eax \n" 
    "mull %2    \n" 
    "cmp $0,  %%ecx \n" 
    "jl  1f    \n" 
    "addl %%ecx, %%eax \n" 
    "adc $0,  %%edx \n" 
    "jmp 2f    \n" 
"1:       \n" 
    "neg %%ecx   \n" 
    "subl %%ecx, %%eax \n" 
    "sbb $0,  %%edx \n" 
"2:       \n" 
    "divl %3    \n" 
    "mov %%eax, %0  \n" 
) 

符號是「局部的功能」。由於「內聯」意味着代碼在物理上是重複的,因此您得到多個符號定義的原因是您的符號確實是以「全局」方式多次定義的。當然,如果你有一個調試版本,它通常意味着「不內聯」,所以內聯函數沒有內聯,符號只聲明一次,而且它「工作」。

[我對此的效率和編譯器本身的效率有些懷疑 - 我曾認爲至少考慮使用寄存器來處理一些輸入會使效率更高]。

+0

感謝您的快速回答!至於效率,這是我一直在移植的東西,所以我只是將最初的英特爾語法ASM轉換成GAS。儘管如此,我可能會嘗試優化它。 – benwad

+0

我會試圖先將它重寫爲C,然後看看結果如何。 [我不是100%確定它做了什麼,但它看起來像是一個大數學函數的一部分 - 但這可能是完全錯誤的] –

+0

你可以解釋跳躍目標上的f和b後綴是什麼意思=) –