2016-02-29 96 views
0

我有跨平臺的音頻處理應用程序。它是使用Qt和PortAudio庫編寫的。我還使用Chaotic-Daw音源處理某些音頻處理功能(Vibarto效果和Soft-Knee動態範圍壓縮)。問題是,我不能口我的應用程序從Windows到Mac OSX,因爲我得到的編譯器錯誤的__asm部分(我使用的是Mac OSX的優勝美地和Qt Creator IDE 3.4.1):移植到Mac OS X錯誤

/Users/admin/My projects/MySound/daw/basics/rosic_NumberManipulations.h:69:
error: expected '(' after 'asm' { ^

這樣的線路:

INLINE int floorInt(double x) 
{ 
    const float round_towards_m_i = -0.5f; 
    int i; 

    #ifndef LINUX 
    __asm 
    { // <========= error indicates that row 
     fld x; 
     fadd st, st (0); 
     fadd round_towards_m_i; 
     fistp i; 
     sar i, 1; 
    } 
    #else 
    i = (int) floor(x); 
    #endif 

    return (i); 
} 

我該如何解決這個問題?

回答

1

該代碼明顯是爲Microsoft的Visual C++編譯器編寫的,因爲它是用於inline assembly的語法。它使用英特爾的語法,而且過於簡單,這使得它易於編寫,但阻礙了它的優化潛力。

Clang和GCC都使用不同的內聯彙編格式。特別是,他們使用GNU AT&T syntax。寫起來比較複雜,但更富有表現力。編譯器錯誤基本上是Clang告訴你的,「我可以告訴你正在嘗試編寫內聯彙編,但是你已經格式化了所有錯誤!」

因此,爲了編譯此代碼,您需要將MSVC樣式的內聯程序集轉換爲GAS格式的內聯程序集。這可能是這樣的:

int floorInt(double x) 
{ 
    const float round_towards_m_i = -0.5f; 
    int i; 

    __asm__("fadd %[x], %[x] \n\t" 
      "fadds %[adj]  \n\t" 
      "fistpl %[i]  \n\t" 
      "sarl $1, %[i]" 
      : [i] "=m" (i) // store result in memory (as required by FISTP) 
      : [x] "t" (x), // load input onto top of x87 stack (equivalent to FLD) 
      [adj] "m" (round_towards_m_i) 
      : "st"); 

    return (i); 
} 

但是,由於氣體風格的額外表現力,我們就可以將更多的工作,以內置的優化,這可能會產生更加優化的對象代碼:

int floorInt(double x) 
{ 
    const float round_towards_m_i = -0.5f; 
    int i; 

    x += x;     // equivalent to the first FADD 
    x += round_towards_m_i; // equivalent to the second FADD 
    __asm__("fistpl %[i]" 
      : [i] "=m" (i) 
      : [x] "t" (x) 
      : "st"); 
    return (i >> 1);   // equivalent to the final SAR 
} 

Live demonstration
(需要注意的是,從技術上講,這樣的最後一行做了簽名的右移是實現定義在C和通常是不可取的。但是,如果你使用內聯彙編,你已經做出了針對特定平臺的決定因此可以依賴於實現特定的行爲。在這種情況下,我知道並且很容易證明所有的C編譯器都會生成SAR指令來對帶符號的整數值進行算術右移。)

這就是說,看起來代碼的作者對於內聯彙編僅在使用當您編譯的平臺不是LINUX(大概這是Windows,他們希望您使用的是Microsoft編譯器)。所以你可以簡單地通過確保在命令行或makefile中定義LINUX來編譯代碼。

我不知道爲什麼做出這個決定; Clang和GCC都將生成與MSVC相同的低效代碼(假設您針對的是舊一代x86處理器並且無法使用SSE2指令)。這取決於你:代碼將以任何方式運行,但是如果不使用內聯彙編來強制使用這種巧妙的優化,代碼將會變慢。