
前回は、8087のスタック・トップが正か負かゼロか、それとも比較しちゃヤバイやつなのかを判定するFTST命令を練習しました。しかし8087にはもっと細かくスタック・トップの素性を検査してくれる命令FXAMあり。しかし、これを理解するにはNaNだけでなく、非正規数とか無限大とか、疑似ナンタラとかヤバイ奴らが目白押しっす。
※「ぐだぐだ低レベル プログラミング」投稿順indexはこちら
浮動小数素人老人がつらつら書くに、今回は演習までたどり着きませんでした。メンドイよ~。
ゼロと疑似ゼロ
まずは与しやすいところから。ゼロです。2の補数表現の整数のゼロに正負はありませんが、浮動小数表現になると、独立した符号ビットがあるので、正のゼロ、負のゼロが存在します。しかし、ここに疑似ゼロというものもありです。
-
- 「正しいゼロ」は符号ビットを除き、指数部、仮数部ともにオールゼロ
- 疑似ゼロは符号ビットを除き、仮数部はオールゼロだが、指数部がオールゼロでない
疑似ゼロは通常は「ありえへん」表現であります。
無限大と疑似無限大
符号ビットによって、正の無限大と負の無限大があるのはゼロ同様っす。
-
- 「ただしい無限大」は符号ビットを除き、指数部はオール1、仮数部は数値表現的にはオール0。ただし内部表現としては「通常どおり」MSBは暗黙の1で他のビットはゼロ
- 疑似無限大は符号ビットを除き、指数部はオール1だが、仮数部がオールゼロ、内部表現のMSBのゼロがないケース。
疑似無限大は通常は「ありえへん」表現であります。
静かなNaN、五月蠅いNaN、疑似NaN
前回、NaNとだけ出てきましたが、NaNにもいろいろアリーので以下の3種類があります。
-
- 静かなNaN=Quiet NaN
- 五月蠅いNaN=Signaling NaN
- 疑似NaN
Quiet NaNは、反則なんだけれどもアドバンテージを見ているような感じで、即座に例外を発生させることなく、計算は進めていけるやつです。計算途中で値が確定すれば流してよし、Quiet NaNが伝播していって、いよいよダメなところまで行きつく最後でようやくレフリー介入するもの。一方Signaling NaNは、これを使って計算すると即座に例外が起こるもの。
-
- Quiet NaN、指数部オール1、仮数部は外部数値表現的にはMSBが1。内部数値表現のMSBも1。
- Signaling NaN、指数部オール1、仮数部は外部数値表現的にはMSBが0。内部数値表現のMSBは1。
- 疑似NaNは、指数部オール1、だが、内部数値表現のMSBが0。
疑似NaNは通常は「ありえへん」表現であります。
デノーマル数(非正規数)
お待ちかねデノーマル数です。通常の「ノーマル数」は符号ビット1ビット、指数部と仮数部からなります。指数部は「下駄履き」表現で2のべき乗(ゼロが下駄の真ん中で上下で正負)を表現してます。特殊な指数表現が2つあり、オール1とオール0です。オール1は上記でみたように、無限大とNaNが使ってます。オール0はゼロとこのデノーマル数が使ってます。
正規化数(ノーマル)では最小の指数部 000..01(2進)で仮数部に暗黙のMSB1(この暗黙のビットの後に仮数部の小数点がある)を置いてます。しかしデノーマル数では、指数部をオールゼロにした上で、暗黙のMSB1という規定を外してしまって、MSB側から0を詰めてます。すると仮数部表現だけで「凄く絶対値の小さい数」を表現できるよね、という方式です。当然、有効数字は落ちていきます。しかし、ゼロに限りなく近いところまで粘って計算可能っと。半世紀ほど前、計算機を習った初年度に似たような大きさの数の間で引き算するな(桁落ち)、と言われたことを思い出しますな。
このデノーマル数(非正規数)にも反逆を企てることができます。指数部がオール0であるのに、仮数部のMSBに1を持つ場合です。これが疑似デノーマル数ね。結局MSBに1があるので、指数部調整して正規化数にできるじゃん、ということらしいです。
非サポート値
インテルの古いマニュアル(1983年版)では、「デノーマル数」とは別に「アンノーマル数」という表現が出てきてとまどうのです。しかし、その後はこの表現が消滅したみたいです。無理に日本語に翻訳すると「不正規数」になる?「非正規数」と紛らわしいデス。その後の日本語解説書では「非サポート値」とかいう表現になっていたりします。多分、8087の開発がIEEE754規格制定より先行していたので、初期のマニュアルの記述が凸凹しているのかも知れません。知らんけど。上記の説明を踏まえると非サポート値というのは、普通に計算していたら出てこない筈の以下のモノドモみたいです。
-
- 疑似NaN
- 疑似無限大
- 疑似ゼロ
- 不正規数
FXAM命令
さて、FXAM命令はスタック・トップにおかれた値を以下のように判定してステータスワードのC3からC0ビットに反映させる命令です。
スタックトップの値 | C3 | C2 | C1 | C0 |
---|---|---|---|---|
+非サポート値 | 0 | 0 | 0 | 0 |
+NaN | 0 | 0 | 0 | 1 |
-非サポート値 | 0 | 1 | 0 | 0 |
-NaN | 0 | 0 | 1 | 1 |
+正規数 | 0 | 0 | 0 | 0 |
+無限大 | 0 | 0 | 0 | 1 |
-正規数 | 0 | 1 | 0 | 0 |
-無限大 | 0 | 0 | 1 | 1 |
+0 | 0 | 0 | 0 | 0 |
+Empty | 0 | 0 | 0 | 1 |
-0 | 0 | 1 | 0 | 0 |
-Empty | 0 | 0 | 1 | 1 |
+デノーマル数 | 0 | 0 | 0 | 0 |
+Empty | 0 | 0 | 0 | 1 |
-デノーマル数 | 0 | 1 | 0 | 0 |
-Empty | 0 | 0 | 1 | 1 |
ほんと、メンドクセー奴らっす。