質問
私は最近、FPUスタックのオーバーフローでいくつかの問題を抱えています。私はそれをなんとかバギーライブラリ関数に戻しました。バギーライブラリ関数は、呼び出されるたびにゴミ値をFPUスタックに押し上げ、決してクリーンアップしません。
幸いなことに、これは簡単に再現でき、どの条件が原因であるかを正確に知っています。インラインASMのブロックをルーチンにドロップし、このルーチンを呼び出してFPUスタックから最上位の値をポップします...何を書くべきかわからないことを除いて。私のASM-FUはミッドリンに公平ですが、そうではありません それ 強い。
それでは、X86アセンブリのFPUスタックの最高値を取り除く最も簡単な方法は何ですか。それがゴミデータであり、私が値を気にしないと仮定していますか?
解決
スタックを調整する必要があるかどうかを知っている場合は、使用できます fincstp
. 。あなたもしたいです ffree
あなたが増やすレジスタ。
ただし、おそらく最も簡単な解決策は、次のようなポップデータ転送操作の1つを使用することです fstp
. 。通常、結果を後で使用するためのメモリの領域に保存します。
mem_area: defs 10 ; ten bytes for 80 bits
fstp mem_area ; pop it
しかし、あなたが価値を捨てたいだけであることを知っているなら、あなたは使用することができます st(0)
目的地としてのそれ自体、メモリ要件を保存します。
fstp st(0)
他のヒント
Delphi/BASMの場合、私の見解では、FPUスタックを1回ポップする最も簡単な方法は次のとおりです。
asm
fstp st(0)
end;
もしも st0
使用中の唯一のx87レジスタは、次のことを空にすることができます。
ffree st0
ただし、これは、使用中の複数のスタックレジスタがある場合、通常のポップとは異なります。これは、スタックの最上位ポインター(X87ステータスワードの上部フィールド)を調整しないためです。
見る Simply FPU X87チュートリアルのレジスタの章.
st1
まだあるでしょう st1
解放後 st0
ポップする代わりに、これは通常あなたが望むものではなく、重要な利点はありません fstp st0
.
ポップする(高速)命令でスタックからポップしてください。8087命令セット
それがうまくいかない場合、Fucomppは2回ポップします。