シリーズ「コンピュータの CPU のしくみ」 第7回
回路が「自分を書き換える」とは?
番地を、ずらしたい
ここまでの 6 回を、短く振り返っておこう。
手順を 0 と 1 のパターンにしてメモリに並べた。上 4 桁が「何をするか」、下 4 桁が「どの番地か」だ(第1〜3回)。 番地のカウンタに命令の下 4 桁を書き込めば飛べ(第4回)、引き算のあとのランプ C で飛ぶかどうかを選べた(第5回)。 前回は、足し算を何度も繰り返して、掛け算をさせた(第6回)。
前回の終わりに、こう書いた。
12・13・14・15 番地に並べた 4 つの数の合計を取りたい。 1 つの「足す」を何度も通し、1 周するたびに、足す番地を 12、13、14、15 とずらしたい。 けれど、「足す 12 番地」の 12 は、命令の下 4 桁に書き込まれたパターンだ。ずっと 12 のままだ。
命令の中の番地を、1 つずつずらすことはできないか。
この回も、ゲートは 1 つも足さない。 足すのは、命令の見方だけだ。
命令を、数として読む
「足す 12 番地」は、メモリの中では 0010 1100 だ。
上 4 桁の 0010 が足す、下 4 桁の 1100 が 12。
第1回で、メモリの表を眺めたとき、こう書いた。 手順も、数も、メモリの中では 8 桁のパターンが並んでいるだけである。
では、この命令を、数として読んだらどうなるか。
「持ってくる」は、その番地の語の下 4 桁を、A の箱に入れる命令だった。 「足す 12 番地」が 1 番地に置いてあるなら、「持ってくる 1 番地」と書けばいい。
A の箱に入るのは、1100。12 だ。
回路は、1 番地の語が命令として置かれたものだとは知らない。 メモリの箱は、番地の入口に 1 が来たら、その語を出す。それだけだ。 出てきた語が命令の置き場に届けば、上 4 桁がデコーダに行く。A の箱に届けば、下 4 桁だけが入る。
下の図で、8 桁のマスを押して、1 語を 2 通りに読んでみてほしい。
メモリの 1 語(マスを押して替えられる)
命令として読む
読む拍で、命令の置き場へ
足す 12 番地
上 4 桁はデコーダへ
数として読む
持ってくるで、A の箱へ
12
上 4 桁は届かない
「1 番地(足す 12)」と「数 12」を押し比べてほしい。
命令として読めば、0010 1100 は足すで、0000 1100 は何もしない。
数として読めば、どちらも 12 だ。
同じパターンを、命令として読むか、数として読むか。 それを決めているのは、パターンではない。どの拍に、どの箱へ届くかだ。
1 足して、書き込む
A の箱に 12 が入った。 これに 1 を足せば、13 になる。1 は、どこかの番地に置いておけばいい(前回の「回数から引く 1」と同じだ)。
あとは、この 13 を 1 番地に書き戻す。「書き込む 1 番地」だ。
ここで、第3回で作ったメモリが効いてくる。 あのとき、メモリの語の下 4 桁だけを書けるようにした。上 4 桁は、読むだけのままだ。 上 4 桁のフリップフロップには、書き込みの合図の線が、はじめからつながっていない。
だから、書き込むは、下 4 桁だけを書き換える。
1 番地は 0010 1100 から 0010 1101 になる。
上 4 桁の足すはそのまま、番地だけが 13 になった。
書き込む先
A の箱の数
紫の枠が、書き込みの合図が届く 4 桁。上 4 桁には、合図の線がつながっていない
書き込む先を 8 番地の止まるにしてみてほしい。
何を書き込んでも、上 4 桁は 1111 のまま、止まるは止まるのままだ。
この CPU では、プログラムが命令の種類を替えることはできない。替えられるのは、命令の番地だけだ。
押して、確かめる
この 2 つを組み合わせたのが、下のプログラムだ。15 語ある(9 番地は空き)。
| 番地 | 中身 | 読み方 |
|---|---|---|
| 0 | 0001 1010 | 持ってくる 10 番地 |
| 1 | 0010 1100 | 足す 12 番地(← この下 4 桁を書き換える) |
| 2 | 0011 1010 | 書き込む 10 番地 |
| 3 | 0001 0001 | 持ってくる 1 番地 |
| 4 | 0010 1011 | 足す 11 番地 |
| 5 | 0011 0001 | 書き込む 1 番地 |
| 6 | 0110 1000 | ランプなら飛ぶ 8 番地 |
| 7 | 0101 0000 | 飛ぶ 0 番地 |
| 8 | 1111 0000 | 止まる |
| 10 | 0000 0000 | 合計を置く場所 |
| 11 | 0000 0001 | 数 1(番地を 1 進める) |
| 12〜15 | 0000 0001 など | 足す数(1・2・3・4) |
上から、3 つのまとまりに分けて読める。
- 0〜2 番地:合計に足す。 合計を持ってきて、1 番地の「足す」で 1 つ足し、10 番地に書き戻す
- 3〜5 番地:1 番地を書き換える。 1 番地の命令を数として持ってきて、1 を足し、1 番地に書き戻す
- 6〜8 番地:続けるか、止まるか。 ランプ C が点いていれば 8 番地で止まる。消えていれば 0 番地へ戻る
6 番地のランプについては、次の節で見る。まずは動かしてみよう。
自分を書き換える シミュレータ
「自動で進める」を押して、1 番地の「足す」の番地が 12・13・14・15 と書き換わっていくのを見てください
回路は前の 2 回とまったく同じ(1900 ゲート)。メモリの箱は、命令の行にも数の行にも、同じように下 4 桁を書き込む
はじめは読む拍。番地のカウンタは 0。次の番地を選ぶ箱は、いつもは「+1」を通している。クロックを入れると、0 番地の語が命令の置き場に届く。
拍ごとの記録
| 拍 | 段階 | 番地 | 起きたこと |
|---|---|---|---|
| まだクロックを入れていない | |||
| 番地 | 中身 | 読み方(人間のメモ) |
|---|---|---|
| 0000(0) | 0001 1010 | 持ってくる 10 番地 |
| 0001(1) | 0010 1100 | 足す 12 番地 |
| 0010(2) | 0011 1010 | 書き込む 10 番地 |
| 0011(3) | 0001 0001 | 持ってくる 1 番地 |
| 0100(4) | 0010 1011 | 足す 11 番地 |
| 0101(5) | 0011 0001 | 書き込む 1 番地 |
| 0110(6) | 0110 1000 | ランプなら飛ぶ 8 番地 |
| 0111(7) | 0101 0000 | 飛ぶ 0 番地 |
| 1000(8) | 1111 0000 | 止まる |
| 1001(9) | 0000 0000 | |
| 1010(10) | 0000 0000 | 数 0(合計を置く場所) |
| 1011(11) | 0000 0001 | 数 1(番地を 1 進める) |
| 1100(12) | 0000 | 数 1(足す数)◀ 1 番地が指す |
| 1101(13) | 0000 | 数 2(足す数) |
| 1110(14) | 0000 | 数 3(足す数) |
| 1111(15) | 0000 | 数 4(足す数) |
青い行は、読む拍で使う番地(番地のカウンタ)。琥珀色の行は、こなす拍で使う番地(命令の下 4 桁)。紫の線は書き換わる 1 番地、紫の枠はその「足す」が指している行。12〜15 番地の下 4 桁は、押して替えられる(替えると、はじめからやり直す)
図は、前の 2 回とまったく同じだ。ゲートは 1 つも増えていない。
「自動で進める」を押して、表の 1 番地の行を見てほしい。 紫の線が引いてある行だ。読み方の欄に、書き換えの跡が残っていく。 紫の枠は、いまの「足す」が指している行だ。書き換えるたびに、枠が 1 行ずつ下へ動く。
| 周 | 1 番地の命令 | 足した数 | 合計(10 番地) | 1 番地の書き換え |
|---|---|---|---|---|
| 1 | 足す 12 | 1 | 1 | 12 拍目に 13 へ |
| 2 | 足す 13 | 2 | 3 | 28 拍目に 14 へ |
| 3 | 足す 14 | 3 | 6 | 44 拍目に 15 へ |
| 4 | 足す 15 | 4 | 10 | 60 拍目に 0 へ |
1 周は 8 命令・16 拍。4 周目は 7 番地の飛ぶを通らずに 8 番地の止まるへ行くので、32 命令・64 拍で止まる。 10 番地の合計は 10。1 + 2 + 3 + 4 の答えだ。
1 つの「足す 12」が、12、13、14、15 番地の数を順に足した。 足す命令は、1 つしか書いていない。
12〜15 番地の数は、押して替えられる。 どんな数を入れても、10 番地には 4 つの和が入り(和が 15 を超えたら、下 4 桁)、必ず 64 拍で止まる。
止まったあとの 1 番地を見てほしい。0010 0000、「足す 0 番地」になっている。
プログラムは、自分を書き換えたまま終わる。
もう一度このまま動かしても、1 番地は 12 を指していない。最初の 1 周で、0 番地の命令 0001 1010 の下 4 桁を、数として合計に足してしまう。
0 番地から 15 番地まで 16 周、256 拍かかってようやく止まり、合計は 3 になる。
この画面の「はじめに戻す」は、メモリも最初のパターンに戻している。だから、何度でも同じように動く。
あふれたら、止まる
前回の掛け算は、「残りの回数」をメモリに置き、1 ずつ減らして、ランプで終わりを知った。 この回のプログラムには、回数を数える数がどこにも無い。
数えているのは、1 番地の番地そのものだ。
1 番地の下 4 桁は、4 桁しかない。15 に 1 を足すと、16 は 4 桁に入らない。
1111 + 0001 は 1 0000。4 桁には 0000 が残り、5 桁目の 1 がランプ C に入る。
第5回で、あふれたら止まるプログラムを書いたのと同じランプだ。
ランプ C
1 番地の下 4 桁
- 足す 12
- 足す 13
- 足す 14
- 足す 15
- 足す 0
4 番地の足すで、ランプ C が点く。 その次の 5 番地の書き込むは、ランプに触らない。 6 番地の「ランプなら飛ぶ 8」がそれを見て、8 番地の止まるへ飛ぶ。
12、13、14 のときは、足してもあふれない。ランプは消えたまま、7 番地の飛ぶで 0 番地へ戻る。
ひとつ、細かいところ。 1 番地の足すも、合計が 15 を超えるとランプ C を点ける。 けれど、6 番地で見る前に、4 番地の足すがランプを上書きする。だから、合計のあふれを、終わりの合図と取り違えることはない(前回の掛け算と同じだ)。
この止め方は、表を 15 番地で終わるように置いたから使える。 番地が 15 から 0 に戻るところが、そのまま表の終わりになっている。
同じパターン
この回のプログラムがしたことを、もう一度並べてみる。
- 1 番地のパターンを、命令として読んで、足した
- 同じ 1 番地のパターンを、数として読んで、1 を足した
- その数を、また 1 番地に書き戻した
命令とデータを、別々の場所に置いていたら、こうはいかない。 同じメモリの、同じパターンだから、命令を数として読めるし、数として書き換えた結果が、そのまま次の命令になる。
命令とデータは、同じメモリの同じパターンだ。だからプログラムは、自分自身を数として読み、書き換えられる。
命令を数と同じようにメモリに置くやり方を、プログラム内蔵方式という。 1945 年に、フォン・ノイマンの名前でまとめられた報告書(「EDVAC についての報告書の第一草稿」)が、この考え方の土台を描いたとされる。報告書は、計算の手順もメモリが覚えておく材料に数え、メモリを 1 つのものとして扱おうとしていた。 そのため、この形のコンピュータはフォン・ノイマン型と呼ばれることが多い。
それより前の ENIAC という計算機では、手順は配線盤の線のつなぎ方で表していた。手順を替えるには、線をつなぎ替える。 第1回の書き出しの、配線で手順が決まっていた自動販売機や電卓と同じだ。
電子のメモリに置いたプログラムを初めて動かした計算機は、イギリスのマンチェスター大学の小さな試作機「Baby」だった。1948 年 6 月 21 日のことだ。 翌 1949 年 5 月 6 日には、ケンブリッジ大学の EDSAC が最初のプログラムを動かした(0 から 99 までの 2 乗の表を作るものだった)。
この CPU は、16 語しかない小さなものだ。けれど、形は同じだ。 第1回からずっと、命令と数を、同じ 1 つのメモリに並べてきた。
こわくもある
自分を書き換えられる、ということは、書き間違えれば、自分を壊せるということでもある。
5 番地の「書き込む 1」の 1 を、別の番地にしてみよう。 命令の中で替わるのは、下 4 桁だけだ。
5 番地「書き込む 5 番地」(0011 0101)
止=正しく止まる 違=止まるが合計が違う ∞=止まらない
16 通りのうち、正しく止まるのは 1 のときだけだ。
4 と 11 は止まるが、合計が違う。残りの 13 通りは、いつまでも止まらない。
1(0001)と 1 桁しか違わない 0・3・5・9 も、止まらない。
書き間違えた先が命令なら、その命令が別のものに変わる。 数なら、合計や「1」が壊れる。 しかも、壊れたプログラムは、壊れたことに気づかない。どの命令も、表どおりに淡々とこなされる。
この CPU では、上 4 桁は書けない作りにした。 だから、壊れ方にも限りがある。足すが止まるに化けることは無い。 これは、このシリーズの CPU の約束だ。本物の CPU がそうなっているとは限らない。
4 桁の CPU 4004 は、そもそもプログラムを書き換えられない形で使われていた。 プログラムは、4001 という読むだけのメモリ(ROM)に入れた。中身は、ROM を作るときの型(マスク)で、注文どおりに作り込む。動いている途中で、そこへ書き込む命令は無い。
自分を書き換えなくても番地をずらせるように、専用の箱も生まれた。 1949 年 4 月までに、マンチェスター大学の機械には、命令の中の番地に数を足してから使う箱(B ライン。いまの言葉でいうインデックスレジスタ)が付いた。 表を順に扱うのに、自分を書き換えるプログラムが要らなくなった。
それに、プログラムがメモリの中のパターンにすぎないなら、外から入ってきたパターンが、命令として読まれてしまうかもしれない。 書き換えられることは、悪用されうることでもある。
外の世界
この回のプログラムは、命令の番地をずらして、表を合計した。
けれど、振り返ってみると、足した数はどれも、はじめからメモリに置いてあった。 3 + 5 も、大きいほうを選ぶのも、掛け算も、この回の合計も、そうだった。 動き出してから、外から何かが入ってくることは、一度も無かった。
記憶のしくみの最終回で作った自動販売機を思い出してほしい。 硬貨は、いつ、いくら入ってくるか分からない。品物は、外へ出さないといけない。
外から数を受け取り、外へ何かを出すには、どうすればいいか。
次回は、いよいよ最終回。メモリの外とつながる入口と出口を足して、自動販売機をプログラムで動かしてみる。
参考文献
- 松下俊介 著. 基礎からわかる論理回路. 第2版, 森北出版, 2021.7. 978-4-627-82842-1. https://ndlsearch.ndl.go.jp/books/R100000002-I031573740
- ディビッド・マネー・ハリス, サラ・L・ハリス 著; 天野英晴, 鈴木貢, 中條拓伯, 永松礼夫 訳. ディジタル回路設計とコンピュータアーキテクチャ. 第2版, 翔泳社, 2017.9. 978-4-7981-4752-9. https://ndlsearch.ndl.go.jp/books/R100000002-I028478041
- 渡波郁 著. CPUの創りかた : IC10個のお手軽CPU設計超入門 : 初歩のデジタル回路動作の基本原理と製作, 毎日コミュニケーションズ, 2003.9. 4-8399-0986-5. https://ndlsearch.ndl.go.jp/books/R100000002-I000004238574
- John von Neumann. "First Draft of a Report on the EDVAC". Moore School of Electrical Engineering, University of Pennsylvania, 1945.6.30. https://cs.carleton.edu/faculty/jondich/courses/cs207_f03/assignments/edvac.pdf, (参照 2026-10-19).
- Computer History Museum. "First draft of a report on the EDVAC". Revolution: The First 2000 Years of Computing. https://www.computerhistory.org/revolution/birth-of-the-computer/4/88, (参照 2026-10-19).
- "プログラム内蔵方式". 世界大百科事典(旧版). コトバンク. https://kotobank.jp/word/%E3%83%97%E3%83%AD%E3%82%B0%E3%83%A9%E3%83%A0%E5%86%85%E8%94%B5%E6%96%B9%E5%BC%8F-125542, (参照 2026-10-19).
- The University of Manchester. "How a 70-year-old 'Baby' changed the face of modern computing". https://www.manchester.ac.uk/discover/news/how-a-70-year-old-baby-changed-the-face-of-modern-computing/, (参照 2026-10-19).
- Engineering and Technology History Wiki. "Milestones:Manchester University "Baby" Computer and its Derivatives, 1948-1951". https://ethw.org/Milestones:Manchester_University_%22Baby%22_Computer_and_its_Derivatives,_1948-1951, (参照 2026-10-19).
- University of Cambridge Department of Computer Science and Technology. "70 years since the first computer designed for practical everyday use". 2019.5.3. https://www.cst.cam.ac.uk/news/70-years-first-computer-designed-practical-everyday-use, (参照 2026-10-19).
- Karen Spärck Jones. "A brief informal history of the Computer Laboratory". EDSAC 99, University of Cambridge Computer Laboratory. https://www.cl.cam.ac.uk/events/EDSAC99/history.html, (参照 2026-10-19).
- Intel. "MCS-4 Micro Computer Set". 1971.11. https://ieeemilestones.ethw.org/w/images/2/2d/Ref2-Intel_MCS-4_DataSheet.pdf, (参照 2026-10-19).