UNIX v6 on simh

Lions' Commentary on UNIX読書会に参加した。いまだにLions本が大学の教科書として現役だという事実に驚いたが、読書会に集まる我々も五十歩百歩か。何はともあれ、一緒に読んだり教えたりしてくれるメンタがいれば、現代でも楽しめる一冊であることは確か。すでに読書会のメモがいくつか書かれているようだけど、@kotritさんがきっとまとめページを作ってくれるはずなので、期待!

ここでは実際にUNIX v6が動いているところを見て理解の助けにしたいということで、PDP-11シミュレータsimhでUNIX v6を動かす方法について書いてみる。

PDP-11は古いマシンではあるんだけど、愛好者が多いのでウェブ上には非常に多くの情報が公開されている。シミュレータの開発や当時のディスクやテープのアーカイブもあるし、ソースコードも公開されている。最初はsimhのSoftware Kitsで公開されているディスクイメージを使ったのだけど、manページやユーザランドソースコードが含まれていなかったりするので、ドイツの大学で作られたディストリビューションを使うことにした。これはPDP-11のテープアーカイブとして公開されている。ここからダウンロードして、このドキュメントにしたがってインストールしていけばディスクからブート可能なUNIX環境を構築できる*1。ちなみに、simhについてはこの日記でも何度か紹介しており、Mac OS X上でのコンパイル方法はここに書いた。

上記のドキュメント通りに進めれば特に詰まるところもないので、作業自体はあっという間に終わってしまうけど、ディップスイッチを操作してブートローダを手入力したんだなとか、テープからディスクへのコピーにはどれくらい掛かったんだろうと当時を想像しながら、インストールするのも一興。その詳細は追々書いていきたいと思うが、ここでは詳細を割愛する。

さて、simhを起動してみよう。

$ cat unixv6.cfg
set cpu 11/40
set tto 7b
att rk0 v6root
att rk1 v6src
att rk2 v6doc
;d sr 1
boot rk0

$ ./pdp11 unixv6.cfg

PDP-11 simulator V3.8-1
Disabling XQ
@unix

login: root
# 

カーネルソースコードは今のように構造化されておらず、/usr/sys以下のkenとかdmr(もちんKen ThompsonとDennis Ditchieのこと)というディレクトリに散らばっているのが微笑ましい。

読書会でldivやlremがアセンブリルーチンなのはなぜかって話がでたので、次のコードをコンパイルしてみた。

/ foo(a, b){return a / b;}

.globl  _foo
.text
_foo:
~~foo:
~a=4
~b=6
jsr     r5,csv
mov     4(r5),r1
sxt     r0
div     6(r5),r0
jbr     L1
L1:jmp  cret
.globl
.data

一方、カーネルソースのldivはこんな感じ。比較するとプロローグとエピローグにcsvとcretルーチンを呼び出すことのオーバヘッドを嫌ったのかな。また、div命令はdestのr0とr1のペアを32ビット整数とみなして、srcで割るんだけど、下のコードではr0をゼロクリアしているのに対して、上のコードではsxt命令で符号拡張している。今回のケースでは符号拡張する必要はないので、どちらでもいいと思うけど。

1392 .globl   _ldiv
1393 _ldiv:
1394   clr      r0
1395   mov   2(sp),r1
1396   div     4(sp),r0
1397   rts      ps

あと、systm.hでcoremap[CMAPSIZ]とかswapmap[SMAPSIZ]って定義されていてあちこちのソースファイルからインクルードされているけど、多重定義にならないの?という話が出た。nmで見ると、各オブジェクトファイルには_coremapがコモンシンボルとして含まれ、/unixにリンクされた段階で実体は一つになっている。古いCの仕様がよくわからないけど、コンパイル段階ではexternとして扱われ、ローダ(リンカ)で実体を確保し、アドレス解決するのかな。

# nm /unix|grep map
062052B _coremap
062362B _swapmap
(一部略)

現在の知識が30年以上前のシステムでもそのまま有効というのは、改めてすごいな。というわけで、Lions本読書のお供にsimhが役に立つかもよという話でした。

余談だけど、ソフトウェアシミュレータじゃ物足りなければ、PDP-11をオークションで競り落とすという方法もあるかもしれない。でも、さすがに普通の家庭に置くことは不可能なので、PDP-11をFPGAで実装したPOP-11を動かすという方法がある。ソースが公開されており、ちゃんとUNIX v6も動くそうだ。ボード自体はALTERAのこの辺のものでいけそうなのかな?

余談その2。manファイルはあるんだけど、manコマンドが見つからない。v7にはmanコマンドあるんだけどな。で、nroffで読んでみようと思ったけど、man用のマクロがないようで整形がいまいち。あとページャがないのがつらい。だれかmanページを適切に読む方法を教えて!

余談その3。/etc以下にinit(カーネルが最初に起動するユーザプロセスは/sbin/initじゃなくて/etc/init)やmount、mknodなどの管理系プログラムがあることに驚いたが、4.3BSDのころに/sbinができるまではこんな感じだったとのこと。

余談その4。sttyで再割り当てできると思うが、デフォルトではeraseが@、killが#に割り当てられている。

*1:chdirを今風にcdでできるようにする変更も何気に便利。