わかるUNIXの歴史第 7 回 / 梯子を、全部外す

C も B も無かった1969年 ── Unix は、機械語のすぐ上の言葉で書かれた

最初のUnix ── アセンブリで書かれたOS これまで降りてきた C・B・BCPL・中間コードは、みな「機械を直接触らずに済ませる梯子」でした。1969年、その梯子はまだ1本もありません。Ken Thompson は、PDP-7 のアセンブリ言語で最初の Unix を書いた ── 機械語のすぐ上の、いちばん薄い言葉で。

必要な道具:第5・6回(言語の梯子) 種明かし:アセンブリは機械語の薄い皮

第6回の終わりで「逃げ道(中間コード)の下には、結局アセンブリと機械がある」と言いました。いよいよそこへ降ります。舞台は1969年のベル研。C も B(第5・6回)も、まだ十分には無い時代です。Ken Thompson は、遊休状態の小さなコンピュータ PDP-7 を見つけ、そのアセンブリ言語だけで、カーネルもシェルもエディタも書き上げました。高級言語という梯子を1本も使わずに ── これが Unix の、剥き出しの出発点です。

01なぜ1969年・PDP-7だったのか

直接のきっかけは、大きな失敗でした。ベル研は MIT・GE と組んで壮大なOS Multics を作っていましたが、進みが遅く、1960年代末に撤退します(この Multics 自体は番外編・系譜の最上流で扱います)。手持ちぶさたになった Thompson は、Multics 上で作った宇宙旅行ゲーム Space Travel を、遊んでいた PDP-7 へ移植しようとし ── そのついでにファイルシステムを作り、プロセスを作り、気づけばOSになっていました。当初はベル研の公式な予算も付いていません。

つなぐ声 ── 名前は「去勢された Multics」 この小さなOSに、同僚の Brian Kernighan が1970年、UNICS という名を付けました。巨大だった Multics(Multiplexed…)のもじりで、Uniplexed…、発音は「ユーニクス(eunuchs=宦官)」。大きく野心的だった Multics への、小さく簡潔な当てこすりです。「小さいことは正しい」という Unix の設計思想は、名前からしてそうでした。のち綴りは UNIX に。

02何もかもが、アセンブリだった

PDP-7 の上で、Thompson(のち Ritchie も)はアセンブリ言語で次々に書きました ── カーネル、コマンドインタプリタ(シェル)、エディタ、アセンブラ自身、そして小さなユーティリティ群。ここで階層ファイルシステムプロセスデバイスファイルといった、いまも Unix/Linux の背骨である概念が生まれています。すべて、機械語のすぐ上の言葉で。

03アセンブリとは何か ── 機械語の、薄い皮

「アセンブリで書いた」の意味を、はっきりさせます。機械が実際に実行するのは 機械語 ── ただの数値の列(オペコードとアドレス)で、人間にはまず読めません。アセンブリ言語は、その数値に人が読める名前を付けただけのもの。命令に lac(ロード)・add(加算)のようなニーモニックを、番地に start:n: のようなラベルを与える。両者はほぼ1対1に対応します。

そして、その名前を数値へ機械的に置き換えるプログラムが アセンブラです。下の図で、アセンブリが機械語へ翻訳される様子を1行ずつ見てください。翻訳後の数字だけを見ると、意味がまるで読めなくなる ── それが「機械が見ている世界」です。

図1:アセンブル。人が読めるアセンブリ(左)を、アセンブラがニーモニック→オペコード、ラベル→番地に置き換えて機械語(右・8進)にする。右だけ見ると、もう意味は読めない
左のアセンブリは人が読める。「▶ アセンブルする」で、機械語(右)へ1行ずつ翻訳される。
今回の急所 ── 梯子は、ここでほぼ尽きる

C・B・BCPL・中間コードは、どれも「もっと楽な言葉で書いて、翻訳してもらう」梯子でした。アセンブリは、その梯子のいちばん下の段。機械の命令そのものに名前を貼っただけで、もう「別のもっと楽な言語」に逃げる余地はほとんどありません。ここから下は、素の機械 ── 数値としての機械語と、それを動かす物理だけです。

◇ ◇ ◇

04ここにも、鶏と卵 ── アセンブラは何が作った?

梯子は尽きても、鶏と卵は消えません。アセンブリを機械語にするには、アセンブラが要る。ではその最初のアセンブラは、何が組んだのか? しかもPDP-7 Unix には、アセンブラ自身がアセンブリで書かれて含まれていました。やがて Unix は自分のアセンブラで自分を組み直せる(self-supporting)ようになります ── アセンブリ層での、最小の自己ホスティングです。でも「いちばん最初の1個」は、その輪の中では作れない(第0回)。下の図で、その輪と、輪の外に残る問いを見てください。

図2:PDP-7 Unix の最下層。アセンブラ(as)が、カーネルやシェル、そして自分自身を組む(アセンブリ層の自己ホスティング)。でも「最初の as は何が組んだか」は、この輪の外にある ── 第8回へ
PDP-7 Unix は丸ごとアセンブリで書かれている。中心の as(アセンブラ)が、他の部品と自分自身を機械語へ組む。

05この先 ── PDP-11、そしてCへ(環をひとつ)

