今回はジャンプ命令追加。その前にvm.rbをいじっておく。getCodeをgetCode8という名前に変え更にgetSignedCode8というメソッドを追加する。これに伴いMoveRImm8やAddALImm8で呼び出しているgetCodeをgetCode8に直す必要がある
def getCode8(index = 0) return @memory[@registers[EIP] + index].ord end def getSignedCode8(index = 0) value = getCode8(index) if value & 0x80 > 0 then value = -((~value + 1) & 0xFF) end return value end
getSignedCode8は符号付き整数を返すようにしたgetCode8である。
次にジャンプ命令を実装する。今回はショートジャンプで、現在のプログラムカウンタ(EIP)をgetSignedCode8分だけ増加(getSignedCode8が負数を返せば減少する)させるものである。そして、ジャンプした値に命令長である2を追加する必要がある
class ShortJump8 def execute(vm) vm.addEIP(vm.getSignedCode8(1)) vm.addEIP(2) end end
最後にInstructionMap.rb。ジャンプ命令を追加しておく
require "./vm/instruction/add/AddALImm8.rb" require "./vm/instruction/jump/ShortJump8.rb" require "./vm/instruction/move/MoveRImm8.rb" class InstructionMap def initialize() @instructions = Array.new(256) @instructions[0x04] = AddALImm8.new() for i in 0..7 @instructions[0xB0 + i] = MoveRImm8.new(i) end @instructions[0xEB] = ShortJump8.new() end def getInstruction(code) return @instructions[code] end end
今回のジャンプ命令の実装でaddに含まれる全ての命令を実行することができる。最終的に無限ループするので、コンソール上には何度も同じ内容が表示される。次回こそはフラグレジスタの更新を行う…はず