マイペースなプログラミング日記

DTMやプログラミングにお熱なd-kamiがマイペースに書くブログ

条件分岐 その1 #13

今日はゼロフラグを利用した条件分岐を行う。本来ならCMP命令などを使うのだが今回は手抜きでADD命令でゼロフラグを更新する。読み込むプログラムはこちら
add_je 直
内容は

    MOV AL, 0x00
    ADD AL, 0x00
    JE mov16

loop:
    JMP loop

mov16:
    MOV AL, 0x10
    JMP loop
    

をnasmでアセンブルしたもの。単純にALに0を代入して、その後ALに0を足している。そしてこの演算の結果ゼロフラグが立っていればJE(別名JZ)でmov16に進んで16(0x10)をALに代入して無限ループに入る。ゼロフラグが立ってない場合はmov16にいかずにそのまま無限ループに入る。これをエミュレータで実行するために./vm/instruction/jump/JE.rbを作成する。

JE.rb

class JE
    def execute(vm)
        if(vm.eflags().zero?()) then
            vm.add_eip!(vm.get_signed_code8(1))
        end
        
        vm.add_eip!(2)
    end
end

内容は簡単で、EFlagsのゼロフラグが立っていればプログラムカウンタの値にオペコードの次の値を加算している。その後、命令長である2をプログラムカウンタに足している。これを実行するためにInstructionMapに変更を加える

@instructions[0x74] = JE.new()

requireも忘れずに

require "./vm/instruction/jump/JE.rb"

この変更を加えれば実行できるのだが値の確認をするためにVMクラスのexecute!でEAXの値を出力しておく

def execute!()
    code = get_code8()
    instruction = @instructions.getInstruction(code)
        
    if instruction == nil then
        raise NotImplementedException, "Not Implmeneted 0x" << code.to_s(16)
    end
        
    instruction.execute(self)

    #命令コードと実行したクラスを表示
    puts "0x" << code.to_s(16) << ": " << instruction.class().to_s()
        
    puts "EAX = 0x" + @registers[EAX].to_s(16)
end

これで無限ループに入った後にプログラムを止めれば、AL(EAXの一番下の8bit)が16(0x10)になっているのを確認できるはず。あとゼロフラグが立たないプログラムも載せておく
add_jne 直
内容は

    MOV AL, 0x01
    ADD AL, 0x00
    JE mov16

loop:
    JMP loop

mov16:
    MOV AL, 0x10
    JMP loop

このプログラムではゼロフラグが立たないためmov16にはいかずにALには0x01が入ったまま無限ループに入る。次回は引き算かCMP命令を扱おうと思う