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

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

某イベント用の簡易x86エミュレータ(2)

ちょっと長くなってきた気もするが現時点のものを全部載せてしまおう。

import java.io.FileInputStream;
import java.io.BufferedInputStream;
import java.io.IOException;

public class Emulator{
    private byte[] memory;    //プログラムを格納するメモリ
    private int[] registers;  //レジスタ郡
    private int eip;          //プログラムカウンタ
    
    private boolean zeroFlag; //ゼロフラグ

    public static final int DEFAULT_MEMORY_SIZE = 1 * 1024 * 1024;
    public static final int AL = 0;
    public static final int CL = 1;
    public static final int DL = 2;
    public static final int BL = 3;
    
    public Emulator(int memorySize){
        memory = new byte[memorySize]; //プログラムを格納する領域の確保
        registers = new int[4];        //現在はレジスタ4つしか使わない
        eip = 0;                       //プログラムカウンタ
    }
    
    public void read(String fileName) throws IOException{
        BufferedInputStream input = null;

        try{
            input = new BufferedInputStream(new FileInputStream(fileName));

            //プログラムを読み込む
            input.read(memory);
            input.close();
        }catch(IOException e){
            if(input != null){
                try{
                    input.close();
                }catch(IOException ioe){
                    throw ioe;
                }
            }
            
            throw e;
        }
    }
    
    public void execute(){
        //オペコードの取得
        int code = memory[eip] & 0xFF;
        
        //オペコードを表示する
        System.out.printf("code = %X\n", code);
        
        if(code == 0xB0){
            movALImm8();
        }else if(code == 0x04){
            addALImm8();
        }else if(code == 0xEB){
            jmpShort();
        }else if(code == 0x3C){
            cmpALImm8();
        }else if(code == 0x74){
            jzShort();
        }
    }
    
    private void movALImm8(){
        //代入を行う
        int value = memory[eip + 1] & 0xFF;
        System.out.printf("MOV AL, 0x%X\n", value);
       
        registers[Emulator.AL] = value;
        eip += 2;
    }
    
    private void addALImm8(){
        //足し算を行う
        int value = memory[eip + 1] & 0xFF;
        System.out.printf("ADD AL, 0x%X\n", value);
        
        registers[Emulator.AL] += value;
        eip += 2;
    }
    
    private void jmpShort(){
        //ジャンプ命令を実行する
        int value = memory[eip + 1];
        System.out.printf("JMP 0x%X\n", value & 0xFF);
        
        eip += value;
        eip += 2;
    }
    
    private void cmpALImm8(){
        //比較を行う
        int value = memory[eip + 1] & 0xFF;
        System.out.printf("CMP AL, 0x%X\n", value);
        
        int result = registers[Emulator.AL] - value;
        zeroFlag = result == 0 ? true : false;
        eip += 2;
    }
    
    private void jzShort(){
        //条件分岐
        int value = memory[eip + 1];
        System.out.printf("JZ 0x%X\n", value);
        
        if(zeroFlag){
            eip += value;
        }
        
        eip += 2;
    }

    public void dumpRegisters(){
        //レジスタを全て出力する
        System.out.println();
        System.out.println("Registers Value");
        System.out.printf("AL = 0x%X\n", registers[Emulator.AL]);
        System.out.printf("CL = 0x%X\n", registers[Emulator.CL]);
        System.out.printf("DL = 0x%X\n", registers[Emulator.DL]);
        System.out.printf("BL = 0x%X\n", registers[Emulator.BL]);
        
        System.out.printf("EIP = 0x%X\n", eip);
        System.out.println("ZeroFlag = " + zeroFlag);
    }
    
    public static void main(String[] args){
        if(args.length == 0){
            System.out.println("引数で読み込むファイルを指定してください");
            System.exit(0);
        }

        try{
            Emulator emulator = new Emulator(Emulator.DEFAULT_MEMORY_SIZE);    

            emulator.read(args[0]);
            
            for(int i = 0; i < 5; i++){
                emulator.execute();
            }
            
            emulator.dumpRegisters();
        }catch(IOException e){
            System.out.println("ファイルの読み込みに失敗しました。");
            e.printStackTrace();
       }
    }
}