機械語の勉強会に参加したので8086の逆アセンブラをGoで書いてみてる

HHVMの話を聴いてからというもの、VMというものにどうにも興味がわいて仕方がない今日この頃。世の中の言語処理系も中身はVMだったりするわけで、そもそもVMってどうやって作るのかな−とか考えてたら

というご意見をもらって、初めてPDP-11というものを調べ始めました。UNIX V6の本とかを買って読み始めてみたり、言語処理系の作り方の本にも手をだしてみました。

PDP-11/UNIX V6の勉強会があった

そんな中、@7shiさんが主催されている「池袋バイナリ勉強会」の存在を知りました。なんと、ついこの間までPDP-11の逆アセンブラ(機械語のバイナリからアセンブリ言語を出力する)を作ったりしていたと!参加者の中にはそのままインタプリタまで実装してしまった人もいるではないですか!

これは!と思いこの間開催されいてた機械語入門に参加してきました。Haskellを初めて書きました。

最近は8086というPDP-11よりは現代に近いCPUに移行したとのことで、今回も8086の機械語を学びました。16bitのCPUで、現代のx86やx86_64に直接つながるCPUなので胸熱です。ちなみにx86は以前Courseraのこちらの講義で軽く学習したことがあります。この講義はマジでおすすめ。

逆アセンブラを作るということ

普通機械語とか計算機を理解するときには、レジスタがどうのとかオペランドがどうのとか、構成を理解するところからはじめると思います。実際、僕もなんとなくの雰囲気は聞いたことありました。でもそれでインタプリタとかVMとかが作れるかというと全然無理ですね。

@7shiさんはまず構成はどうでもいいので、与えられる機械語を1:1に対応するアセンブリ言語にただ翻訳する行為を通じて、まず機械語の表現力を学ぶことがとっかかりとして大事とおっしゃっていましたが、実際やってみて強く同感しました。

勉強会では以下のテキストに従って説明8、練習問題2という感じで進んでいって、データシートからバイナリを作成し、ndisasmという既存の逆アセンブラを使って正解を見つつテスト駆動で逆アセンブラをHaskellで実装する方法をばっちり習得してきました。

Goで書いてみた

ただ、このままHaskellで書き進めても他の人と同じだし、なんか違う感じにしたいなと思って、かねてから勉強したかったGoで書いてみることにしました。

とりあえずMOV命令については@7shiさんのHaskell実装があるので、基本それを移植して完成させました。パターンマッチが無いのが辛いですが、それ以外は特に大きく困ることはなかったです。2進数の扱いとかは標準ライブラリを使って逃げましたが。。。

8086tinyを目指す

あと、C言語でたった800行程で実装された8086のVMであるところの8086tinyを見つけて興奮してました。動かしてみたら実際Windows 3.0がMacの上で動きましたよ。。。恐ろしい。。。

BIOSとかのめんどくさいところの実装がすでにあるので、大いに活用させてもらいつつ、8086tinyのGo言語版を目指して残りの命令の逆アセンブラ実装、およびそれが終わったらVMの実装を進めていきたいなと思っています。

なんか色々遠回りしてる感もしますが、コンピュータのいい勉強になっています。