Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.
PDP-11のインタプリタを
作った話
@kanorimon
>誰?
• kano
• Twitter:@kanorimon
• Github:https://github.com/kanorimon/
• 低レイヤ初心者
• 文系SE 兼 情報系大学一年生
• たまにJava書く程度の能力
• パタヘネ...
>何を話すのか?
• 初心者がPDP-11のインタプリタを作ってみた
• 池袋バイナリ勉強会でやったカリキュラムを紹介
• バイナリを教えるときの参考になれば
• PDP-11でない方が良いかもしれませんが……
>カリキュラム
• Brainf*ckのインタプリタ作成
• PDP-11の逆アセンブラ作成
• PDP-11のインタプリタ作成
• UNIX V6のカーネルビルド
>Brainf*ckのインタプリタ作成
ソース
実行結果
>Brainf*ckのインタプリタソース
byte[] mem : メモリをあらわす配列
プログラムをPC=1から順に
読込み、pcの位置にある命
令によって処理を分岐する
int ptr : ポインター
int pc : プログラムカウンタ
>Brainf*ckでわかったこと
• メモリはbyte配列として表現できる
• メモリを読み書きするにはポインタ(アドレス)(添え字)が必要
• 原則として、プログラムは1命令目から順に実行される
• 次に実行する命令がある位置はプログラムカ...
>PDP-11の逆アセンブラ作成
ソース
>PDP-11の逆アセンブラ作成
バイナリ
実行結果
> PDP-11の逆アセンブラソース
仮想メモリ空間をあらわす配列を作成
byte[] mem
バイナリを仮想メモリ空間に読み込み
>PDP-11の逆アセンブラソース
コンディションコードを
あらわす変数を作成
boolean n
boolean z
boolean v
boolean c
レジスタをあらわす配列を作成
int reg[0]~[7]
>PDP-11の逆アセンブラソース
int ptr : ポインター
Int pc : プログラムカウンタ
命令ごとに
ソース/デスティネーションのオペランドを
判定する
命令を1桁ずつ分類して
ニーモニックを判定する
例)000006 : RT...
>PDP-11の逆アセンブラソース
結果を画面に出力
>PDP-11の逆アセンブラでわかったこと
• バイナリ
• 0と1のファイル
• 一定のルール(仕様)をもとに解釈するとアセンブリに書き換えることができ
る(この仕様のセットを命令セットと言う)
• PDP-11
• レジスタは、R0~R7
...
>PDP-11の逆アセンブラ(発展)ソース
アドレッシングモードの取り込み
R1 : R1にオペランドがある
(R1) : R1にオペランドのアドレスがある
(R1)+ : R1オペランドのアドレス、実行後にR1の内容をインクリメント
*(R1...
>PDP-11のインタプリタ作成
ソース
実行結果
> PDP-11のインタプリタソース
仮想メモリ空間をあらわす配列を作成
byte[] mem
バイナリを仮想メモリ空間に読み込み
>PDP-11のインタプリタソース
コンディションコードを
あらわす変数を作成
boolean n
boolean z
boolean v
boolean c
レジスタをあらわす配列を作成
int reg[0]~[7]
>PDP-11の逆アセンブラソース
命令ごとに
レジスタ・メモリの操作を行う
命令を1桁ずつ分類して
ニーモニックを判定する
例)000006 : RTT , 0001xx : JMP
>PDP-11のインタプリタソース
システムコールの実装
read()
write()
exit()
…
>PDP-11のインタプリタ(発展1)
• PDP-11のnmを読み込んで、標準出力にオブジェクトファイル
のシンボルリストを出力した
• PDP-11のccを読み込んで、Cのソースをコンパイルした
>PDP-11のインタプリタ(発展2)
• fork(),exec(),wait()の実装
• リファクタリング
カーネル
クラス
プロセス
クラス
仮想アドレス空間
クラス
>PDP-11のインタプリタでわかったこと
• UNIX V6
• ユーザー空間とカーネル空間は異なる
• プロセスごとに仮想アドレス空間を持ち、MMUがメモリの物理アドレスに変
換する
• 仮想アドレス空間はテキスト/空き領域(マジックナンバ...
>PDP-11のインタプリタでわかったこと
• コンパイラ
• ccは以下の順で実行する
• (Cコンパイラ)/lib/c0
• (Cコンパイラ)/lib/c1
• (アセンブラ)/bin/as
• (アセンブラ)/lib/as2
• (リンカ...
>UNIX V6のカーネルビルド
インタプリタ
CC ロード
UNIX V6
カーネル
UNIX V6
ソース
コンパイル
>UNIX V6のカーネルビルド
• lib1
• cd ken
• java pdp11.Pdp11 -e -s cc -c -O *.c
• java pdp11.Pdp11 -e -s ar r lib1 main.o trap.o si...
>UNIX V6のカーネルビルド
• con/mkconf
• cd conf
• java pdp11.Pdp11 -e -s as m40.s
• rename a.out m40.o
• java pdp11.Pdp11 -e -s cc...
>うまく動かない…
実行ログを確認して
インタプリタのソースから
実装ミスを探す
↓
【よくあったミス】
コンディションコードの設定
システムコールの仕様
>UNIX V6のカーネルビルド結果
• 処理時間→1:50
>UNIX V6のカーネルビルド結果
• 処理時間→1:50→1:50:00
>UNIX V6のカーネルビルド結果
• ボトルネックは10進数の値を8進数に変換して、そのx桁の値を
取得する処理
• 例:42798→0123456→3桁目=3
>UNIX V6のカーネルビルド結果
• 処理時間→1:50→1:50:00→0:07:30
>総括
• 着手から完成まで約半年(100~200時間)程度
• 自分で手を動かしてプログラムを作ることで、楽しく調べながら勉
強を進めることができました
• HACKING本読んでます
• 初心者におすすめな本があれば教えてください
Upcoming SlideShare
Loading in …5
×

PDP-11のインタプリタを作った話

12,416 views

Published on

Published in: Software
  • P15の表記にミスがあります。
    −(R1) : R1にオペランドのアドレス、実行後にR1の内容をデクリメント
    *−(R1) : R1にオペランドへのポインタのアドレス、実行後にR1の内容を2だけデクリメント

    実行「前」です。
       Reply 
    Are you sure you want to  Yes  No
    Your message goes here

PDP-11のインタプリタを作った話

  1. 1. PDP-11のインタプリタを 作った話 @kanorimon
  2. 2. >誰? • kano • Twitter:@kanorimon • Github:https://github.com/kanorimon/ • 低レイヤ初心者 • 文系SE 兼 情報系大学一年生 • たまにJava書く程度の能力 • パタヘネ読み始めてMIPSで詰み、偶然見つけた池袋バイナリ勉強会へ
  3. 3. >何を話すのか? • 初心者がPDP-11のインタプリタを作ってみた • 池袋バイナリ勉強会でやったカリキュラムを紹介 • バイナリを教えるときの参考になれば • PDP-11でない方が良いかもしれませんが……
  4. 4. >カリキュラム • Brainf*ckのインタプリタ作成 • PDP-11の逆アセンブラ作成 • PDP-11のインタプリタ作成 • UNIX V6のカーネルビルド
  5. 5. >Brainf*ckのインタプリタ作成 ソース 実行結果
  6. 6. >Brainf*ckのインタプリタソース byte[] mem : メモリをあらわす配列 プログラムをPC=1から順に 読込み、pcの位置にある命 令によって処理を分岐する int ptr : ポインター int pc : プログラムカウンタ
  7. 7. >Brainf*ckでわかったこと • メモリはbyte配列として表現できる • メモリを読み書きするにはポインタ(アドレス)(添え字)が必要 • 原則として、プログラムは1命令目から順に実行される • 次に実行する命令がある位置はプログラムカウンタが管理している • ジャンプ命令やループ命令はプログラムカウンタを書き換える命令
  8. 8. >PDP-11の逆アセンブラ作成 ソース
  9. 9. >PDP-11の逆アセンブラ作成 バイナリ 実行結果
  10. 10. > PDP-11の逆アセンブラソース 仮想メモリ空間をあらわす配列を作成 byte[] mem バイナリを仮想メモリ空間に読み込み
  11. 11. >PDP-11の逆アセンブラソース コンディションコードを あらわす変数を作成 boolean n boolean z boolean v boolean c レジスタをあらわす配列を作成 int reg[0]~[7]
  12. 12. >PDP-11の逆アセンブラソース int ptr : ポインター Int pc : プログラムカウンタ 命令ごとに ソース/デスティネーションのオペランドを 判定する 命令を1桁ずつ分類して ニーモニックを判定する 例)000006 : RTT , 0001xx : JMP
  13. 13. >PDP-11の逆アセンブラソース 結果を画面に出力
  14. 14. >PDP-11の逆アセンブラでわかったこと • バイナリ • 0と1のファイル • 一定のルール(仕様)をもとに解釈するとアセンブリに書き換えることができ る(この仕様のセットを命令セットと言う) • PDP-11 • レジスタは、R0~R7 • コンディションコードは、N(ネガティブ),Z(ゼロ),V(オーバーフロー),C(キャ リー) • 命令セット
  15. 15. >PDP-11の逆アセンブラ(発展)ソース アドレッシングモードの取り込み R1 : R1にオペランドがある (R1) : R1にオペランドのアドレスがある (R1)+ : R1オペランドのアドレス、実行後にR1の内容をインクリメント *(R1)+ : R1にオペランドへのポインタのアドレス、実行後にR1の内容を2だけインクリメント −(R1) : R1にオペランドのアドレス、実行後にR1の内容をデクリメント *−(R1) : R1にオペランドへのポインタのアドレス、実行後にR1の内容を2だけデクリメント 2(R1) : R1+2がオペランドのアドレス *2(R1) : R1+2がオペランドのポインタへのアドレス
  16. 16. >PDP-11のインタプリタ作成 ソース 実行結果
  17. 17. > PDP-11のインタプリタソース 仮想メモリ空間をあらわす配列を作成 byte[] mem バイナリを仮想メモリ空間に読み込み
  18. 18. >PDP-11のインタプリタソース コンディションコードを あらわす変数を作成 boolean n boolean z boolean v boolean c レジスタをあらわす配列を作成 int reg[0]~[7]
  19. 19. >PDP-11の逆アセンブラソース 命令ごとに レジスタ・メモリの操作を行う 命令を1桁ずつ分類して ニーモニックを判定する 例)000006 : RTT , 0001xx : JMP
  20. 20. >PDP-11のインタプリタソース システムコールの実装 read() write() exit() …
  21. 21. >PDP-11のインタプリタ(発展1) • PDP-11のnmを読み込んで、標準出力にオブジェクトファイル のシンボルリストを出力した • PDP-11のccを読み込んで、Cのソースをコンパイルした
  22. 22. >PDP-11のインタプリタ(発展2) • fork(),exec(),wait()の実装 • リファクタリング カーネル クラス プロセス クラス 仮想アドレス空間 クラス
  23. 23. >PDP-11のインタプリタでわかったこと • UNIX V6 • ユーザー空間とカーネル空間は異なる • プロセスごとに仮想アドレス空間を持ち、MMUがメモリの物理アドレスに変 換する • 仮想アドレス空間はテキスト/空き領域(マジックナンバ0410の場合) /データ+bss/ヒープ/空き領域/スタックとなっている • ファイルはinodeで管理されている • ファイル入出力等の基本機能はシステムコールを呼び出すことで実現して いる • 関数呼び出しをする場合は、スタックに引数と戻り先のアドレスを格納し てからジャンプする
  24. 24. >PDP-11のインタプリタでわかったこと • コンパイラ • ccは以下の順で実行する • (Cコンパイラ)/lib/c0 • (Cコンパイラ)/lib/c1 • (アセンブラ)/bin/as • (アセンブラ)/lib/as2 • (リンカ)/bin/ld
  25. 25. >UNIX V6のカーネルビルド インタプリタ CC ロード UNIX V6 カーネル UNIX V6 ソース コンパイル
  26. 26. >UNIX V6のカーネルビルド • lib1 • cd ken • java pdp11.Pdp11 -e -s cc -c -O *.c • java pdp11.Pdp11 -e -s ar r lib1 main.o trap.o sig.o sysent.o • java pdp11.Pdp11 -e -s ar r lib1 *.o • lib2 • cd dmr • java pdp11.Pdp11 -e –s cc -c -O *.c • java pdp11.Pdp11 -e -s ar r lib2 *.o
  27. 27. >UNIX V6のカーネルビルド • con/mkconf • cd conf • java pdp11.Pdp11 -e -s as m40.s • rename a.out m40.o • java pdp11.Pdp11 -e -s cc mkconf.c • rename a.out mkconf • rkunix • (echo rk& echo tm& echo tc& echo done)| java pdp11.Pdp11 -e -s mkconf • java pdp11.Pdp11 -e -s cc -c c.c • java pdp11.Pdp11 -e -s as l.s • java pdp11.Pdp11 -e -s ld -x a.out m40.o c.o lib1 lib2 • copy a.out rkunix
  28. 28. >うまく動かない… 実行ログを確認して インタプリタのソースから 実装ミスを探す ↓ 【よくあったミス】 コンディションコードの設定 システムコールの仕様
  29. 29. >UNIX V6のカーネルビルド結果 • 処理時間→1:50
  30. 30. >UNIX V6のカーネルビルド結果 • 処理時間→1:50→1:50:00
  31. 31. >UNIX V6のカーネルビルド結果 • ボトルネックは10進数の値を8進数に変換して、そのx桁の値を 取得する処理 • 例:42798→0123456→3桁目=3
  32. 32. >UNIX V6のカーネルビルド結果 • 処理時間→1:50→1:50:00→0:07:30
  33. 33. >総括 • 着手から完成まで約半年(100~200時間)程度 • 自分で手を動かしてプログラムを作ることで、楽しく調べながら勉 強を進めることができました • HACKING本読んでます • 初心者におすすめな本があれば教えてください

×