PDP-7 Unix はやがて1970年に PDP-11 へ移り(やはりアセンブリ)、そして第5回で見たとおり、1972〜73年に C で書き直されます。ここでシリーズの環がひとつ閉じます ── 第5回「C は B から育った」と、この第7回「最初の Unix はアセンブリ」が、1973年の C 化という同じ結び目でつながる。私たちは今、その結び目のさらに下、いちばん最初のアセンブラの出どころへ向かっています。

正直な線 ── 図の命令は“それらしく”作った例です

(1) 図1の命令・8進コードは、アセンブリと機械語の対応の感じを伝えるための簡略化した例で、実在の PDP-7 の命令表を厳密に再現したものではありません(PDP-7 は18ビット語の小さな機械で、lac/dac/tad/jmp などのニーモニックは実在します)。(2) 「アセンブリ→機械語はほぼ1対1」は基本的に正しいですが、疑似命令・マクロ・複数語命令など例外もあります。

(3) Unix 誕生の経緯(Multics 撤退→Space Travel→ファイルシステム→OS)は語り継がれる有名な流れですが、細部は資料により差があります。(4) 「梯子がここで尽きる」は言い回しで、実際にはアセンブリより下にも、マイクロコードなど機械内部の層が続くことがあります(第10回で扱います)。(5) 初期はアセンブル自体を別マシンで行っていました ── その話がまさに第8回です。

練習問題(今回の話だけで解けます)
  1. 最初の Unix(1969) は、どの機械の何という言語で書かれたか。
    答えを見る
    PDP-7 の(PDP-7 の)アセンブリ言語。C も B もまだ十分に無く、機械語のすぐ上の言葉で書かれた。
  2. アセンブリ言語とアセンブラの違いを一文で。
    答えを見る
    アセンブリ言語は機械語(数値)に人が読める名前(ニーモニック・ラベル)を付けた表記で、アセンブラはその名前を数値へ機械的に置き換えて機械語を作るプログラム。
  3. C・B・BCPL・中間コードと、アセンブリの決定的な違いは何か。
    答えを見る
    前者は「もっと楽な言葉で書いて翻訳してもらう梯子」。アセンブリは機械の命令そのものに名前を貼っただけで、より楽な言語に逃げる余地がほとんど無い=梯子の最下段。
  4. この回で新たに残った「鶏と卵」は何か。
    答えを見る
    アセンブリを機械語にするアセンブラが要るが、その最初のアセンブラは何が組んだのか、という問い。自己ホスティングの輪の外にある最初の1個の出どころ(第8回)。

まとめ梯子を全部外すと、機械語の薄い皮が残った

1969年、Multics から撤退したベル研で、Thompson は遊休の PDP-7 に Space Travel を移植するついでにファイルシステムを作り、それが最初の Unix になった(名は Kernighan の UNICS)。C も B もまだ無く、カーネル・シェル・エディタ・アセンブラ・ユーティリティは、すべてPDP-7 のアセンブリ言語で書かれた。ここで階層ファイルシステムやプロセスといった Unix の背骨が生まれている。

アセンブリは、機械語(人に読めない数値)に人が読める名前(ニーモニック・ラベル)を貼っただけの、いちばん薄い皮。それを数値へ置き換えるのがアセンブラだ。C・B・BCPL・中間コードという「楽をする梯子」は、ここで最下段まで降り切った。だが鶏と卵は残る ── 最初のアセンブラは、何が組んだのか? PDP-7 Unix はアセンブラ自身を含み、アセンブリ層で自己ホスティングするが、最初の1個は輪の外にある。次回、その答え ── 別のマシンでアセンブルし、紙テープで運んだクロス方式へ。

この文書は「わかるUNIXの歴史」シリーズ第7回です。史実:1960年代末、ベル研は MIT・GE との Multics 開発から撤退した。Ken Thompson は Multics 上で作ったゲーム Space Travel を GECOS(GE-635)経由で PDP-7 に移し、その過程でファイルシステム等を実装、最初の Unix となった。最初の Unix は PDP-7 のアセンブリ言語で書かれ(カーネル、シェル、エディタ、アセンブラ、各種ユーティリティ)、階層ファイルシステム・プロセス・デバイスファイル・コマンドインタプリタといった概念が生まれた。名称 UNICS は1970年に Brian Kernighan が Multics のもじりとして考案(Uniplexed…、後に UNIX)。Unix は1970年に PDP-11 へ、1972〜73年に C へ書き直された(第5回)。図1の命令列と8進コードは、アセンブリと機械語の対応を説明するための簡略化した例で、PDP-7 の命令表の厳密な再現ではない(lac/dac/tad/jmp 等のニーモニックは実在)。アセンブリと機械語の対応は概ね1対1だが疑似命令・マクロ等の例外がある。PDP-7 は18ビット語の小型機。 ── 印刷する場合はブラウザの「印刷」から「PDF に保存」を(印刷版では図の操作と解答は静止/非表示になります)。

印刷 / PDF 化:⌘+P(Windows は Ctrl+P)。画面では図1の「▶ アセンブルする」でアセンブリ→機械語の翻訳を、図2で PDP-7 Unix の最下層の自己ホスティングを追えます。「答えを見る」で解答が開きます。