V6のコードリーディングをやってると,pdp11のエミュレータsimhの使い方とか クロスコンパイラの使い方を知っているといろいろ捗ると思うのでそのまとめです. やってることは,

  1. クロスコンパイラを使ってpdp11のa.out-pdp11フォーマットの実行ファイルを作る.
  2. simhでそれを実行させてメモリ・レジスタの内容を確認する.(simhの仮想ディスクに実子ファイルを割り当ててブートする.)

pdp11では基本的に8進で書かれることが多いので注意です.

クロスコンパイラ

binuitlsとgccは以下のものを使いました. OS Xでのインストール手順を貼っておきます.

  • binuitls 2.23
  • gcc 3.4.6
1
2
3
4
5
6
$ wget http://ftp.gnu.org/gnu/binutils/binutils-2.23.tar.gz
$ tar xvf binutils-2.23.tar.gz
$ cd binuitls-2.23
$ ./configure --target=pdp11-aout --prefix=/hogehoge
$ make
$ make install
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
$ brew install libmpc
$ brew install gmp
$ brew install mpfr
$ wget http://ftp.tsukuba.wide.ad.jp/software/gcc/releases/gcc-4.8.2/gcc-4.8.2.tar.gz
$ tar xvf gcc-4.8.2.tar.gz
$ cd gcc-4.8.2
$ mkdir work # 別ディレクトリから
$ cd work
$ ../configure --target=pdp11-aout --prefix=/hogehoge
$ make
$ make install
1
2
3
$ pdp11-aout-acc hello.c -O0 -S -o hello.s   # クロスコンパイル
$ pdp11-aout-as hello.s -o hello.o           # アセンブル
$ pdp11-aout-objdump -d hello.o              # 逆アセンブル

simh

pdp11のエミュレータです. V6ならnm /unixとかでシンボルテーブルを探しておけば効率が良いかもしれない.

  • c simhモード -> シミュレーションモード
  • ctrl-e シミュレーションモード -> simhモード
  • set cpu 11/40 CPUの設定
  • att rk0 hoge.dsk ディスクの設定
  • boot ブート
    • boot rk0
  • run 実行スタート
    • run 1020 アドレス1020から実行
  • d(ata) データ配置
    • d 001002 046114 アドレスに046114を書き込む
  • e(xamine) メモリ,レジスタの内容
    • e pc pcの内容
    • e pc-sp レジスタ一覧
    • e r5 r5の内容
    • e KDPRR0-KDPDR7 MMU
    • e -m 0:20 メモリの内容(アセンブラ)
    • e 0:20 メモリの内容(バイナリ)
    • -m(命令),-a(ASCII),-x(16進)
  • s(tep) ステップ実行
  • br(reak) ブレークポイント
    • break 012345
  • q(uit)

遊ぶ

simhを起動した後は,attで仮想ディスクに割り当てて ブートします.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
sim> set cpu 11/40
Disabling XQ
sim> att rk0 hello.o
sim> boot rk0

HALT instruction, PC: 000034 (HALT)
sim> e -m 0:30
0:      BR 20
2:      000012
4:      HALT
6:      HALT
10:     000020
12:     HALT
14:     HALT
16:     HALT
20:     INC R1
...

a.outフォーマットのファイルをそのままブートストラップローダが 実行できているのは,実行ファイル(a.outフォーマット)のヘッダが下の図のようになっていて 0407がbr 020の命令とみなせるからであるようです. 020(8進) = 16バイトで,ヘッダ直後にジャンプします. これで,ブートストラップローダがわざわざa.outのローダを書かなくても大丈夫. うまく出来てる.

1
2
3
4
5
6
7
8
9
offset(バイト) 意味
0              マジックナンバ(0407,0410,0411,テキストセグメントを共有するかどうかなど)
2              テキストセグメントサイズ
4              データ領域サイズ
6              bssサイズ
8              シンボルテーブルサイズ
10             0
12             使用されない
14             リロケーションフラグ