まずブートローダを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++; } }