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

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

あまりにもJavaだったため #9

今までメソッドの名前があまりにもJavaだったため、Rubyっぽく修正した。主にgetCode8のような名前だったのがget_code8になっている。また、オブジェクト自体に変更を加えるメソッドの最後に!を付けたり、まだ存在してないが真偽を返すメソッドは最後に?を付けるようにした。変更のあったファイルを載せておく

./vm/vm.rb

require "./vm/instruction/InstructionMap.rb"
require "./vm/register/RegisterIndex.rb"
require "./vm/exception/Exception.rb"

include RegisterIndex

class VM
    def initialize(memorySize)
        @registers = Array.new(REGISTER_COUNT);
        @memory = Array.new(memorySize);
        @instructions = InstructionMap.new()
        
        for i in 0..REGISTER_COUNT - 1
            @registers[i] = 0
        end
    end
    
    def load!(fileName)
        file = open(fileName)
        file.binmode()
        
        buf = file.read(512)
        count = buf.size < 512 ? buf.size - 1 : 511
        
        for i in 0..count
            @memory[0x7C00 + i] = buf[i]
        end
        
        file.close()
        @registers[EIP] = 0x7C00
    end
    
    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()
    end
    
    def get_code8(index = 0)
        return @memory[@registers[EIP] + index].ord
    end
    
    def get_signed_code8(index = 0)
        value = get_code8(index)
        if value & 0x80 > 0 then
            value = -((~value + 1) & 0xFF)
        end
        
        return value
    end
    
    def get_register8(index)
        if index < 4 then
            return get_register8_low(index)
        else
            return get_register8_high(index - 4)
        end
    end
    
    def get_register8_low(index)
       return @registers[index] & 0xFF
    end
    
    def get_register8_high(index)
       return (@registers[index] >> 8) & 0xFF
    end
    
    #8bitレジスタに値を設定する。indexが4未満かどうかで呼び出すメソッド分岐
    def set_register8!(index, data)
        if index < 4 then
            set_register8_low!(index, data)
        else
            set_register8_high(index - 4, data)
        end
    end

    #下位8bitレジスタに値を設定する
    def set_register8_low!(index, data)
        @registers[index] &= 0xFFFFFF00;
        @registers[index] |= (data & 0xFF);
    end
    
    #上位8bitレジスタに値を設定する
    def set_register8_high!(index, data)
        @registers[index] &= 0xFFFF00FF;
        @registers[index] |= (data & 0xFF) << 8;
    end

    def add_eip!(value)
        @registers[EIP] += value
    end
end

./vm/register/RegisterIndex.rb

module RegisterIndex
    EAX = 0
    ECX = 1
    EDX = 2
    EBX = 3
    ESP = 4
    EBP = 5
    ESI = 6
    EDI = 7
    
    EIP = 8
    
    ES = 9
    CS = 10
    SS = 11
    DS = 12
    FS = 13
    GS = 14
    
    REGISTER_COUNT = 15
end

./vm/instruction/add/AddALImm8.rb

require "./vm/register/RegisterIndex.rb"
include RegisterIndex

class AddALImm8
    def execute(vm)
        al = vm.get_register8(EAX)
        al += vm.get_code8(1)
        vm.set_register8!(EAX, al)
        
        vm.add_eip!(2)
    end
end

./vm/instruction/move/MoveRImm8.rb

class MoveRImm8
    def initialize(index)
        @index = index
    end
    
    def execute(vm)
        vm.set_register8!(@index, vm.get_code8(1))
        vm.add_eip!(2);
    end
end

./vm/instruction/jump/ShortJump8.rb

class ShortJump8
    def execute(vm)
        vm.add_eip!(vm.get_signed_code8(1))
        vm.add_eip!(2)
    end
end

./emulator.rb

#! ruby -Ks

require "./vm/VM.rb"

if ARGV.size == 0 then
    puts "ファイル名を指定してください"
    exit()
end

vm = VM.new(1 * 1024 * 1024)
vm.load!(ARGV[0])

loop do
    vm.execute!()
end