From: slack Date: Sun, 22 Jun 2008 04:23:38 +0000 (+0200) Subject: Iniciado debugger. X-Git-Tag: v0.1~51 X-Git-Url: http://slack.codemaniacs.com/git/?a=commitdiff_plain;h=3f60e66ad645c17bae8f4019fc412085fd44c813;p=wenboi.git Iniciado debugger. Bugfix en core, en calculos de direcciones de 16 bits. --- diff --git a/Makefile b/Makefile index 0c67d37..2512b13 100644 --- a/Makefile +++ b/Makefile @@ -15,7 +15,8 @@ GBMemory.o: GBMemory.cc GBMemory.h Logger.h MBC.o: MBC.cc MBC.h Logger.h g++ $(CXXFLAGS) -c -o $@ $< -gbcore.o: gbcore.cc gbcore.h GBRom.h Logger.h MBC.h GBMemory.h +gbcore.o: gbcore.cc gbcore.h opcodes.h disasm.h \ + GBRom.h Logger.h MBC.h GBMemory.h g++ $(CXXFLAGS) -c -o $@ $< tests/test_gbrom: GBRom.cc GBRom.h diff --git a/disasm.h b/disasm.h new file mode 100644 index 0000000..51b2132 --- /dev/null +++ b/disasm.h @@ -0,0 +1,165 @@ +#define dis_for_each_register(opA, opB, opC, opD, opE, opH, opL, name, macro) \ + macro(opA, name, A) \ + macro(opB, name, B) \ + macro(opC, name, C) \ + macro(opD, name, D) \ + macro(opE, name, E) \ + macro(opH, name, H) \ + macro(opL, name, L) + +#define dis_for_each_register16(opBC, opDE, opHL, opSP, name, macro) \ + macro(opBC, name, BC) \ + macro(opDE, name, DE) \ + macro(opHL, name, HL) \ + macro(opSP, name, SP) + +#define dis(opcode, name) \ + case opcode: \ + result << name; \ + break; + +// OP reg +#define dis_reg(opcode, name, reg) \ + case opcode: \ + result << name << " " << #reg; \ + break; + + +// OP reg16 +#define dis_reg16(opcode, name, reg16) \ + case opcode: \ + result << name << " " << #reg16; \ + break; + +// OP (reg16) +#define dis__reg16_(opcode, name, reg16) \ + case opcode: \ + result << name << " (" << #reg16 << ")"; \ + break; + +// OP inm8 +#define dis_inm8(opcode, name) \ + case opcode: \ + result << name << " 0x" << std::setw(2) << \ + int(memory.read(PC++)); \ + break; + +// OP inm16 +#define dis_inm16(opcode, name) \ + case opcode: \ + result << name << " 0x" << std::setw(4) << \ + int(memory.read(PC)+(memory.read(PC+1) << 8)); \ + PC += 2; \ + break; + +#define dis_reg_inm(opcode, name, reg) \ + case opcode: \ + result << name << " " << #reg << ", 0x" << std::setw(2) << \ + int(memory.read(PC++)); \ + break; + +#define dis_reg16_inm(opcode, name, reg16) \ + case opcode: \ + result << name << " " << #reg16 << ", 0x" << \ + std::setw(4) << \ + int(memory.read(PC)+(memory.read(PC+1) << 8)); \ + PC += 2; \ + break; + +#define dis_reg16_inm8(opcode, name, reg16) \ + case opcode: \ + result << name << " " << #reg16 << ", 0x" << \ + std::setw(2) << \ + int(memory.read(PC++)); \ + break; + +#define dis_reg_reg(opcode, name, reg1, reg2) \ + case opcode: \ + result << name << " " << #reg1 << ", " << #reg2; \ + break; + +#define dis_A_reg(opcode, name, reg2) dis_reg_reg(opcode, name, A, reg2) +#define dis_B_reg(opcode, name, reg2) dis_reg_reg(opcode, name, B, reg2) +#define dis_C_reg(opcode, name, reg2) dis_reg_reg(opcode, name, C, reg2) +#define dis_D_reg(opcode, name, reg2) dis_reg_reg(opcode, name, D, reg2) +#define dis_E_reg(opcode, name, reg2) dis_reg_reg(opcode, name, E, reg2) +#define dis_H_reg(opcode, name, reg2) dis_reg_reg(opcode, name, H, reg2) +#define dis_L_reg(opcode, name, reg2) dis_reg_reg(opcode, name, L, reg2) + +#define dis_reg16_reg16(opcode, name, reg16_1, reg16_2) \ + case opcode: \ + result << name << " " << #reg16_1 << ", " << #reg16_2; \ + break; + +#define dis_HL_reg16(opcode, name, reg16_2) dis_reg16_reg16(opcode, name, HL, reg16_2) + +// OP reg, (reg16) +#define dis_reg__reg16_(opcode, name, reg, reg16) \ + case opcode: \ + result << name << " " << #reg << ", (" << #reg16 << ")"; \ + break; + +// OP reg, (HL) +#define dis_reg__HL_(opcode, name, reg) dis_reg__reg16_(opcode, name, reg, HL) + +// OP reg, (inm) +#define dis_reg__inm_(opcode, name, reg) \ + case opcode: \ + result << name << " " << #reg << ", (0x" << \ + std::setw(4) << \ + int(memory.read(PC) + (memory.read(PC+1)<<8)) << \ + ")"; \ + PC += 2; \ + break; + +// OP (reg16), reg +#define dis__reg16__reg(opcode, name, reg16, reg) \ + case opcode: \ + result << name << " (" << #reg16 << "), " << #reg; \ + break; + +// OP (HL), reg +#define dis__HL__reg(opcode, name, reg) dis__reg16__reg(opcode, name, HL, reg) + +// OP (inm), reg +#define dis__inm__reg(opcode, name, reg) \ + case opcode: \ + result << name << " (0x" << \ + std::setw(4) << \ + int(memory.read(PC) + (memory.read(PC+1)<<8)) << \ + "), " << #reg; \ + PC += 2; \ + break; + +// OP (inm), reg16 +#define dis__inm__reg16(opcode, name, reg16) \ + case opcode: \ + result << name << " (0x" << \ + std::setw(4) << \ + int(memory.read(PC) + (memory.read(PC+1)<<8)) << \ + "), " << #reg16; \ + PC += 2; \ + break; + +// OP (reg16), inm +#define dis__reg16__inm(opcode, name, reg16) \ + case opcode: \ + result << name << " (" << #reg16 << "), 0x" << \ + std::setw(2) << \ + int(memory.read(PC++)); \ + break; + + + +//////////////////////////////////////////////////////////// + + + + + + + + + + + diff --git a/gbcore.cc b/gbcore.cc index 0168f86..1229854 100644 --- a/gbcore.cc +++ b/gbcore.cc @@ -76,7 +76,7 @@ void GameBoy::reset() #include "opcodes.h" -void GameBoy::run_cycle() +GameBoy::run_status GameBoy::run_cycle() { // Check for interrupts before opcode fetching u8 IE; @@ -118,17 +118,9 @@ void GameBoy::run_cycle() } } - - - int prefix; int opcode; opcode = memory.read(regs.PC++); - if (opcode == 0xCB) - { - prefix=opcode; - opcode=memory.read(regs.PC++); - } - + switch(opcode) { // LD n, nn @@ -161,7 +153,7 @@ void GameBoy::run_cycle() regs.A = memory.read(regs.DE); break; case 0xFA: // LD A, (nn) - regs.A = memory.read(memory.read(regs.PC) + memory.read(regs.PC+1)<<8); + regs.A = memory.read(memory.read(regs.PC) + (memory.read(regs.PC+1)<<8)); regs.PC+=2; break; @@ -173,7 +165,7 @@ void GameBoy::run_cycle() memory.write(regs.DE, regs.A); break; case 0xEA: // LD (nn), A - memory.write(memory.read(regs.PC) + memory.read(regs.PC+1)<<8, regs.A); + memory.write(memory.read(regs.PC) + (memory.read(regs.PC+1)<<8), regs.A); regs.PC+=2; break; @@ -259,7 +251,7 @@ void GameBoy::run_cycle() // LD (nn), SP case 0x08: { - int addr = memory.read(regs.PC) + memory.read(regs.PC+1) << 8; + int addr = memory.read(regs.PC) + (memory.read(regs.PC+1) << 8); regs.PC += 2; memory.write(addr, regs.SP); break; @@ -440,7 +432,7 @@ void GameBoy::run_cycle() // CP n for_each_register(0xBF, 0xB8, 0xB9, 0xBA, 0xBB, 0xBC, 0xBD, CP_reg) - case 0xBE: {//SUB (HL) + case 0xBE: {//CP (HL) int res = regs.A - memory.read(regs.HL); int half_res = (regs.A & 0x0F) - (memory.read(regs.HL) & 0x0F); regs.A = static_cast(res); @@ -452,7 +444,7 @@ void GameBoy::run_cycle() break; } - case 0xFE: {//SUB # + case 0xFE: {//CP # int inm = memory.read(regs.PC++); int res = regs.A - inm; int half_res = (regs.A & 0x0F) - (inm & 0x0F); @@ -941,9 +933,33 @@ void GameBoy::run_cycle() } // end switch - std::ostringstream tracemsg; - tracemsg << "t = " << std::dec << cycle_count << - "\tPC = " << std::hex << std::setw(4) << std::setfill('0') << regs.PC << std::endl << + ++cycle_count; + + return NORMAL; +} + +GameBoy::run_status GameBoy::run() +{ + run_status status=NORMAL; + while (status == NORMAL) + { + status = run_cycle(); + } + + return status; +} + + +std::string GameBoy::status_string() +{ + std::string disassembled_instruction; + int length; + disassemble_opcode(regs.PC, disassembled_instruction, length); + + std::ostringstream result; + result << "t = " << std::dec << cycle_count << + "\tPC = " << std::hex << std::setw(4) << std::setfill('0') << regs.PC << + "\t" << disassembled_instruction << std::endl << "A = " << std::hex << std::setw(2) << std::setfill('0') << int(regs.A) << " B = " << std::hex << std::setw(2) << std::setfill('0') << int(regs.B) << " C = " << std::hex << std::setw(2) << std::setfill('0') << int(regs.C) << @@ -952,14 +968,295 @@ void GameBoy::run_cycle() " H = " << std::hex << std::setw(2) << std::setfill('0') << int(regs.H) << " L = " << std::hex << std::setw(2) << std::setfill('0') << int(regs.L) << "\tflags = " << int(regs.flags) << "\tZF = " << check_flag(ZERO_FLAG); - logger.trace(tracemsg.str()); - ++cycle_count; - + return result.str(); } -void GameBoy::run() +#include "disasm.h" +void GameBoy::disassemble_opcode(u16 addr, std::string &instruction, int &length) { -} + int opcode; + u16 PC = addr; + opcode = memory.read(PC++); + std::ostringstream result; + + result << std::hex << std::setfill('0'); + + switch(opcode) + { + // LD n, nn + dis_for_each_register(0x3E, 0x06, 0x0E, 0x16, 0x1E, 0x26, 0x2E, "LD", dis_reg_inm) + + // LD r1,r2 + dis_for_each_register(0x7F, 0x78, 0x79, 0x7A, 0x7B, 0x7C, 0x7D, "LD", dis_A_reg) + dis_for_each_register(0x47, 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, "LD", dis_B_reg) + dis_for_each_register(0x4F, 0x48, 0x49, 0x4A, 0x4B, 0x4C, 0x4D, "LD", dis_C_reg) + dis_for_each_register(0x57, 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, "LD", dis_D_reg) + dis_for_each_register(0x5F, 0x58, 0x59, 0x5A, 0x5B, 0x5C, 0x5D, "LD", dis_E_reg) + dis_for_each_register(0x67, 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, "LD", dis_H_reg) + dis_for_each_register(0x6F, 0x68, 0x69, 0x6A, 0x6B, 0x6C, 0x6D, "LD", dis_L_reg) + + // LD reg, (HL) + dis_for_each_register(0x7E, 0x46, 0x4E, 0x56, 0x5E, 0x66, 0x6E, "LD", dis_reg__HL_) + + // LD (HL), reg + dis_for_each_register(0x77, 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, "LD", dis__HL__reg) + + dis__reg16__inm(0x36, "LD", HL) + + dis_reg__reg16_(0x0A, "LD", A, BC) + dis_reg__reg16_(0x1A, "LD", A, DE) + dis_reg__inm_(0xFA, "LD", A) + + dis__reg16__reg(0x02, "LD", BC, A) + dis__reg16__reg(0x12, "LD", DE, A) + dis__inm__reg(0xEA, "LD", A) + + // LD A, (C) + dis(0xF2, "LD A, (C)") + // LD (C), A + dis(0xE2, "LD (C), A") + + // LD A, (HLD); LD A, (HL-); LDD A,(HL); + dis(0x3A, "LD A, (HL-)") + // LD (HLD), A; LD (HL-), A; LDD (HL), A; + dis(0x32, "LD (HL-), A") + // LD A, (HLI); LD A, (HL+); LDI A, (HL); + dis(0x2A, "LD A, (HL+)") + // LD (HLI), A; LD (HL+), A; LDI (HL), A; + dis(0x22, "LD (HL+), A") + + // LDH (n), A + case 0xE0: { + result << "LD (IO_BASE + 0x" << + std::setw(2) << int(memory.read(PC++)) << "), A"; + break; + } + // LDH A, (n) + case 0xF0: + result << "LD A, (IO_BASE + 0x" << + std::setw(2) << int(memory.read(PC++)) << ")"; + break; + + dis_reg16_inm(0x01, "LD", BC) + dis_reg16_inm(0x11, "LD", DE) + dis_reg16_inm(0x21, "LD", HL) + dis_reg16_inm(0x31, "LD", SP) + + // LD SP, HL + dis(0xF9, "LD SP, HL") + + // LD HL, SP+n + // LDHL SP, n + case 0xF8: + result << "LD HL, SP + 0x"<< std::setw(2) << int(memory.read(PC++)); + break; + + // LD (nn), SP + dis__inm__reg16(0x08, "LD", SP) + + // PUSH nn + dis_reg16(0xF5, "PUSH", AF) + dis_reg16(0xC5, "PUSH", BC) + dis_reg16(0xD5, "PUSH", DE) + dis_reg16(0xE5, "PUSH", HL) + + // POP nn + dis_reg16(0xF1, "POP", AF) + dis_reg16(0xC1, "POP", BC) + dis_reg16(0xD1, "POP", DE) + dis_reg16(0xE1, "POP", HL) + + // 8-bit ALU + // ADD A,reg + dis_for_each_register(0x87, 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, "ADD", dis_A_reg) + + dis_reg__reg16_(0x86, "ADD", A, HL) + dis_reg_inm(0xC6, "ADD", A) + + // ADC A, n + dis_for_each_register(0x8F, 0x88, 0x89, 0x8A, 0x8B, 0x8C, 0x8D, "ADC", dis_A_reg) + + dis_reg__reg16_(0x8E, "ADC", A, HL) + dis_reg_inm(0xCE, "ADC", A) + + // SUB n + dis_for_each_register(0x97, 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, "SUB", dis_reg) + + dis__reg16_(0x96, "SUB", HL) + dis_inm8(0xD6, "SUB") + + // SBC n + dis_for_each_register(0x9F, 0x98, 0x99, 0x9A, 0x9B, 0x9C, 0x9D, "SBC", dis_reg) + + dis__reg16_(0x9E, "SBC", HL) + + // AND n + dis_for_each_register(0xA7, 0xA0, 0xA1, 0xA2, 0xA3, 0xA4, 0xA5, "AND", dis_reg) + + dis__reg16_(0xA6, "AND", HL) + dis_inm8(0xE6, "AND") + + // OR n + dis_for_each_register(0xB7, 0xB0, 0xB1, 0xB2, 0xB3, 0xB4, 0xB5, "OR", dis_reg) + + dis__reg16_(0xB6, "OR", HL) + dis_inm8(0xF6, "OR") + // XOR n + dis_for_each_register(0xAF, 0xA8, 0xA9, 0xAA, 0xAB, 0xAC, 0xAD, "XOR", dis_reg) + + dis__reg16_(0xAE, "XOR", HL) + dis_inm8(0xEE, "XOR") + + // CP n + dis_for_each_register(0xBF, 0xB8, 0xB9, 0xBA, 0xBB, 0xBC, 0xBD, "CP", dis_reg) + + dis__reg16_(0xBE, "CP", HL) + dis_inm8(0xFE, "CP") + + // INC n + dis_for_each_register(0x3C, 0x04, 0x0C, 0x14, 0x1C, 0x24, 0x2C, "INC", dis_reg) + + dis__reg16_(0x34, "INC", HL) + + // DEC n + dis_for_each_register(0x3D, 0x05, 0x0D, 0x15, 0x1D, 0x25, 0x2D, "DEC", dis_reg) + + dis__reg16_(0x35, "DEC", HL) + + // 16-bit ALU + // ADD HL, n + dis_for_each_register16(0x09, 0x19, 0x29, 0x39, "ADD", dis_HL_reg16) + + // ADD SP, # + dis_reg16_inm8(0xE8, "ADD", SP) + + // INC nn + dis_for_each_register16(0x03, 0x13, 0x23, 0x33, "INC", dis_reg16) + + // DEC nn + dis_for_each_register16(0x0B, 0x1B, 0x2B, 0x3B, "DEC", dis_reg16) + + // Miscellaneous instructions + case 0xCB: { + int sub_opcode = memory.read(PC++); + switch(sub_opcode) + { + // SWAP n + dis_for_each_register(0x37, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, "SWAP", dis_reg) + + // SWAP (HL) + dis__reg16_(0x36, "SWAP", HL) + + // RLC n + dis_for_each_register(0x07, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, "RLC", dis_reg) + + // RLC (HL) + dis__reg16_(0x06, "RLC", HL) + + // RL n (through carry) + dis_for_each_register(0x17, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, "RL", dis_reg) + + // RL (HL) (through carry) + dis__reg16_(0x16, "RL", HL) + + // RRC n + dis_for_each_register(0x0F, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, "RRC", dis_reg) + + // RRC (HL) + dis__reg16_(0x0E, "RRC", HL) + + // RR n (through carry) + dis_for_each_register(0x1F, 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, "RR", dis_reg) + // RR (HL) (through carry) + dis__reg16_(0x1E, "RR", HL) + } + break; + } + + dis(0x27, "DAA") + + dis(0x2F, "CPL") + + dis(0x3F, "CCF") + + dis(0x37, "SCF") + dis(0x00, "NOP") + dis(0x76, "HALT") + + dis(0x10, "STOP") + + dis(0xF3, "DI") + + dis(0xFB, "EI") + + // Rotates and shifts + dis(0x07, "RLCA") + + dis(0x17, "RLA") + + dis(0x0F, "RRCA") + + dis(0x1F, "RRA") + + // TODO: Bit instructions + + // Jumps + dis_inm16(0xC3, "JP") + // JP cc, nn + dis_inm16(0xC2, "JP NZ") + dis_inm16(0xCA, "JP Z") + dis_inm16(0xD2, "JP NC") + dis_inm16(0xDA, "JP C") + dis(0xE9, "JP (HL)") + + dis_inm8(0x18, "JR") + dis_inm8(0x20, "JR NZ") + dis_inm8(0x28, "JR Z") + dis_inm8(0x30, "JR NC") + dis_inm8(0x38, "JR C") + + // Calls + dis_inm16(0xCD, "CALL") + // CALL cc, nn + dis_inm16(0xC4, "CALL NZ") + dis_inm16(0xCC, "CALL Z") + dis_inm16(0xD4, "CALL NC") + dis_inm16(0xDC, "CALL C") + + // Restarts + dis(0xC7, "RST 0x00") + dis(0xCF, "RST 0x08") + dis(0xD7, "RST 0x10") + dis(0xDF, "RST 0x18") + dis(0xE7, "RST 0x20") + dis(0xEF, "RST 0x28") + dis(0xF7, "RST 0x30") + dis(0xFF, "RST 0x38") + + // Returns + dis(0xC9, "RET") + // RET cc + dis(0xC0, "RET NZ") + dis(0xC8, "RET Z") + dis(0xD0, "RET NC") + dis(0xD8, "RET C") + + dis(0xD9, "RETI") + + default: + std::ostringstream errmsg; + errmsg << "Unknown opcode 0x"; + errmsg << std::hex << std::setw(2) << std::setfill('0') << opcode; + errmsg << " at 0x" << std::hex << std::setw(4) << PC-1; + errmsg << " (cycle count = " << std::dec << cycle_count << ")"; + logger.trace(errmsg.str()); + break; + + } // end switch + + instruction = result.str(); + length = PC - addr; +} diff --git a/gbcore.h b/gbcore.h index 7012648..04caef3 100644 --- a/gbcore.h +++ b/gbcore.h @@ -10,6 +10,7 @@ union GBRom; class GameBoy { + public: enum GameBoyType { GAMEBOY, GAMEBOYCOLOR, SUPERGAMEBOY } gameboy_type; enum InterruptRequest { IRQ_VBLANK = 0x00, @@ -36,7 +37,7 @@ class GameBoy // CPU Registers // ENDIANNESS WARNING! - struct + struct RegisterSet { union { @@ -81,13 +82,24 @@ class GameBoy void reset_flag(Flag f) { regs.flags &= (~f); } bool check_flag(Flag f) { return ((regs.flags & f) != 0); } - public: + enum run_status + { + NORMAL = 0, + BREAKPOINT = 1, + WATCHPOINT = 2, + TRACEPOINT = 3, + }; + GameBoy(std::string rom_name, GameBoyType type=GAMEBOY); void irq(InterruptRequest i) { memory.write(0xFFFF, memory.read(0xFFFF) | i); } void reset(); - void run_cycle(); - void run(); + run_status run_cycle(); + run_status run(); + + // debug methods + void disassemble_opcode(u16 addr, std::string &instruction, int &length); + std::string status_string(); }; diff --git a/opcodes.h b/opcodes.h index 0a5ba75..537973f 100644 --- a/opcodes.h +++ b/opcodes.h @@ -9,8 +9,8 @@ #define for_each_register(opA, opB, opC, opD, opE, opH, opL, macro) \ macro(opA, A) \ macro(opB, B) \ - macro(opC, C) \ - macro(opD, D) \ + macro(opC, C) \ + macro(opD, D) \ macro(opE, E) \ macro(opH, H) \ macro(opL, L) diff --git a/tests/test_core.cc b/tests/test_core.cc index 5518065..a15dfe3 100644 --- a/tests/test_core.cc +++ b/tests/test_core.cc @@ -1,16 +1,99 @@ #include "../gbcore.h" #include +#include +#include +#include #include +#include + +using std::cin; +using std::cout; +using std::cerr; +using std::endl; +using std::string; +using std::vector; int main(int argc, char **argv) { if (argc != 2) { - std::cerr << "Usage: " << argv[0] << " rom_file" << std::endl; + cerr << "Usage: " << argv[0] << " rom_file" << endl; exit(EXIT_FAILURE); } GameBoy gb(argv[1]); - while(1) + + cout << gb.status_string() << endl; + + bool exit_program=false; + string line, command, last_command; + vector arguments; + + while(!exit_program) { - gb.run_cycle(); + cout << "(wenboi) "; + std::getline(cin, line, '\n'); + if (line == "") command = last_command; + else + { + std::istringstream iss(line); + iss >> command; + arguments.clear(); + while(iss.good()) { + string arg; + iss >> arg; + arguments.push_back(arg); + } + } + + if (command == "step") + { + gb.run_cycle(); + cout << gb.status_string() << endl; + } + else if (command == "run") + { + gb.run(); + } + else if (command == "quit") + { + exit_program = true; + } + else if (command == "disasm") + { + int start, end, pos; + switch(arguments.size()) + { + case 0: + start = gb.regs.PC; + end = start + 256; + break; + case 1: + start = atoi(arguments[0].c_str()); + end = start + 256; + break; + case 2: + default: + start = atoi(arguments[0].c_str()); + end = atoi(arguments[1].c_str()); + break; + } + + pos = start; + while (pos < end) + { + string ins; + int len; + gb.disassemble_opcode(pos, ins, len); + cout << "0x" << std::hex << std::setw(4) << std::setfill('0') << + pos << "\t" << ins << endl; + pos += len; + } + + } + else + { + cout << "Unknown command '" << command << "'" << endl; + } + + last_command = command; } }