今日は 4004が発売された日(1971年)。
インテルが作った、世界初のマイクロコンピューターですね。開発話は、以前に書いているので 4004 の構造を説明しましょう。
4004 は世界初の 1chip CPU。4bit CPU ですが、これは内部レジスタとデータ入出力の単位が 4bit なだけ。命令は 8bit で、メモリアドレスは 12bit です。
命令は 8bit なので、プログラムを収めた ROM は 8bit 単位にアドレスが割り振られています。それに対して、RAM は 4bit 単位のアドレスです。
そして、現在のアクセスが RAM に対するデータアクセスなのか、ROM に対するプログラムアクセスなのかを示す信号線が出ています。
RAM と ROM はアクセス方法が違うだけでなく、アドレス空間も分離されています。それぞれ 0番地から始まるアドレスを持てるのです。
4bit 処理でプログラムサイズが 4KByte 、できる処理はかなり限られています。
事実 4004 は「汎用性」を重視していましたが、事実上電卓専用。
LSI の製造技術として、18ピン(電気的な接続端子が 18本)が限界だった、と言う現実がまずあり、その中で「プログラム可能な電卓用 LSI」をどうやって作るか考えられた結果が 4004 でした。
最終的に 16ピンの LSI になっています。
アドレスが 12bit で、ROM から読み込むデータが 8bit 。これだけで 20本の信号線になります。18ピンが最大では作れません。
そこで、4bit づつ何回かにわけてデータを送受信する方法が考えられました。
プログラムを実行する場合、4bit づつ、3クロックかけて 12bit のアドレスを送出します。
すると、ROM がデータを返してくるので、4bit づつ、2クロックかけて 8bit のデータを受け取ります。
プログラムの命令を読み出すだけで5クロック。この後、命令解釈に1クロック、実行に2クロックかけます。
というわけで、1命令の実行は最低でも8クロック。
命令によってはさらに追加で ROM から 8bit データを読み出したり、RAM と 4bit データをやり取りしますが、この場合は非常に遅くなります。
アドレスを3回に分けて送るとか、データを2回に分けて取り出すとか…非常に特殊なやり方なので、専用の ROM/RAM が一緒に開発されています。
ROMの型番は 4001 、RAM は 4002、I/Oに使用する 10bit のシフトレジスタが 4003。
これに、CPU 4004 を加えて「4000ファミリー」となります。
4004 は 4bit づつ処理を行う、という不便はありますが、その内部構造は世界初にしてはなかなか豪華です。
アキュムレータ(計算用レジスタ)の他に、汎用レジスタを 16本も持っています。計算は、常にレジスタとアキュムレータの間で行われます。
アキュムレータもレジスタもすべて 4bit ですが、汎用レジスタ2本をペアにして、8bit データを表現することもできます。
このペアのつくり方は決まっていました。(レジスタには 0~15の番号が付けられていて、ペアになれるのは 0と1、2と3、4と5…のように固定されています)
先に書いたように、命令は 8bit ですが、このうち「命令」そのものは大抵 4bit で表現されます。
のこりの 4bit は、レジスタの指定など。4bit あれば 16本のレジスタが指定できるわけです。
また、アキュムレータにデータをセットする場合などは、そのデータが 4bit で指定されます。
2byte が必要な命令は、4bit にさらに 8bit を足して 12bit のアドレスを示したり(ジャンプ命令など)、レジスタペアに 8bit のデータを読み込ませたりする場合に使われます。
…ところで、アドレスとレジスタを両方同時に指定する命令と言うのは存在しないのですね。
基本的に、4004 のプログラムは「シーケンシャル」です。データが必要な場合は、4bit のアキュムレータ読み込みや、8bit のレジスタペア読み込みとして、プログラムにデータが埋め込まれます。
プログラムは ROM に置かれる、と言うのが前提で、「データをメモリに書き込む」と言う命令は存在しないのです。
実は、接続された RAM は I/O 空間にあるのです。
4004 では RAM と I/O を区別しておらず「RAM 空間」と呼んでいるのですが、8080 以降は同じ仕組みで I/O 空間と呼ばれるようになります。
(8080 では、メモリ空間にRAM を使用する前提で、書き込みができるようになったため)
こう考えると、ROM は 8bit アクセスなのに RAM は 4bit アクセス、という不自然さも理解できます。
全く違うものとして考えているのですね。
RAM や I/O にアクセスする際は、まず RAM のバンクを選択し、レジスタペアにアドレスを入れ、アドレス出力命令を実行し、最後にアクセス命令で読み書きを行う必要がありました。
非常に面倒で、遅いです。
先に書いた、16本も汎用レジスタがあるのも、おそらくはこの影響。
16本もあって豪華、ではなく、RAM が使いづらいからレジスタを増やさざるを得ないのですね。
4004 には、TEST 端子というのがありました。
これ、外部から CPU に対して働きかけるための唯一の方法。4004 は割り込みは持っていないのですが、同じようなことをしようとしています。
上に書きましたが、4004 の I/O アクセスは遅いです。
しかし、電卓ではユーザーがいつキーを押すかわかりません。常に I/O を見張り続ける必要がありました。
計算中にも常にキーを見張り続ける…というのは、遅いばかりで無駄ですが、やらなくてはならないのです。
ここで TEST 端子が使用されます。TEST 端子の状態は、4004 の内部フラグに反映されており、これを元に条件ジャンプを行えます。
キーを押されたかどうか判別し、押されていなければ I/O のプログラムは飛ばします。押されたときだけ、プログラムが実行され、押されたキーを読み取ります。
こうすることで、プログラムを高速に動作させることができました。
4004の設計者である嶋さんは、TEST 端子は「『4ビットのCPU』をタイム・シェアして使用」するための重要ピンだった、と記述しています。
4004 には割り込みはありません。
まだ割り込みと言うアイディアがなかった気もしますが、RAM が I/O 空間にあるので、割り込みに必要なスタックが作れないことも影響したかもしれません。
スタックが存在しない。…プログラマならサブルーチンも使えないの?と気になるところでしょう。
ところが、これは大丈夫なのです。制限はあるけど、スタックなしにサブルーチンを呼び出すための仕組みが備わっています。
現在実行中のアドレスを保持するためのレジスタ、「プログラムカウンタ」が4つあり、切り替えられるようになっているのです。
サブルーチン呼び出しを行うと、そのアドレスが「次のプログラムカウンタ」に入れられ、そちらが使われるように切り替わります。これにより、サブルーチンの先頭から実行が開始されます。
サブルーチンからの復帰時は、「前のプログラムカウンタ」が使われるように切り替わります。これにより、呼び出し前の続きから実行が行われます。
ハードウェア的な仕組みで、スタックなしにサブルーチン呼び出しを実現しているのですね。
ただし、プログラムカウンタは4つしかないので、サブルーチンの呼び出しは3段までしかできません。
この回数を超えないようにするのは、プログラマの責任です。
#じつはこの4つのレジスタは「スタック」ではなく「リング」になっているので、4段目の呼び出しを行うと、最初のデータが破壊されます。
4004 は世界初のマイコンで、電卓用途を考えていたためにそれほど汎用性は高くないのですが、たった 16ピンのパッケージで上手にまとまっています。
最後に、4004 に興味を持った方へ、3つの資料を提示します。
Intel のページに未だに置かれている、4004 のデータシート。
そのデータセットにも概要は書かれているけど、命令の動作詳細をまとめたページ。
さらに、Javascript で動作する、エミュレーター、ディスアセンブラ、アセンブラのページ。
命令詳細とエミュレータ類のページは、同じサイト内のものですね。
ところで、最後のリンク先は右上に polish ボタンがあるのですが、押しても三月魔臼は見つかりません。
(最後の最後に誰もわからないネタを…)
同じテーマの日記(最近の一覧)
関連ページ
HARLIE あらすじと解説(1/2)【日記 14/09/21】
HARLIE あらすじと解説(1/2)【日記 14/09/21】
別年同日の日記
申し訳ありませんが、現在意見投稿をできない状態にしています。 |