ぐだぐだ低レベルプログラミング(218)x86(16bit)、浮動小数点数のテスト

Joseph Halfmoon

前回は8087での浮動小数点数の比較結果を8086のフラグに反映させて分岐する練習でした。今回は比較でなくテストです。8087のレジスタスタックのトップに置かれている浮動小数値が、正なの負なのゼロなの?と調べる命令。でもメンドクセーことに「比較不能」という分類もこれあり。浮動小数だもんね。ようやくNaN登場。

※「ぐだぐだ低レベル プログラミング」投稿順indexはこちら

※実機動作確認(といってもエミュレータなんだけれども)には以下を使用させていただいております。

    •  Windows 11 PC (i5-1235U)
    •  Ubuntu 24.04 LTS on WSL2
    •  QEMU 8.2.2
    •  FreeDOS 1.3

※オリジナルの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

まずはプログラムの逆アセンブルリストから。uFTST

赤枠のところで π(正の浮動小数値)を判定、青枠でπの符号反転(当然負)を判定、黄枠でゼロを判定、緑枠でメモリ上においたNaNを拾ってきて、これはダメだと判定するという目論見であります。

まずは値πのロードから。FLDPI

そのFTST。FTST_1

SW(ステータスワード)の値は目論見通りなのだけれど、事前準備なく、フラグが変わった様子が目に見えないのがイマイチ。

つづいて符号反転。FCHS

πから-πになっておりますぞ。そこでFTST。FTST_2

今度はSWの値が変わりました。ビット8(C1)が立ってます。ネガティブの証拠よ。

つづいてスタックトップにゼロを。FLDZ

ここはロード命令なので、さきほどの-πの「上」にゼロが載せられてスタックが伸びます。

その判定。FTST_3

C3=1、C2=C1=0となってますな。

さて最後にお待ちかねのNaNのロードとその判定。FTST_NaN_EC

これまたロード命令なので、スタックはさらに伸び、ゼロの上にNaNがロードされます。それをFTSTで検査しているので、結果は「比較不能」。目論見通り。良かった。

ぐだぐだ低レベルプログラミング(217)x86(16bit)、浮動小数点数の比較と判断

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です