/** * Writes the given instruction in assembly-code format. * * @param instr the instruction to display. */ private void writeInstruction(Instruction instr) { String targetLabel = "***"; // get label of destination addr, if instr transfers control if (instr.r == Machine.Reg.CB.ordinal()) targetLabel = addrToLabel.get(instr.d); Machine.Op instruction = Machine.intToOp[instr.op]; asmWrite(String.format("%-7s", instruction.toString())); switch (instruction) { case LOAD: blankN(); writeD(instr.d); writeR('[', instr.r, ']'); break; case LOADA: blankN(); writeD(instr.d); writeR('[', instr.r, ']'); break; case LOADI: break; case LOADL: blankN(); writeD(instr.d); break; case STORE: blankN(); writeD(instr.d); writeR('[', instr.r, ']'); break; case STOREI: break; case CALL: if (instr.r == Machine.Reg.PB.ordinal()) { blankN(); writePrimitive(instr.d); } else { blankN(); asmWrite(targetLabel); } break; case CALLI: break; case RETURN: writeN(instr.n); writeD(instr.d); break; case CALLD: blankN(); writeD(instr.d); break; case PUSH: blankN(); writeD(instr.d); break; case POP: blankN(); writeD(instr.d); break; case JUMP: blankN(); asmWrite(targetLabel); break; case JUMPI: break; case JUMPIF: writeN(instr.n); asmWrite(targetLabel); break; case HALT: writeN(instr.n); break; default: asmWrite("???? "); writeN(instr.n); writeD(instr.d); writeR('[', instr.r, ']'); break; } }
/** disassembles program held in code store */ void disassembleProgram(String asmFileName) { try { asmOut = new FileWriter(asmFileName); } catch (IOException e) { System.out.println("Disassembler: can not create asm output file " + asmName); error = true; return; } // collect all addresses that may be the target of a jump instruction SortedSet<Integer> targets = new TreeSet<Integer>(); for (int addr = Machine.CB; addr < Machine.CT; addr++) { Instruction inst = Machine.code[addr]; Machine.Op op = Machine.intToOp[inst.op]; switch (op) { case CALL: // only consider calls (branches) within code memory (i.e. not primitives) if (inst.r == Machine.Reg.CB.ordinal()) targets.add(inst.d); break; case JUMP: // address following an unconditional branch is an implicit target targets.add(addr + 1); /* FALL THROUGH! */ case JUMPIF: // a jump of any sort creates a branch target targets.add(inst.d); } } // map branch target addresses to unique labels addrToLabel = new HashMap<Integer, String>(); int labelCounter = 10; for (Integer addr : targets) { String label = "L" + labelCounter++; addrToLabel.put(addr, label); } // disassemble each instruction for (int addr = Machine.CB; addr < Machine.CT; addr++) { // generate instruction address asmWrite(String.format("%3d ", addr)); // if this addr is a branch target, output label if (addrToLabel.containsKey(addr)) asmWrite(String.format("%-7s", addrToLabel.get(addr) + ":")); else asmWrite(" "); // instruction writeInstruction(Machine.code[addr]); // newline asmWrite("\n"); } // close output file try { asmOut.close(); } catch (IOException e) { error = true; } }