Rubyでx86エミュレータ
今まで避けてきたけどついに登場したModR/Mバイト。演算でオペランドがレジスタ同士だったりメモリを使ったりするとオペコードにでてくる1バイトのデータ。8ビットの中に3つのフィールドがあり、mod、reg/opecode、r/mに分かれている。modが2bitでreg/ope…
エミュレータでHelloWorldを実行したかったんだけど画面描画をどうすればいいのかわからなかった。調べてみるとTkが使えそうだったので、Tkを使うことにした。そこでRuby/Tk環境を作るに従ってActive Tclをインストールした。しかし、require "tk"のところで…
今回はCMP命令とJB命令を使って条件分岐を行う。CMP命令は2つのオペランドを使い引き算を行って、フラグレジスタを更新する。ソースオペランドがデスティネーションオペランドより小さいとか大きいとか、同じ値だとかの情報をフラグレジスタに設定する。引…
今日はゼロフラグを利用した条件分岐を行う。本来ならCMP命令などを使うのだが今回は手抜きでADD命令でゼロフラグを更新する。読み込むプログラムはこちら add_je 内容は MOV AL, 0x00 ADD AL, 0x00 JE mov16 loop: JMP loop mov16: MOV AL, 0x10 JMP loop …
今回はx86エミュレータ作りに必須となるマニュアルを紹介する。http://www.intel.com/jp/download/index.htmにある IA-32 インテル® アーキテクチャー・ソフトウェア・デベロッパーズ・マニュアル、上巻: 基本アーキテクチャー IA-32 インテル® アーキテクチ…
今回はEFlagsの更新をメソッドを定義する。その前に前回のソースコードの修正がある。set_carryメソッドだが、これはset_carry!メソッドの間違いである。!を付け忘れた…まだRubyに慣れてないからだろう。それで本題に入る。EFlagsの更新だが、これは四則演算…
今回はEFlagsクラスを定義する。EFlagsに関してはhttp://www.intel.com/jp/download/index.htmの『IA-32 インテル® アーキテクチャ ソフトウェア・デベロッパーズ・マニュアル、上巻: 基本アーキテクチャー』に載っている。ここに載っている全てを定義するわ…
今までメソッドの名前があまりにもJavaだったため、Rubyっぽく修正した。主にgetCode8のような名前だったのがget_code8になっている。また、オブジェクト自体に変更を加えるメソッドの最後に!を付けたり、まだ存在してないが真偽を返すメソッドは最後に?を付…
今回はジャンプ命令追加。その前にvm.rbをいじっておく。getCodeをgetCode8という名前に変え更にgetSignedCode8というメソッドを追加する。これに伴いMoveRImm8やAddALImm8で呼び出しているgetCodeをgetCode8に直す必要がある def getCode8(index = 0) retur…
今回はオペコード0x04にあたるADD AL, Imm8を実装した。その追加に伴い以下のファイルを作成した ./vm/instruction/add/AddALImm8.rb 中身は require "./vm/register/RegisterIndex.rb" include RegisterIndex class AddALImm8 def execute(vm) al = vm.getR…
まず、以下のファイルを作成した ./vm/exception/Exception.rbそして中身は class NotImplementedException < Exception; end これはvmクラスのexecuteメソッドで使っている。取得した命令が未実装の場合、この例外を発生させる。メッセージには命令コードを…
getCodeの文字コードの取得の部分はkeyesberryさんに教えてもらったString#ordを使うことにした def getCode(index = 0) return @memory[@registers[EIP] + index].ord end
MOV AL, 1を実行できるようにしてみた。追加したファイルは以下の通り。またemulator.rbとVM.rbを変更している。 ./vm/instruction/InstructionMap.rb ./vm/instruction/move/MoveRImm8.rb読み込んでいるファイルはadd まずはMoveRImm8.rbから class MoveRIm…
文字列の任意の文字の文字コードの取得方法をsyonbori_techに教えて頂いたので、VMクラスのgetCodeを以下の変更しておく def getCode() return @memory[@registers[EIP]].bytes().to_a()[0] end
とりあえずRubyでx86エミュレータを作ってみる。まず、以下のファイルを作る。 ./emulator.rb ./vm/VM.rb ./vm/register/RegisterIndex.rbまずRegisterIndex.rbから module RegisterIndex EAX = 0 ECX = 1 EDX = 2 EBX = 3 ESP = 4 EBP = 5 ESI = 6 EDI = 7 …
getCodeをまた修正した def getCode() return @memory[@registers[EIP]].unpack("C")[0] end