
前回、8087浮動小数点コープロセッサの例外について説明し「メンドイ」話も終了かと。今回こそはアセンブラの練習に戻りたい、と思ったのです。練習再開にあたり、ついては現代においても8087系の浮動小数点演算命令が残っている意義の一つである「超越関数」の計算と思ったらばまたもやコマケー話あり。SIN、COS、TANね。
※「ぐだぐだ低レベル プログラミング」投稿順indexはこちら
※2025年6月18日追記:本文中、追記や消し線で消して訂正している部分があります。この詳細についてはお手数ですが、次回記事をご参照ください。
超越関数
現代的なプロセッサ共は幅広で自由に使えるレジスタファイル上で動作できる浮動小数対応のSIMD命令セットを持っており、これを使った浮動小数演算はパフォーマンスも良いので、「加減乗除などのフツーの計算」では8087系のレジスタスタックを使う命令の出る幕はなくなっている、ように思われます(個人の感想です。)
しかし、それでも、8087系の命令を使いたくなる時があり、これが「超越関数」どもを計算(勿論近似値だけれども)するときじゃないかとおもいます。なにせ8087系は高度にマイクロコードなマシンであり、超越関数のようなメンドイ計算を実現する命令セットを持ってます。数学苦手なお惚け老人でもそいつら命令を使えば、関数電卓使うお手軽さで計算できてしまうっと。
以下に、「超越関数」を忘れてしまった「よゐこ」のためにGoogleの生成AI、Gemini様のご説明を引用させていただきます。
そしてこっからが本番。
上記でGemini様は、ガンマ函数の後にもズラズラと列挙されておりますが、お惚け老人の一存で以降省略させていただきました。皆さん、毎日お世話になっているじゃないかと思われる、指数関数、対数関数、三角関数など、皆、超越関数であります。なあんだ、普通の関数じゃん。
今回はSIN(正弦)、COS(余弦)を8087で計算する方法について考えてみたいと思います。
8087にはSINもCOSも無い
まず、衝撃の事実を書いてしまうと、8087浮動小数点コープロセッサはSINやCOSを直接計算する命令を持ちませぬ。おっと、どうするんだ。
8087の超越関数サポートの考え方(素人老人の推測ですが)は
-
- 各超越関数ども、に共通する「部品」的な関数を提供する
- 後はそれを組み合わせてプログラマ様の方でよしなに
ということみたいです。多分、8087当時の集積度で、限りあるマイクロコードROMを各種関数で埋め尽くしてしまうと収まらん、と思ったのかも知れませぬ。
しかし80387以降のFPUにはSINもCOSもある
ところが、上記の方針は「分かりズライ」と評判悪かったのかも知れませぬ。80387以降のFPUにはSIN、COSを直接計算する命令(FSIN、FCOSなど)が含まれてます。勿論、80486以降のFPUを内部に取り込んでしまったプロセッサにおいても同じです。つまり、
-
- 8087用にSINやCOSを計算するルーチンは80387以降でも使える(多分、無駄なことして効率悪いケド。)
- 80387以降向けにSINやCOSを直接求める命令をつかった「ズボラ」なプログラムは8087上では走らない。
ということになります。まあ、新しいプロセッサ向けのプログラムをわざわざ8087上で走らせるということも無さそうなので、ま、いいかという感じかと。
80287はどうよ
上記で、8087と80387以降、現代につながるところの「断絶」について述べましたが、87と387の間の287はどうなのか?前回も、8087は自力でバスサイクルを制御できるコプロ、80287と80387はCPU側に面倒みてもらい、自分は演算に「集中」するIOプロセッサと書きました。プロトコル的には80287は80387側だと思うのですが、命令セット的には、80287の命令セットは8087と(ほぼ)同じ(ちゃんと比較してないけど。)命令セットにいろいろ「テコ入れ?」が入ったのは80387以降のことみたいです。
8087、80287でSIN、COS計算する方法
8087、80287で正弦、余弦を計算するのに使う命令は以下です。
FPTAN
タンジェントを計算する命令ですな。「部分正接」命令。どこが「部分」かというと、入力θはラジアン単位でスタックトップに置いておくのですが、入力可能な範囲は
0 < θ < π/4 (8087、20287の場合)
つまり「第1象限の下半分」に限られてます。それ以外ではエラーとなるみたい。計算できる角度以外については、頭の中でグラフをパタパタとひっくり返したりすれば計算できるでしょ、という思し召しらしいです。メンドイよ~。
なお、80387以降ではこのような入力可能範囲の制限は大幅に緩和されてます。
0 < θ < π*2^62
上限に制限はあるものの、「一般角」化されて、くるくる回っても大丈夫みたい。
なお、FPTAN命令は、スタックトップに置かれた角度(単位ラジアン)を読み取って、ST(1)、スタックトップの1個下、に正接、ST、スタックトップ、に1.0を置く命令です。(追記:FSIN、FCOSはスタックトップに三角関数を求めた結果が返り、謎の1.0はありません。)
さてGoogleの生成AI、Gemini 2.5 Flash様に再びお出ましいただいて、TAN(正接)から、COS(余弦)、SIN(正弦)を計算する方法をご説明いただきます。中学でやる内容だったけ?忘却力の老人は忘れとるよ~。
なお、80387以上では、正弦、余弦を求めるための
-
- FSIN
- FCOS
- FSINCOS
という命令が存在しており、それらは全て
0 < θ < π*2^62
の入力範囲でOKです。いやあ、練習は387以降でやりたいデス(ま、練習で使わせていただいているシミュレータは586レベルなので大丈夫だと思いますケド。)