
前回は8087での浮動小数点数の比較結果を8086のフラグに反映させて分岐する練習でした。今回は比較でなくテストです。8087のレジスタスタックのトップに置かれている浮動小数値が、正なの負なのゼロなの?と調べる命令。でもメンドクセーことに「比較不能」という分類もこれあり。浮動小数だもんね。ようやくNaN登場。
※「ぐだぐだ低レベル プログラミング」投稿順indexはこちら
※実機動作確認(といってもエミュレータなんだけれども)には以下を使用させていただいております。
※オリジナルの8086+8087の組み合わせでは8086と8087の同期をとるためにWAIT命令が必用になる場合があります。後継機種ではWAIT命令が不要(演習に使用しているエミュレータQEMUでも不要)なのでWAIT命令は使用しません。メンドイし。
FTST命令
前回のFCOMP命令にくらべるとFTSTはシンプルです。引数をとったりすることもなく、実行後にスタックをポップすることもありません。ただスタックトップに置かれている数値の正負かゼロ、そして比較不能な表現なのかを判定するだけのもの。
判定結果は、前回同様、8087のステータスワードレジスタのC3、C2、C0ビットに以下のように反映されます。
スタックトップの値 | C3(14)=>ZF | C2(10)=>PF | C0(8)=>CF |
---|---|---|---|
ノンゼロで正 | 0 | 0 | 0 |
ノンゼロで負 | 0 | 0 | 1 |
ゼロ(+/-) | 1 | 0 | 0 |
比較不能 | 1 | 1 | 1 |
IEEE754規格に精通された姉貴兄貴の皆さまはよ~くご存じのとおり、2の補数表現の整数と違い、浮動小数点数には正のゼロ、負のゼロという表現もあり。そのせいか上記の表はちょいと回りくどい表現です。さらには第4のカテゴリとして「比較不能」という判定結果まであります。ここには、NaN(ノット・ア・ナンバーざんす)、無限大などのヤバイ表現どもが分類されるところです。
上記の8087のステータスワードは、前回やりましたFSTSW命令で8086のAXレジスタに転送でき、それにSAHF命令をさらに適用することで、8086のZF、PF、CFに反映させることができたのでした。よって上記表を参照していただけば、スタックトップの値の上記4分類による条件判断ができると。今回はやらんけどね。メンドイし。
FCHS命令
今回、ドサクサまぎれにFCHS命令も練習してます。浮動小数の符号をヒックリ返す命令です。
今回実験のプログラム
スタックトップに置いた数をFTST命令で、正、負、ゼロ、比較不能と4分類するフラグをたてるだけのプログラムです。フラグさえ変化すれば後は野となれ山となれと先に進める無責任な一本です。例によって強力なx86用アセンブラNASM用のソースです(MSのMASMともインテルASM86とも微妙に異なるけど、分かるっしょ。)
そんななか今回から以下のおまじないが追加されております。
%use fp
上記は、NASMに浮動小数用のマクロ共を使うからお願い、と伝えている呪文です。これが必要なのは、今回ようやく、ソースコードの中に NaN が登場するからです。NaNというマクロを呼ぶのに必要なだけね。まあ、NaNにも静かな奴と五月蠅い奴がいてとか、深みにハマる話はまた後でです。
%use fp segment code ..start: mov ax, data mov ds, ax mov ax, stack mov ss, ax mov sp, stacktop test: fldpi ftst fchs ftst fldz ftst mov bx, src1 fld dword [bx] ftst fin: mov ax, 0x4c00 int 0x21 resb 2048 segment data align=16 resb 1024 * 63 src1: dd NaN segment stack class=STACK align=16 resb 2048 stacktop: dw 1024 dup (0) stackend:
アセンブルして実行
MS-DOS互換で機能強化されているフリーなFreeDOS上、以下のステップで上記のアセンブラソース ftst.asm から実行可能なオブジェクトファイルを生成して実行することができます(nasmとwatcom Cがインストール済であること。)
なお、FreeDOS付属の「debugx」デバッガは、8087のレジスタ内容を浮動小数で見せてくれます。
nasm -f obj -l ftst.lst ftst.asm wlink name ftst.exe format dos file ftst.obj debugx ftst.exe
赤枠のところで π(正の浮動小数値)を判定、青枠でπの符号反転(当然負)を判定、黄枠でゼロを判定、緑枠でメモリ上においたNaNを拾ってきて、これはダメだと判定するという目論見であります。
SW(ステータスワード)の値は目論見通りなのだけれど、事前準備なく、フラグが変わった様子が目に見えないのがイマイチ。
今度はSWの値が変わりました。ビット8(C1)が立ってます。ネガティブの証拠よ。
ここはロード命令なので、さきほどの-πの「上」にゼロが載せられてスタックが伸びます。
C3=1、C2=C1=0となってますな。
これまたロード命令なので、スタックはさらに伸び、ゼロの上にNaNがロードされます。それをFTSTで検査しているので、結果は「比較不能」。目論見通り。良かった。