80386のアーキテクチャ(1) - レジスタ
今のインテル系CPUの基本となっている80386ですが、以下の記事で触れたものの、その中身をもう少し深堀りしてみます。
80386 - 32ビット時代と過去の資産の両立
まず、レジスタ構成から整理してみましょう。80386は16ビット時代の8086から互換性を持つ形で進化しています。最初は8086時代のレジスタです。レジスタは大きく分けて「汎用レジスタ」「インデックスレジスタ」「セグメントレジスタ」そして「特殊なレジスタ」に分けられ、それぞれ複数のレジスタを持っていますがいずれもサイズは16ビットです。
汎用レジスタ
AX - 一般演算向け
BX - ベースポインタ向け
CX - 繰り返しカウント向け
DX - 一時退避向け
それぞれのレジスタには想定されている用途が決められており、命令によって特定のレジスタしか使えないことがあります。
またこれらのレジスタは上位8ビットをxH、下位8ビットをxLとして(AHやALなど)、8ビットのレジスタとして扱うことも出来ます。
インデックスレジスタ
SI - ソースインデックス
DI - デスティネーションインデックス
どちらも通常のインデックスとして使えるが「ここから(SI)」「ここまで(DI)」という使い方をする命令がある。
セグメントレジスタ
CS - 命令セグメント
DS - データセグメント
ES - もう一つのデータセグメント
SS - スタックセグメント
8086では16ビットしか無いレジスタで20ビットのメモリをアクセスするので、4ビット分左シフトしたセグメントレジスタの値を足して20ビットのアドレスを生成する。CSはIPに対して、DSやESはデータとしてのアドレスに対して、SSはBPやSPに対して使われる。
特殊レジスタ
BP - ベースポインタ
SP - スタックポインタ
IP - プログラムポインタ
FLAGS - フラグとして使われるビットが集まったレジスタ
※キャリーであるとかゼロ、符号、オーバフローなど
80286になるとプロテクトモードでのタスク管理やセグメント管理で使うためのレジスタが追加されましたが、一般的な命令で使えるレジスタに大きな変化はありません。
システムレジスタ
GDTR - グルーバル・ディスクリプタ・テーブル・レジスタ
IDTR - インタラプト・…
LDTR - ローカル・…
TR - タスク・レジスタ
FLAGS には IOPL(特権レベル)に2ビット分とNT(Nested task)が追加されています。
そして80386では32ビットとなったので、多くのレジスタが32ビットに拡張されました。
汎用レジスタ
AX/BX/CX/DXを32ビットとして使うときにはEAX/EBX/ECX/EDXとして使う。
インデックスレジスタ
SI/DIを32ビットとして使うときにはESI/EDIとして使う。
セグメントレジスタ
セグメントレジスタは16ビットのままだが、CS/SS/DS/ESに加えてFS/GSが追加された。用途はDS/ESと同じ。
特殊レジスタ
IP/BP/SPを32ビットとして使うときはEIP/EBP/ESPとして使う。FLAGSも32ビットに拡張され、32ビットとして使うときはEFLAGS。上位ビットには追加された仮想86モードなどのフラグがある。
実は上記以外にも普段はお目にかからないレジスタもいくつかあるのですが、普通にプログラムを書くときにはお目にかからないのでスルーしておきます。
最近の多くのCPUは、同じ役割の多くのレジスタがあって番号をつけて呼ばれることが多いのに対して、8086系では、その先祖である8080の影響を受けてレジスタ毎に役割があり、命令毎に対象となるレジスタが決まっていることもあります。もっとも80386になった時点で命令も追加され、使うレジスタを選べることも増えました(命令長が同じとは限らない)。
何か単調な列挙になってしまいましたが、次回は動作モードに行きましょう。
ヘッダ画像は、AIで生成したのでリアルなチップの写真ではありません。