借り初めのひみつきち

仮ブログです。移転先募集中

x86 の汎用レジスタのルーツ

x86 の汎用レジスタは AX CX DX BX です。AX BX CX DX ではありません!
この由来について 8086 のルーツから探ってみたいと思います。

Intel 4004

Intel が初めて作った CPU は電卓を作るために開発された 4004 でした。
このことから 8086 は電卓の子孫と言われることがあります。本当なのでしょうか?

8086 の祖先は 8080 であり、 8080 の祖先は 8008 でした。
では 8008 の先祖が 4004 かというと、同時期に同じ会社が作ったものだからパッケージ技術等の多少の共通点はあるにしてもそれ以上の類似性は認められません。両者を調べれば調べるほど 8008 が 4004 の後継とは考えにくいです。
8008 の後継の 8080 が出るのと同時期に 4004 の後継の 4040 がリリースされていることなどからも両者は別のシリーズだと考えられます。

ちなみに 4004 の汎用レジスタは Accumulator とは独立した16個の4ビットレジスタがあり、偶数番号のレジスタと奇数番号のレジスタをペアにして8組の8ビットレジスタとして使える命令もあったようです。
汎用レジスタの個数も合計容量も 8008 より多いです。

Intel 8008

f:id:neriring16:20191113075713p:plain

8008 は Intel が初めて作った8ビット CPU で 8080 や 8008 の先祖になります。

8008 の機械語の基本構造は8進数です。 8bit の機械語が 2bit + 3bit + 3bit の構造になっていて、 3bit で同じグループに属する8種類の命令を指定したり、8種類(以下)のレジスタを指定したり使われました。例えば ADD, ADC, SUB, SBB, AND, XOR, OR, CMP の8種類の ALU 命令は同じグループに属した同じ構造の機械語になっています。 CPU によってニーモニックや順番は多少変わるもののこれらは 8080 を経て 8086 に現在も受け継がれている特徴のひとつです。

8008 には A B C D E H L の7つの8ビットレジスタがありました。8番目のレジスタに相当する M という仮想レジスタは後述の HL ペアレジスタで指定するメモリアクセスを指しています。

A レジスタは別名 Accumulator という ALU に直結された演算のためのレジスタで、ほとんどの演算命令は A レジスタが暗黙のソースオペランドになります。
なお、古い CPU では ALU に直結された同様のレジスタはよく使われました。

H レジスタと L レジスタは High/Low のペアになっていて、仮想レジスタ M にアクセスする命令は HL レジスタペアでメモリアドレスを間接参照するメモリアクセスに使われました。
ただし 8008 にはペアレジスタの概念がなく H レジスタと L レジスタはあくまで独立したふたつの8ビットレジスタだったので、 256 バイト境界を超えるブロック転送はかなりめんどくさかったようです。

B C D E レジスタは特に決まった用途のない一時的なデータを格納するレジスタだったようです。

8008 のスタックは CPU 内部に7レベルの固定スタックが存在していました。7つと中途半端なのはおそらく PC レジスタと合わせて8つのレジスタからマルチプレクサで切り替えるような構造になってたんじゃないかと思います。

フラグは Sign, Zero, Parity, Carry の4つあって演算の動作や分岐方法は 8080 や 8086 と大きくは変わらなかったようですが、大きな違いとしてフラグレジスタのようなまとまったレジスタが存在しないので値を直接取得したり設定したりすることはできなかったようです。

Intel 8080

f:id:neriring16:20191109030510p:plain

8080 は 8008 の後継の CPU で、汎用レジスタは 8008 と同様に A B C D E H L の7つの物理レジスタと仮想レジスタ M がありました。
バイナリは非互換ですがアセンブリソースレベルでは 8008 の上位互換があったようです。

8080 で進化した点のひとつに、ふたつのレジスタをペアにして BC DE HL という3組の仮想的な16ビットレジスタにすることで一部の命令で16ビット処理ができるようになり256バイト境界を超えるメモリ転送などの処理が楽になりました。

