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

x86エミュレータやFPGA、WebGLにお熱なd-kamiがマイペースに書くブログ

バイナリ変換

まずブートローダJavaで書きたかったのでJavaバイトコードx86バイナリに変換した。以下のコード(ループ使えよ!)をコンパイルして、変換プログラムにかけたものをqemuやらbochsに読み込ませるとHello World!が表示されるようになった。

public class Hello{
    public static void main(String[] args){
        BIOS.put('H');
        BIOS.put('e');
        BIOS.put('l');
        BIOS.put('l');
        BIOS.put('o');
        BIOS.put(' ');
        BIOS.put('W');
        BIOS.put('o');
        BIOS.put('r');
        BIOS.put('l');
        BIOS.put('d');
        BIOS.put('!');
    }
}

変換プログラムはこんな感じ

import parser.ClassParser;
import parser.struct.StaticMethod;

import java.io.FileOutputStream;
import java.io.BufferedOutputStream;

public class Class2x86{
    private byte[] memory;
    private int index;
    
    public Class2x86(){
        memory = new byte[512];
        index = 0;
        
        memory[510] = (byte)0x55;
        memory[511] = (byte)0xAA;
    }
    
    public static void main(String[] args) throws Exception{
        Class2x86 translator = new Class2x86();
        translator.translate(args[0], args[1]);
    }
    
    public void translate(String className, String x86Name) throws Exception{
        ClassParser parser = new ClassParser();
        parser.parse(className);
        byte[] code = parser.getMethodCode("main");
        
        for(int i = 0; i < code.length; i++){
            int opcode = code[i] & 0xFF;
            
            if(opcode == 0x10){
                put((byte)0x6A);
                put(code[i + 1]);
                i++;
            }else if(opcode == 0xB8){
                int pindex = (code[i + 1] & 0xFF) << 8;
                pindex |= (code[i + 2] & 0xFF);
                StaticMethod method = parser.getStaticMethod(pindex);
                String name = String.format("%s.%s", method.getClassName(), method.getMethodName());

                if("BIOS.put".equals(name)){
                    put((byte)0x58);
                    put((byte)0xB4);
                    put((byte)0x0E);
                    put((byte)0xB7);
                    put((byte)0x00);
                    put((byte)0xB3);
                    put((byte)0x15);
                    put((byte)0xCD);
                    put((byte)0x10);
                    
                    i+=2;
                }
            }
        }
        
        put((byte)0xEB);
        put((byte)0xFE);
        
        BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(x86Name));
        bos.write(memory);
        bos.close();
    }
    
    public void put(byte data){
        memory[index] = data;
        index++;
    }
}