前回はピン配置のみから8080、8085、Z80のハードウエアの違いというか、設計思想?について勝手なことを書きました。今回はレジスタ一覧から8080、Z80そして8086について語りたいと思います。8085が居なくなった?レジスタ的には8080と8085はクリソツだからっす。代わりに16ビット8086を比較すると。
8086は現在のパソコンの多くに搭載されているインテル/AMD製のx86_64系プロセッサの直系の御先祖にあたる16ビット・プロセッサです。拡張に次ぐ拡張の結果、今じゃ64ビットCPUになっていますが、その始まりは16ビットだったのでした。それどころか当時のベストセラー8ビット「8080」のソフトウエアの継承をかなり意識して作られた16ビットです。そのおかげで8086のレジスタセットは8080とすごく良く似ています。8086発売当初のインテルは8080用のアセンブラソースを8086用に変換するコンバータソフトウエアを売っていたくらいです。どのくらい売れたのかは知らんけど。
また1980年代を中心に8080の「後継」としてベストセラーになったZilog社Z80は、8080とソフトウエアコンパチ(バイナリが何の修正もなく走る)が売りでした。当初は単一電源の8080的な立ち位置。しかし独自に拡張を遂げており、後にはZ80特有の命令を使うソフトも増えたのでした。ただ残念なことにZilog社の16ビット、Z8000はZ80との互換性が無く余り売れなかったようです。やっぱりZ80とコードコンパチでないと、と気づいてその方向に舵を切った後継機種も登場するのですが後の祭り。
先ずは8080の「汎用レジスタ」部分を見る
まずは8080の「汎用レジスタ」部分を見てみます(当時はそういう言い方しなかった気がするけど。)8080は8ビット機で、物理的には、A、B、C、D、E、H、Lの7本の8ビットレジスタを持っていました。それにプラスして条件フラグを集めたものをFというお名前でレジスタとして扱ってもいます。それら物理レジスタが以下に。
一方、アセンブラの命令セット的には、A、B、C、D、E、H、Lの7本に加え、Mという名の「レジスタ」が使えるようになっていました。M=メモリです。HとLのレジスタをペアにしてHLの16ビットでアドレスを指定できるメモリの内容をMという名を介して読み、書き、演算(CISCだぜ、メモリ相手に演算できるのよ)できたのです。なお当然ですが、Hの方が16ビットアドレスのハイ側、Lが16ビットアドレスのロー側です。
8080はこのレジスタペアというのが幅を利かせていて、各種の命令やアドレシングで活躍します。またHLに格納する16ビットアドレスを計算するために、BCペアやDEペアと限定的な16ビット演算もできました。さらにスタック操作の際には16ビットのレジスタペアでスタックに出し入れするようになっていました。その際、AレジスタにはF「レジスタ」がペアになっており、PSW(プログラム・ステータス・ワード)という名前でAFペアをまとめて出し入れする仕組みにもなっています。
上記の8080レジスタのイメージはそれら「レジスタペア」を踏まえた配置です。
なお、Fの中の個別のフラグ配置についても覚えておいてください。緑っぽい部分は実体フラグのあるところで、オレンジっぽいところはフラグが存在しないところです(8080のときに「たまたま」読める0、1をオレンジの部分に書き入れてますが後継機種では保証されてない筈。)
8080の「汎用レジスタ」部分とZ80のそれを比べる
さて、8080とのオブジェクトコードのコンパチビリティを維持したZ80のレジスタセットの「汎用レジスタ」部分は以下です。倍になっている!
Z80は8080とまったく同じように見えるレジスタセットを2組持っています。この片方の組の上で8080とまったく同じ機械語命令を実行できるのです。もう一方は日本では「裏」レジスタと呼ばれてました。Z80固有の「レジスタセットを表裏ヒックリ返す」命令があり、それを使うと表と裏をヒックリ返せたのです。後は8080と同じ命令で動きます。表裏同時には使えません。このような機構を採用したのは、高速な割り込みを実現するためであったようです。8080で割り込まれた場合、割り込みルーチンで使用するレジスタをスタックに退避する時間が必要であったのに対し、Z80では表裏をひっくり返せば即サービスできたと。しかし、割り込みがネストするようなケースではどうしようもないですが。。。
後に、当初の目的とは関係なく、使えるものは全部使えということで表裏を全部使うようなプログラミングも出てきましたが、正直読みずらいっす。
なお、Z80はこれ以外にも割り込みやリフレッシュのためのレジスタなども拡張されているのですが、ちょっとディープになりすぎるので今回は触れません。
8080の「汎用レジスタ」部分と8086のそれを比べる
さて、ある意味過激な方向に走ったZ80の「拡張」に比べると8086は16ビット機なのに8080クリソツです。16ビットレジスタがAX、CX、DX、BX(BXが一番後ろにあるところポイントね)と4本あるのですが、16ビットレジスタのHigh側とLow側を別々の8ビットレジスタとしてアクセスできるようにもなっているのです。
つまり、対8080的には、A=AL、B=CH、C=CL、D=DH、E=DL、H=BH、L=BLという対応関係がつけられるようになっていました。ここでABCDの順でなく、BXを最後にもってきたのは8080でメモリアドレスを置くのに多用したHLレジスタペアに相当するのが8086のBXレジスタであるからです。名前がちょっとズレてますが、役割としてはほぼほぼ8080を踏襲してます。また、Flagsと呼ばれる条件フラグを格納した16ビットレジスタの下8ビットのイメージは8080のレジスタと一致してます。そして、その下8ビットをAに相当するALとペアにすいるためにAHにコピーするという命令までもってます。その辺の「気持ち」をくみ取れる人であれば、8080のアセンブラコードを8086に書き変えるのはたやすい筈、知らんけど。
結果、8086(そして8ビットデータバス縛りの8088)は16ビットといいつつ、8ビットとの互換性(そしてお求めやすいシステムコスト)を武器にZ8000や68000を出し抜いて市場を占有していくのでありました。まあ、他の石より半年早かったというのも大きいケド。
ポインタ「レジスタ」群を比べる
さて、汎用レジスタ群は以上でしたが、特定の用途(主としてメモリアドレスをポイントする)を持つレジスタ群はどうだったでしょうか。以下の図の3列のうち、左がZ80、中が8080、右が8086です。全て16ビット幅のレジスタです。
まず真ん中の8080ですが、SP=スタックポインタとPC=プログラムカウンタの2本だけです。使い途は御存じのとおり。
次に左のZ80では、SP、PC以外にIX、IYというレジスタが増えてます。これはインデックスレジスタと呼ばれるものです。これが8080に対して「増設」されたのは、68系プロセッサが強力なインデックスアドレシングを備えているのに対し、80系はアドレシング能力が低いとディスられていたためと思われます。Z80の場合、8080の未定義オペコード2つを費やして、8080でHLレジスタペアを使ってメモリをアクセスする命令にどちらかのオペコードをつけるとHLの代わりにIXまたはIYをインデックスのベースに使い、さらに8ビットのオフセットを漏れなく付加するという方法でアドレシングモードを強化しました。命令長が2バイトも増えてしまうので、もろ手を挙げてとはいかなかったと思いますが、まあ80系だってインデックス+オフセット使えるもん、という感じ。
一方左端の8086の場合、下の方に4本ならんでいるのが「悪名高い」セグメントレジスタ4人衆です。CS=コード(プログラム)セグメント、SS=スタック・セグメント、DS=データ・セグメント、ES=エクストラ・データ・セグメントの4本です。ここに書き込まれた値を4ビット左シフトして、メモリのセグメントベースとするのです。16ビットを4ビット左シフトするので20ビット=1Mバイトの空間にアクセスできます。流石16ビット、8ビットの64Kバイトの空間の16倍もメモリが使えると。でもま、直ぐにこれが頭を抑えつける障壁になっていくのですが。
セグメントレジスタ導入により8080ではPCと呼ばれていたレジスタはIP(インストラクション・ポインタ)と改名されてます。その心はIP+(CS<<4)の位置にプログラムがあるから、ちょっとPCと違うだろ、という感じでしょうか。そのくせスタックもSP+(SS<<4)なのにお名前はSPで変わっていない。
なお、最近のコンパイラではフレームポインタとかを使わないコードを吐くことも多いかと思いますが、8086ではBPというお名前でスタックフレームをポイントするポインタも備えました。この当時はまだコンパイラ屋さんもヨワヨワだった?よってBPもSSに引っ付いてます(デフォルト、変更可能。)
もう2本のSIとDIはソースインデックスとデスティネーションインデックスです。これもインデックスレジスタなのですが固有のお役目も担ってます。8086の場合、普通にBXレジスタ等でもインデックスアドレシングは使えるのですが、それ以外に「ブロック転送」というこれまた悪名高い命令群があり、そのソースとデスティネーションを指定するための「専用」レジスタでもあるのです。SIはDS、DIはESにデフォで紐づいていた筈。
<余談>もしかするとこの時代最強のNEC-V30
NECのV30は、初期のPC98搭載CPUとして知られるNEC製のCPUです。インテルと泥沼の訴訟合戦になったことでNECは出ていく鼻先にパンチをくらうことになりました。
V30は8086の上位互換(8086のバイナリがそのまま走る)です。そう言えばということで思い出したのですが、V30は「8080互換モード」を持っていた朧げな記憶があります。本家インテルの8086はレジスタや命令を8080に似せてあるから、アセンブラレベルで頑張って変換してね、バイナリは非互換というスタンスだったのに、NEC-V30の方は8080互換モードを使えば、そのまま走らせられるよ~という機能があったような。ただね、私はこのモード使った記憶が無いデス。V30が出たときには8080互換モードなどは誰も気にしなくなっていたのか?どうなんだろ。