はじめて読む8086 ノート
構成概要
論理構成としてはこんなかんじになる。
物理的にはアドレスバス・データバスは同一の信号線であり、非常に細かいインターバルで目的に応じた切り替えを行っている。
- アドレスバス
- 2種類のアドレスデータが通るバス。
- 1 MB のメモリ空間から任意の1バイトあるいは1ワードを選択するための20ビットアドレス
- I/O ポートを選択するための16ビットアドレス(つまり最大 65536 ポート)
- データバス
- 2種類のデータを読み書きするためのバス。
- メモリにリード or ライトするデータ
- 入出力ポートにリード or ライトするデータ
1アドレスが1バイトに対応する構成の場合は、利用可能なメモリが最大 1 MB(2^20 = 1,048,576 バイト)
負数の扱い
最上位ビットが立ってると負数ってやつ。
- バイト FF をインクリメントすると 01 00 でオーバフローするとみなせる
- オーバフローした箇所を無視すると FF をインクリメントした結果 00 になりましたと帰着
- FF は 00 より1小さい == 負数 -1 であると考えられる
- 同様に FE は -2, FD は -3 って考えていっても成り立つよね
- って逆算してったとき 00 〜 7F の 128 個と 80 〜 FF の128個にわけると都合が良い
- なぜなら後者は先頭ビット(MSB)が常にたってるから。
- じゃあ負数を取り扱うときはこの判断系で実装しましょう
CPU の基本動作
ノイマン型であれば基本的な動作は3ステップで行われ、これがシーケンシャルに続く。
- 命令の読み込み
- アドレスバスにアドレス信号等を出力し、メモリに対してデータを出力するよう要求
- メモリからバスにデータが出力されてくるので、データバスを通じて取り込み
- 命令の解読
- ビットのパターン(オペコード)に対して割り当てられている命令がある
- 演算
- 演算結果によるプログラム実行制御
- 演算結果データの転送
- 外部とのデータ入出力
- その他
- ビットのパターン(オペコード)に対して割り当てられている命令がある
- 命令の実行
- アドレスバスにアドレス信号等を出力して準備するよう要求
- メモリや I/O に信号出力(レジスタの内容)
解読や実行中にバスが空いていれば命令読み込みが実行される。
この実装をパイプラインと呼ぶ。
命令の実行にあたっては、クロックによって CPU とコンポーネント間で同期がとられる。
クロックは水晶発振器によって作り出される一定周期のパルスを指す。
仕組みは簡単で「電圧の高い状態」「電圧の低い状態」を交互に作り出している。
コンポーネントは「高い状態」の時に状態が変化して、「低い状態」の時に次の状態に移る準備をする。
8 MHz 動作の CPU であれば、この状態の変化(1サイクル)が 1/8,000,000 秒で回される。
命令によって必要なクロック数は違う。
CPU とメモリ
16bit CPU ではアドレスバス 20 本に対してデータバス 16 本 が存在。
1つのアドレス指定で 16bit = 2byte をリード or ライトできる。
8bit だけのリード・ライトも可能。
この1つのアドレス指定でリードライトできる単位を「ワード」と定義する。
このため、CPU の種類によってワードは変化する。
ちなみに 8bit CPU ではアドレスバスが8本しかないのでメモリ容量は最大 256 KB となる。
データバスも8本しかないので、単純に比較すれば 16bit は 8bit の2倍データをやりとり出来る分動作が高速。
ROM と RAM
ROM も RAM も CPU から見ると同じアドレスバス・データバスでつながっているメモリでしかなく、プログラム実行上は区別がない。ただし ROM はライトが出来ない。
ちなみに ROM は Read Only Memory, RAM は Random Access Memory の略だが、ROM もランダムアクセス可能である(つまり慣習的に名前がこうなっている)
実際の 8086 CPU を見ると、メモリ空間には ROM, RAM が混在している。
一般的には ROM には BIOS が入っていて、処理系によっては BASIC インタープリタがはいっていたりする。
8086 CPU では電源 ON やリセット時に読まれ始めるメモリアドレスが FFFF0 以後なのでここに ROM を割り当てている。
また、割り込みベクタテーブルが 0 〜 3FF に割り当てられるが、これは読み書きできる RAM が割り当てられる。
一般的には高アドレス領域を ROM, 低い方を RAM とする処理系が多く、MS-DOS もこれを想定した作りになっている。
8086 のソフトウェアがリッチになってきてメモリが 1M という上限にひっかかるようになってくると、メモリバンク切り替えというテクニックが編み出された。
これは、ベクタテーブルと ROM 以外のアドレス空間をバンク空間と位置づけて、 プログラマブルなスイッチによってデータバスの接続先を切り替えるようにして限界をこえるというもの。
プログラマブルスイッチ用に、ノンバンク空間に少し領域をとっておく。
こうすることで論理的に扱える空間を増やすという工夫をしていた。CPU から見えていないバンクを「裏バンク」とか呼ぶこともあったらしい。
I/O
8086 では I/O アドレスバスは 16bit なので最大 65,536 ポートを利用できる。
利用するバスはアドレスバス20本のうち、下位16本。
メモリアドレスなのか I/O アドレスなのかを区別する信号がアドレスと共に出力されるので、それをもとにハードウェア的に信号の宛先をスイッチしている。
CPU によっては、このような方式では無く、あるアドレス範囲を I/O ポートに固定割り付けして区別している場合もある。68k 系列の場合はこの方法を採用している。