
前回まで8087FPUの浮動小数を扱う命令ばかり練習してきました。でもFPUにも整数をロード/ストアする命令があるのです。しかし整数を演算する命令というのは不在。FPUレジスタにロードしてしまえばどんな整数も強力なテンポラリReal型に収まってしまうみたいです。今回はその様子を前回やったFXTRACT命令使って観察。
※「ぐだぐだ低レベル プログラミング」投稿順indexはこちら
※実機動作確認(といってもエミュレータなんだけれども)には以下を使用させていただいております。
整数ロード命令
整数のロード命令として、浮動小数のロード命令のニーモニック FLD に一文字を挿入した以下の2つの命令が存在します。
-
- FILD、通常のバイナリ整数(2の補数)ロード
- FBLD、BCD形式の整数ロード
今回はフツーの整数ということでFILD命令だけ練習です。「パックド」なBCD(バイナリ・コーデッド・デシマル)整数はフツーの整数を一通りやったあとね。
FPUが取り扱える2の補数の整数型は以下のようです。なお、x86の場合、ワードは16ビットのことなのでお間違えなく。
-
- ワード(16ビット)整数
- ショート(32ビット)整数
- ロング(64ビット)整数
の3とおりです。アセンブラ的にはFILD命令のオペランドに DWORD PTR(ダブルワードへのポインタ)などとポインタ修飾指定することでワード、ショート、ロングのオペランド選択が行えます。
今回実験のプログラム
今回はFILD命令で、メモリ上に置かれた整数(当然、いつもの整数デス。CPU側で読んでも同じ整数値に見えるもの)をFPUのレジスタスタックにロード後、前回も使ってみたFXTRACT命令を発行し、仮数部と指数部に分離してその値を眺めてみます。
-
- ロードする整数値は 55771、ただしポインタはDWORD PTRで指すので「ショート(32ビット整数)」扱い
なお以下は「強力なx86用アセンブラNASM」用のソースです(MSのMASMともインテルASM86とも微妙に異なるけど、まあ分かるっしょ。)
%use fp segment code ..start: mov ax, data mov ds, ax mov ax, stack mov ss, ax mov sp, stacktop test: mov bx, src1 fild dword [bx] fxtract fin: mov ax, 0x4c00 int 0x21 resb 2048 segment data align=16 resb 1024 * 63 src1: dd 55771 segment stack class=STACK align=16 resb 2048 stacktop: dw 1024 dup (0) stackend:
アセンブルして実行
MS-DOS互換で機能強化されているフリーなFreeDOS上、以下のステップで上記のアセンブラソース fild.asm から実行可能なオブジェクトファイルを生成して実行することができます(nasmとwatcom Cがインストール済であること。)
なお、FreeDOS付属の「debugx」デバッガは、8087のレジスタ内容を浮動小数で見せてくれます
nasm -f obj -l fild.lst fild.asm wlink name fild.exe format dos file fild.obj debugx fild.exe
まずは、FILD命令でBXレジスタで指定されているメモリ上の32ビット「ショート整数」をロードするところ。
FILD命令のオペランド指す、DS:FC00=0000D9DB(16進)は、10進に直すと55771です。FILD実行後、FPUのレジスタスタックのST0に「55771」という「整数相当」なピッタンコな値が入ってます。
緑色の箱のST0に仮数部、ST1に指数部(下駄履き無)が格納されてます。整数ロードしたけれどもFPUレジスタ的には
1.7019958496093750 * 2^15
という浮動小数点数値がロードされたのと等価です。念のためにWindowsの電卓で検算すれば以下のごとし。2の15乗は32768ですぞ、念のため。
確かに「ピタリ」の整数と等価な値。お陰で浮動小数点数でも整数でも演算は思いのままだと。