スタックは CPU 外のメモリに追い出されて SP レジスタで指定する現代的な方式に変わりました。ただし SP レジスタにアクセス可能な命令はかなり限定されていて汎用レジスタとはだいぶ扱いが違いました。

また、フラグがフラグレジスタ (F) という8ビットのレジスタとしてまとまり、PUSH / POP 命令のみ A レジスタとフラグ(F)レジスタを組み合わせたレジスタペア (PSW/AF) も使うことができました。*1
フラグレジスタのビット配置は現在の x86 の rFLAGS の下位8ビットとほぼ同じ内容で、謎の予約ビットはこの時代から謎の予約ビットとして存在しました。

8080 の代表的な OS として CP/M が存在しました。
CP/Mシステムコールは基本的に C レジスタに機能番号、 DE レジスタにパラメータを入れて CALL 5 で呼び出しました。

Intel 8085 / Z80

f:id:neriring16:20191109025458p:plain

8085 は 8080 の公式の上位互換 CPU で一部命令が拡張されましたが、あまり使われませんでした。

Z80 は 8080 の設計者が Intel から独立して作った CPU で 8080 とバイナリレベルでほぼ上位互換があり、たくさんの8ビットコンピュータに採用されました。

Z80 で拡張された汎用レジスタに IX, IY というメモリブロック転送のための16ビットレジスタがありました。
IX, IY レジスタデコーダ回路のトランジスタを節約するために HL レジスタのデコードを流用していたので、非公式の隠し命令を使うことで IXH, IXL, IYH, IYL のような8ビットレジスタとして使うこともできました。

Intel 8086

f:id:neriring16:20191109025510p:plain

ご存知 8086 は 8080 の後継として作られた16ビット CPU です。
8086 は 8080 と 8008 の間ほどではないですが 8080 系 CPU のソフトウェアが移植しやすいように設計されていました。

8086 の汎用レジスタは8個の16ビットレジスタがありました。そのうち半分は4組の8ビットレジスタペアとして使うこともできました。

4組の16ビットレジスタペアはそれぞれ役割 (Accumulator, Counter, Data, Base) に応じて A C D B で始まる名前が付けられ、 16bit ペアの時は X、8bit の時は上位(High) の H と下位(Low) の L の接尾辞が付きました。

そして、これらのレジスタは 8080 の汎用レジスタとほぼ同等の機能と使い方をしました。

A レジスタは Accumulator として使われ、 AL レジスタになりました。
B/BC レジスタZ80 で Counter として使われました。 8086 では CL/CX レジスタが引き継ぎました。
DE レジスタは他の汎用レジスタに比べると特化した目的が少ない Data として使われたため DX レジスタになりました。
HL レジスタはメモリ関節アドレスに使われました。 8086 ではアドレッシングモードが増えたものの Base Address として依然として重要なため BX レジスタになりました。
F レジスタは拡張して rFLAGS レジスタになりましたが、8080 の AF ペアで使われた名残で 8086 では LAHF/SAHF 命令で AH レジスタと関係があります。
IX/IY レジスタは Index として使われ、Source/Destination を明示してより用途が明確な SI/DI レジスタになりました。一方 SI/DI の8ビットバージョンである SIL/DIL は AMD64 の登場まで待たねばなりませんでした。

8086 の代表的な OS である MS-DOS の初期のバージョンは CP/M のクローンと言われるほどよく似ていて MS-DOS ファンクションコールの最初の30個くらいは CP/M とほぼ同じだったため、アセンブラレベルで変換することで 8080 の CP/M のプログラムが 8086 の MS-DOS である程度動いたと言われています。

このように 8080 と同等の機能を持つレジスタの名前が後付けで変更されたために AX CX DX BX という不規則な順番になったと当初仮定していました。
しかし、実は 8080 の時点で汎用レジスタ機械語上の順番は A B C D E H L ではありませんでした。

汎用レジスタのルーツはなんとなくわかったものの順番の理由は不明でした。 Intel の偉い人に聞いてください。

*1:このレジスタペアは 8080 では PSW というわかりにくい呼称でしたが、 Z80 では AF という構造がわかりやすい呼称に変わりました。