2012-01-05 7 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上のMinGW GCCを使用して

+0

ダブル結果= sqrt1((ダブル)10)が通話をいWindowsの規則では、レジスタST0またはFP0に浮動小数点数が返されますか? – rsaxvc

+0

コンパイラフラグは何ですか? – rsaxvc

+0

私は、不必要にスタックに戻ってきて、リターンも実装する必要がないようにします。スタックにフラッシュすると、精度が80ビットx87の代わりに64ビットの倍精度にトリミングされます。 (スピードのためにこれをしているのなら、もっと必要です;学習のためには、Carlの答えが私のために解決しました)。 – rsaxvc

答えて

-2

メモリ位置を指定する "= 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と同じエラーがあります。実際、私はclangを使っているので、「あいまいな命令には明示的な接尾辞が必要です( 'flds'、 'fldl'、または 'fldt'とすることができます)。 –

+0

ありがとうございますが、まだ問題はありません。それはコンパイルされ、素晴らしい実行されているようだが、私は返された値をその0.0だけ印刷し、それが周囲のどのコードでもファンキーなことをするようだ。 'int main(){ \t double number = 5.12343; \t printf( "%f%f"、数値、asmSqrt(144.0)); \t getchar(); } ' これを実行すると、関数は巨大なlong floatを返します。 リンクに感謝します。これまでに見た他のウェブサイトよりずっと優れたさまざまな制約を説明しました。とても有難い。 – Dan

+0

十分です。おもちゃの例は学習目的には良いです。 :)あなたは[ここ](http://gcc.gnu.org/onlinedocs)から適切なマニュアルを選択し、目次で "制約"を検索することをお勧めします。 - t制約はマシン固有の部分にリストされています。特にasmと一般的なx86浮動小数点スタックの使用法について説明している(その直前の)セクションもあります。 – ams

3

明示的にしたいfldfst命令バリアントを指定する必要があります。さもなければ、コンパイラは、あなたのオペランドがどれくらいの大きさであるかを知らない。このコードは、ここに私の作品:

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

あなたがダブルチェックするために、64ビットFLDとFST(DD/0DD/2)のための右のオペコードが放出なっていることを逆アセンブラを使用することができます。

+0

私はこのコードを試しても、それはまだ動作しません:/それはコンパイラで何かできる? – Dan

+0

私は、GCCがインラインアセンブリーをかなり成功裏に処理できることを確信しています。私はMinGWを持っていないので、環境に関係するかもしれません。申し訳ありませんが、この回答は役に立たなかった! –

+0

私は自分のLinuxマシンでそれを実行してコンパイルして、あなたのソリューションは完璧に動作したので、MinGWの中に何か入っているはずです。皆さん、ありがとうございました。 編集:Windowsでは、前述のようにサイズを指定して、oのメモリ制約を使用する必要がありました。なぜ私はそれをもっと早く試してみたいと思っていなかったのか知りません:)私を助けてくれた皆さんにもう一度感謝します! – Dan

1

まず、これはどうしてですか?コンパイラは平方根自体を行うことができます。あなたは適切な数学ライブラリ関数を呼び出し、最適化を有効にして(インライン標準関数をインライン化する)、あなたが望むことをしなければ驚くでしょう。結果はプラットフォームに依存しません(必要な場合は64ビット、他のアーキテクチャ全体を構築することもできます)。コードを簡単に保守できます。

あなたはそれを苦労して行う上で主張する場合、gccはまた、(私は実際にこれをテストしていませんでした)ここに助けることができる:

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

t制約手段が浮動の上に価値を置きますポイントスタック - それがどのようにそこに到達するか気にする必要はありません。 +は、入力と出力の両方に値を使用することを意味します。

編集:ああ、あなたは自身が、あなたがより良い「切り詰め」セクションでそのことについてコンパイラに指示していたか、あなたはそれがそこに格納されたものを上書きする可能性があるレジスタで物事を入れたいん場合。

+0

学習目的。私は、私が投稿したコードを使用して私はこのエラーを取得し続けている他のアセンブリコードがあります。私はfsqrt命令を単離しました。なぜなら、それをidivのようなものに置き換えることができ、うまく動作するからです。しかし、作業コードに感謝します。 – Dan

0

ダブルsqrt1(ダブルN) { FSQRT __asm { FLD N } }

呼び出し方法:例