PDP-11のインタプリタを作った話をする
何のエントリ?
池袋バイナリ勉強会でPDP-11のバイナリをインタプリタ実行するプログラム(以下、インタプリタ)を作った記録です。
間違いや思い込み、より良いやり方があったらご指摘いただけると助かります。
作ったものはkanorimon/pdp11 · GitHubにあります。
誰?
一応動くプログラムが作れる程度の文系SE。
勉強会に参加した発端
パタヘネ読み始めてMIPSで詰み、偶然見つけた池袋バイナリ勉強会へ。
どんな感じでバイナリハックしてたか
- 勉強会(だいたい隔週日曜午後)
- カリキュラムに合わせた課題をもらう
- 課題や周辺知識を説明してもらう
- わからない部分を質問しながら課題をもくもく
- 自宅
- わからない部分をメモしながら課題をもくもく
- 参考書
バイナリハックのカリキュラム
詳しくは池袋バイナリ勉強会wiki(7shi / ikebin / wiki / Home — Bitbucket)を参照。
次からカリキュラムに沿ってやったことと、わかったことを書いていく。
Brainf*ckのインタプリタ作成
Brainf*ckの以下のコードを読み込んで、標準出力に"HellowWorld"を出力するプログラムを作成した。
++++++++[>+++++++++<-]>. <+++++[>++++++<-]>-. <++[>+++<-]>+. . +++. <++++++[>----<-]>. <++++++[>++++<-]>. +++. ------. --------.
PDP-11の逆アセンブラ作成
以下のアセンブリをコンパイルしたPDP-11のバイナリ(a.out)を読み込んで、標準出力に逆アセンブル結果を出力するプログラムを作成した。(単純な逆アセンブラ)
mov $1, r0 sys write hello 6 mov $0, r0 sys exit .data hello: <hello\n>
以下のアセンブリをコンパイルしたPDP-11のバイナリ(a.out)を読み込んで、標準出力に逆アセンブル結果を出力するプログラムを作成した。(アドレス指定方式の取り込み)
mov $1, r0 sys write hello 6 mov $hello, r0 mov $62510, r1 mov r1, (r0) mov $1, r0 sys write hello 6 mov $0, r0 sys exit .data hello: <hello\n>
PDP-11のインタプリタ作成
以下のアセンブリをコンパイルしたPDP-11のバイナリ(a.out)を読み込んで、標準出力に"hello"を出力するプログラムを作成した。(単純なインタプリタ)
mov $1, r0 sys write hello 6 mov $0, r0 sys exit .data hello: <hello\n>
以下のアセンブリをコンパイルしたPDP-11のバイナリ(a.out)を読み込んで、標準出力に"Hello"を出力するプログラムを作成した。(アドレス指定方式の取り込み)
mov $1, r0 sys write hello 6 mov $hello, r0 mov $62510, r1 mov r1, (r0) mov $1, r0 sys write hello 6 mov $0, r0 sys exit .data hello: <hello\n>
以下のソースをコンパイルしたPDP-11のバイナリ(a.out)を読み込んで、結果を標準出力に出力するプログラムを作成した。(各種命令の実装、システムコールの実装)
main(){ write(1, "hello\n", 6); }
main(){
putchar('a');
}
main(){ printf("hello\n"); }
main(){ int a; a = 1234; printf("a=%d\n", a); }
以下のソースをコンパイルしたPDP-11のバイナリ(a.out)を読み込んで、結果を標準出力に出力するプログラムを作成した。(コマンドライン引数の実装)
main(argc, argv){ char **argv; { int i; for(i = 0; i < argc; i++){ printf("argv[%d]=%s\n", i, argv[i]); }
以下のソースをコンパイルしたPDP-11のバイナリ(a.out)を読み込んで、結果を標準出力に出力するプログラムを作成した。(関数呼び出しの実装)
main(){ printo(012345); } printo(v){ int i; putchar(v < 0 ? '1' : '0'); for(i = 0; i < 5; i++){ putchar(((v >> 12) & 7) + '0'); } }
PDP-11のバイナリ(nm)を読み込んで、標準出力にオブジェクトファイルのシンボルリストを出力するプログラムを作成した。(各種命令の実装、システムコールの実装)
# nm a.out
PDP-11のバイナリ(cc)を読み込んで、Cのソースをコンパイルするプログラムを作成した。(更に命令の種類とシステムコールが増える)
# cc test.c
総括
- できるようになったこと
- まだできないこと
- 感じたこと
- 自作インタプリタのバグを見つけるのは正直しんどかった。まさに苦行。
- なんとか完成できたのは、@7shiさんをはじめ、要所要所でアドバイスいただいた池袋バイナリ勉強会の方々のおかげです。ありがとうございます。