id:n7shi:20110408で開発したSilverlight版のPDP-11インタプリタですが、ブラウザから出してコマンドラインで動かなければ、実用には厳しいと感じました。そのためC++で書き直して、Win32とPOSIXに対応しました。Win32はMinGW、POSIXは Interix 3.5, NetBSD 5.1, FreeBSD 8.1-R での動作を確認しています。他のOSでは多少の修正が必要になるかもしれません。
- ソース閲覧: https://bitbucket.org/7shi/v6run/src
- ダウンロード: https://bitbucket.org/7shi/v6run/downloads
- スクリーンショット: http://twitpic.com/4irwbi
- ライセンス: パブリックドメイン(インタプリタ)、BSDスタイル(V6のコマンド)
Lions' Commentary on UNIX 読書会 Part 006 に間に合わせようと突貫で開発したため、一部のシステムコールしかサポートしていません。現段階ではUNIX V6カーネルのビルドが可能です。
インストール方法
最初にインタプリタ本体(v6run)をビルドします。ソースをMercurialでcloneするか、ダウンロードページの Tags & snapshots から 0.2-20110412 を選択してください。(Uploaded files については後で説明します)
ソースを展開して make install としてください(WindowsではMinGW Shellを使用)。デフォルトでは /usr/local/bin にインストールされますが、変更するにはMakefileのPREFIXを書き換えてください。
$ hg clone https://bitbucket.org/7shi/v6run $ cd v6run $ make install
※BSD系のOSではgmakeを使用してください。
V6バイナリの配置
v6runはPDP-11の命令をインタプリタで実行して、UNIX V6のシステムコールをネイティブのシステムコールに変換するだけのプログラムです。そのため何か作業するには別途V6のバイナリが必要となります。
開発環境一式をダウンロードページの Uploaded files で配布しています。
- v6root-20110412.tar.xz
これをMakefileのV6ROOTで指定したパスに展開します。デフォルトでは /usr/local/v6root です。
$ tar xvJf v6root-20110412.tar.xz -C /usr/local
※tarがxzに未対応の場合、gtarを使用してください。
これで開発環境が整いました。
動作確認
簡単なプログラムで動作確認を行います。
次のソースを作成してください。simhの外での作業ですから、edを使う必要はありません。任意のエディタを使用可能です。
hello.c
main() { printf("hello\n"); }
コンパイルして動作を確認します。
$ v6cc hello.c $ v6run a.out hello
a.outがPDP-11バイナリであることを確認します。
$ file a.out a.out: PDP-11 executable
【注】Windowsでは、改行コードがCR+LFのままだと以下のようにエラーとなります。LFをサポートしたエディタを使用してください。
$ v6cc hello.c 1: Unknown character 2: Unknown character 3: Unknown character 4: Unknown character
オプション
デバッグ用にトレース機能が利用できます。引数なしでコマンドを起動するとオプションが表示されます。
$ v6run usage: v6run [-r V6ROOT] [-v/-s] cmd [args ...] -v: verbose mode (output syscall and disassemble) -s: syscall mode (output syscall)
すべての命令を逆アセンブルしながら動作を確認するには -v オプションを使用します。
$ v6run -v a.out 0000,0000,0000,0000,0000,0000,sp=fff6,pc=0000: setd 0000,0000,0000,0000,0000,0000,sp=fff6,pc=0002: mov sp, r0 fff6,0000,0000,0000,0000,0000,sp=fff6,pc=0004: mov (r0), -(sp) fff6,0000,0000,0000,0000,0000,sp=fff4,pc=0006: tst (r0)+ (以下略)
システムコールだけを表示するには -s オプションを使用します。
$ v6run -s a.out 0001,0000,0000,0000,ffea,ff5a,sp=ff58,pc=022a: sys indir; 02a8 0001,0000,0000,0000,ffea,ff5a,sp=ff58,pc=022a: sys write; 02c0; 0001 h0001,0000,0000,0000,ffea,ff5a,sp=ff58,pc=022a: sys indir; 02a8 0001,0000,0000,0000,ffea,ff5a,sp=ff58,pc=022a: sys write; 02c0; 0001 e0001,0000,0000,0000,ffea,ff5a,sp=ff58,pc=022a: sys indir; 02a8 0001,0000,0000,0000,ffea,ff5a,sp=ff58,pc=022a: sys write; 02c0; 0001 l0001,0000,0000,0000,ffea,ff5a,sp=ff58,pc=022a: sys indir; 02a8 0001,0000,0000,0000,ffea,ff5a,sp=ff58,pc=022a: sys write; 02c0; 0001 l0001,0000,0000,0000,ffea,ff5a,sp=ff58,pc=022a: sys indir; 02a8 0001,0000,0000,0000,ffea,ff5a,sp=ff58,pc=022a: sys write; 02c0; 0001 o0001,0000,0000,0000,ffea,ff5a,sp=ff58,pc=022a: sys indir; 02a8 0001,0000,0000,0000,ffea,ff5a,sp=ff58,pc=022a: sys write; 02c0; 0001 0000,ffea,0000,0000,0000,fff0,sp=fff0,pc=0252: sys exit
上の例で表示がずれている部分があるのは、writeシステムコールによって文字が表示されているためです。このようにprintf()では一文字ずつ表示していることが分かります。
カーネルのビルド
カーネルをビルドしてみます。オリジナルのV6ではビルド用にrunというシェルスクリプトが用意されていますが、これは現在のシェルスクリプトとは少し仕様が異なるため、そのままでは使用することができません。
そのためMakefileを追加したソース一式を用意しました。ダウンロードページの Uploaded files で配布しています。Makefileを追加した以外の変更はありません。ソースはオリジナルのままです。
- v6sys-20110411.tar.xz
これを展開してビルドします。
$ tar xvJf v6sys-20110411.tar.xz $ cd v6sys-20110411 $ make
※tarがxzに未対応の場合、gtarを使用してください。
成功すれば、以下の3つのカーネルが生成されます。それぞれコンフィグが異なるカーネルです。
- hpunix
- rkunix
- rpunix
どのようにコマンドを呼び出しているかはMakefileを参照してください。もともとあったシェルスクリプト(run)を直訳したもののため、Makefileとしては格好悪いスタイルです。気持ち悪い方は各自修正してみてください。