2012-01-05 163 views
2

嘿我試圖學習如何在我的C程序中編寫彙編代碼。我理解裝配中的整數,但花車繼續讓我絆倒。C行內彙編 - 'fst'的操作數類型不匹配

double asmSqrt(double x) { 
    double o; 
    __asm__ ("fld %1;" 
      "fsqrt;" 
      "fst %0;" 
      : "=g" (o) 
      : "g" (x) 
    ); 
    return o; 
} 

正如你可以看到我只是想找到x的平方根。但是每當我嘗試編譯它時,我都會遇到操作數類型不匹配錯誤。

我跟着這裏所使用的相同的語法:http://www.codeproject.com/KB/cpp/edujini_inline_asm.aspx?display=Print

PS:在Windows XP

+0

是否主叫Windows上的約定返回寄存器ST0或FP0中的浮點數? – rsaxvc 2012-01-05 02:14:27

+0

你的編譯器標誌是什麼? – rsaxvc 2012-01-05 04:33:28

+0

我認爲會不必要地衝回棧,以避免你需要實現返回。沖刷到堆棧還可以將精度降低到64位雙精度而不是80位x87。 (如果你正在爲速度做這件事,則需要更多;如果是學習,卡爾的答案爲我解決了這個問題)。 – rsaxvc 2012-01-05 05:11:45

回答

-2

im使用的MinGW GCC指定存儲器位置 「= M」 而不是 「= G」。但最好是閱讀本手冊在這裏:http://ibiblio.org/gferg/ldp/GCC-Inline-Assembly-HOWTO.html#s4

不管怎麼說,這是解決方案:

double asmSqrt(double x) { 
    double o; 
    __asm__ ("fld %1;" 
      "fsqrt;" 
      "fst %0;" 
      : "=m" (o) 
      : "g" (x) 
); 
    return o; 
} 
+0

無法在我的機器上運行...它與OP提到有關操作數類型不匹配的錯誤相同。實際上,因爲我使用的是鏗鏘聲,所以它說:「模棱兩可的指令需要一個明確的後綴(可以是'flds','fldl'或'fldt')」。 – 2012-01-05 03:43:06

+0

謝謝你,但仍然有問題。它編譯並且似乎運行良好,但是當我打印出返回的值時,它的值僅爲0.0,並且它似乎也隨時隨地執行任何代碼。 'int main(){ \t double number = 5.12343; printf(「%f%f」,number,asmSqrt(144.0)); \t getchar(); }' 當我運行這個函數返回一個巨大的長浮點數。 並感謝您的鏈接。解釋了不同的限制比迄今爲止我見過的任何其他網站都要好得多。非常感激。 – Dan 2012-01-06 00:59:04

+0

夠公平的;玩具的例子對學習的目的很有好處。 :)我建議你從[here](http://gcc.gnu.org/onlinedocs)中選擇一個合適的手冊,並在目錄中搜索「約束」 - 「t」約束列在機器特定部分。還有一部分(就在此之前),一般講到「asm」,特別是x86浮點堆棧使用。 – ams 2012-01-06 09:18:24

3

你需要明確指定哪些fldfst指令形式你想要的。否則,編譯器不知道你的操作數應該是多少。此代碼的工作對我來說在這裏:

__asm__ ("fldl %1 ;" 
     "fsqrt ;" 
     "fstl %0 ;" 
     : "=g" (o) 
     : "g" (x) 
); 

可以使用反彙編仔細檢查,對64位的FLD和FST(DD/0DD/2)正確操作碼越來越發射。

+0

我試過這段代碼,它仍然不起作用:/它可以是編譯器的東西嗎? – Dan 2012-01-06 00:22:10

+0

我確定GCC已經能夠很好地處理內聯程序集了一段時間了。我沒有MinGW,所以也許它與環境有關。對不起,這個答案沒有幫助! – 2012-01-06 18:58:17

+0

我編譯在我的linux機器上執行它,你的解決方案完美工作,所以它必須是MinGW裏面的東西,就像你說的。非常感謝你的幫助! 編輯:在Windows上,我必須指定像你所說的大小,並使用內存約束o。我不知道爲什麼我不想早點嘗試:)再次感謝大家幫助我! – Dan 2012-01-08 01:55:09

1

首先,你爲什麼要這樣做?編譯器可以自己做平方根。您只需調用適當的數學庫函數,啓用優化(以便它將內聯標準函數),如果它不能滿足您的要求,我會感到驚訝。其結果是獨立於平臺(即,如果你願意,你可以構建64位,甚至整個其他架構),易於維護代碼 - 更好!

如果你堅持這樣做硬盤的方式,GCC還可以幫助在這裏(我沒有實際測試過這一點):

double asmSqrt(double x) { 
    __asm__ ("fsqrt" : "+t" (x)); 
    return x; 
} 

t約束手段把價值上的浮頂點堆棧 - 你不必關心它如何到達那裏。 +表示爲輸入和輸出使用該值。

編輯:哦,如果你想自己登記東西,那麼你最好告訴編譯器有關'clobbers'部分,或者你可能會覆蓋它存儲在那裏的東西。

+0

學習目的。我有其他彙編代碼,我使用我發佈的代碼,我繼續得到這個錯誤。我只是隔離了fsqrt指令,因爲我可以用像idiv這樣的東西代替它,它工作正常。但是,感謝你的工作代碼 – Dan 2012-01-06 00:28:32

0

雙sqrt1(雙N) { __asm { FLDÑ FSQRT } }

呼叫的方法,包括:雙結果= sqrt1((雙)10)例如