今回は前回の[Java][x86エミュレータ]クラス分けを更に進めて、VMの本体のクラスからifを一部消すことにした。今までは
if(code == 0x04){ ... }else if(code == 0x3C){ ... }else if(...){ }...
という感じだったが、今回の変更で以下のようになった。Instructionという名前がですぎな気がするが気にしない
Instruction instruction = InstructionMap.getInstruction(code); instruction.execute(buff, registers, manager);
これをするためにMapを内部に持った(staticだけど…)クラスを作り、そこでコードと実行する命令クラスを関連づけている。これらの命令クラスはInstructionというinterfaceを実装している。以下がそのコードだが、importで*をしているがそのうちリフレクションでクラス名を指定してインスタンスを作るのでimportは消える予定。そのとき、クラス名は外部のファイルかなんかに書いておく。NotImplementedExceptionは聞いたことがある名前だが、ここでは独自のものである
package vm.instruction; import java.util.Map; import java.util.HashMap; import vm.instruction.add.*; import vm.instruction.cmp.*; import vm.instruction.sub.*; import vm.instruction.bios.*; import vm.instruction.jump.*; import vm.instruction.move.*; public class InstructionMap{ private static final Map<Integer, Instruction> map; static{ map = new HashMap<Integer, Instruction>(); map.put(0x04, new AddALImm()); map.put(0x3C, new CompALImm()); map.put(0x75, new JNE()); map.put(0x81C1, new AddCXImm()); map.put(0x81C2, new AddDXImm()); map.put(0x81F9, new CompCXImm()); map.put(0x81FA, new CompDXImm()); map.put(0xB0, new MoveALImm()); map.put(0xB4, new MoveAHImm()); map.put(0xB9, new MoveCXImm()); map.put(0xBA, new MoveDXImm()); map.put(0xCD10, new BiosGraphics()); } public static Instruction getInstruction(int index){ if(!map.containsKey(index)){ throw new NotImplementedException(index); } return map.get(index); } }