public virtual int GetSourceLine() { return(mAccessor.SrcPosToLine(mPosition) + 1); }
/// <exception cref="VariantException"></exception> public virtual void Disassemble(ScriptBlock data, int start, int end) { // dis-assemble the intermediate code. // "output_func" points a line output function. //String s; string msg; string com; int prevline = -1; int curline = -1; if (end <= 0) { end = mCode.Length; } if (end > mCode.Length) { end = mCode.Length; } for (int i = start; i < end;) { msg = null; com = null; int size; int srcpos = mAccessor.CodePosToSrcPos(i); int line = mAccessor.SrcPosToLine(srcpos); // output source lines as comment if (curline == -1 || curline <= line) { if (curline == -1) { curline = line; } int nl = line - curline; while (curline <= line) { if (nl < 3 || nl >= 3 && line - curline <= 2) { //int len; string src = mAccessor.GetLine(curline); OutputFuncSrc(src, string.Empty, curline, data); curline++; } else { curline = line - 2; } } } else { if (prevline != line) { string src = mAccessor.GetLine(line); OutputFuncSrc(src, string.Empty, line, data); } } prevline = line; switch (mCode[i]) { case VM_NOP: { // decode each instructions msg = "nop"; size = 1; break; } case VM_NF: { msg = "nf"; size = 1; break; } case VM_CONST: { msg = string.Format("const %%%d, *%d", mCode[i + 1], mCode[i + 2]); if (mData != null) { com = string.Format("*%d = %s", mCode[i + 2], Utils.VariantToReadableString(mData [mCode[i + 2]])); } size = 3; break; } case VM_CP: { // instructions that // 1. have two operands that represent registers. // 2. do not have property access variants. msg = string.Format("cp %%%d, %%%d", mCode[i + 1], mCode[i + 2]); size = 3; break; } case VM_CEQ: { msg = string.Format("ceq %%%d, %%%d", mCode[i + 1], mCode[i + 2]); size = 3; break; } case VM_CDEQ: { msg = string.Format("cdeq %%%d, %%%d", mCode[i + 1], mCode[i + 2]); size = 3; break; } case VM_CLT: { msg = string.Format("clt %%%d, %%%d", mCode[i + 1], mCode[i + 2]); size = 3; break; } case VM_CGT: { msg = string.Format("cgt %%%d, %%%d", mCode[i + 1], mCode[i + 2]); size = 3; break; } case VM_CHKINS: { msg = string.Format("chkins %%%d, %%%d", mCode[i + 1], mCode[i + 2]); size = 3; break; } case VM_LOR: { // instructions that // 1. have two operands that represent registers. // 2. have property access variants msg = string.Format("lor %%%d, %%%d", mCode[i + 1], mCode[i + 2]); size = 3; break; } case VM_LOR + 1: { msg = string.Format("lorpd %%%d, %%%d.*%d, %%%d", mCode[i + 1], mCode[i + 2], mCode [i + 3], mCode[i + 4]); if (mData != null) { com = string.Format("*%d = %s", mCode[i + 3], Utils.VariantToReadableString(mData [mCode[i + 3]])); } size = 5; break; } case VM_LOR + 2: { msg = string.Format("lorpi %%%d, %%%d.%%%d, %%%d", mCode[i + 1], mCode[i + 2], mCode [i + 3], mCode[i + 4]); size = 5; break; } case VM_LOR + 3: { msg = string.Format("lorp %%%d, %%%d, %%%d", mCode[i + 1], mCode[i + 2], mCode[i + 3]); size = 4; break; } case VM_LAND: { // OP2_DISASM msg = string.Format("land %%%d, %%%d", mCode[i + 1], mCode[i + 2]); size = 3; break; } case VM_LAND + 1: { msg = string.Format("landpd %%%d, %%%d.*%d, %%%d", mCode[i + 1], mCode[i + 2], mCode [i + 3], mCode[i + 4]); if (mData != null) { com = string.Format("*%d = %s", mCode[i + 3], Utils.VariantToReadableString(mData [mCode[i + 3]])); } size = 5; break; } case VM_LAND + 2: { msg = string.Format("landpi %%%d, %%%d.%%%d, %%%d", mCode[i + 1], mCode[i + 2], mCode [i + 3], mCode[i + 4]); size = 5; break; } case VM_LAND + 3: { msg = string.Format("landp %%%d, %%%d, %%%d", mCode[i + 1], mCode[i + 2], mCode[i + 3]); size = 4; break; } case VM_BOR: { // OP2_DISASM msg = string.Format("bor %%%d, %%%d", mCode[i + 1], mCode[i + 2]); size = 3; break; } case VM_BOR + 1: { msg = string.Format("borpd %%%d, %%%d.*%d, %%%d", mCode[i + 1], mCode[i + 2], mCode [i + 3], mCode[i + 4]); if (mData != null) { com = string.Format("*%d = %s", mCode[i + 3], Utils.VariantToReadableString(mData [mCode[i + 3]])); } size = 5; break; } case VM_BOR + 2: { msg = string.Format("borpi %%%d, %%%d.%%%d, %%%d", mCode[i + 1], mCode[i + 2], mCode [i + 3], mCode[i + 4]); size = 5; break; } case VM_BOR + 3: { msg = string.Format("borp %%%d, %%%d, %%%d", mCode[i + 1], mCode[i + 2], mCode[i + 3]); size = 4; break; } case VM_BXOR: { // OP2_DISASM msg = string.Format("bxor %%%d, %%%d", mCode[i + 1], mCode[i + 2]); size = 3; break; } case VM_BXOR + 1: { msg = string.Format("bxorpd %%%d, %%%d.*%d, %%%d", mCode[i + 1], mCode[i + 2], mCode [i + 3], mCode[i + 4]); if (mData != null) { com = string.Format("*%d = %s", mCode[i + 3], Utils.VariantToReadableString(mData [mCode[i + 3]])); } size = 5; break; } case VM_BXOR + 2: { msg = string.Format("bxorpi %%%d, %%%d.%%%d, %%%d", mCode[i + 1], mCode[i + 2], mCode [i + 3], mCode[i + 4]); size = 5; break; } case VM_BXOR + 3: { msg = string.Format("bxorp %%%d, %%%d, %%%d", mCode[i + 1], mCode[i + 2], mCode[i + 3]); size = 4; break; } case VM_BAND: { // OP2_DISASM msg = string.Format("band %%%d, %%%d", mCode[i + 1], mCode[i + 2]); size = 3; break; } case VM_BAND + 1: { msg = string.Format("bandpd %%%d, %%%d.*%d, %%%d", mCode[i + 1], mCode[i + 2], mCode [i + 3], mCode[i + 4]); if (mData != null) { com = string.Format("*%d = %s", mCode[i + 3], Utils.VariantToReadableString(mData [mCode[i + 3]])); } size = 5; break; } case VM_BAND + 2: { msg = string.Format("bandpi %%%d, %%%d.%%%d, %%%d", mCode[i + 1], mCode[i + 2], mCode [i + 3], mCode[i + 4]); size = 5; break; } case VM_BAND + 3: { msg = string.Format("bandp %%%d, %%%d, %%%d", mCode[i + 1], mCode[i + 2], mCode[i + 3]); size = 4; break; } case VM_SAR: { // OP2_DISASM msg = string.Format("sar %%%d, %%%d", mCode[i + 1], mCode[i + 2]); size = 3; break; } case VM_SAR + 1: { msg = string.Format("sarpd %%%d, %%%d.*%d, %%%d", mCode[i + 1], mCode[i + 2], mCode [i + 3], mCode[i + 4]); if (mData != null) { com = string.Format("*%d = %s", mCode[i + 3], Utils.VariantToReadableString(mData [mCode[i + 3]])); } size = 5; break; } case VM_SAR + 2: { msg = string.Format("sarpi %%%d, %%%d.%%%d, %%%d", mCode[i + 1], mCode[i + 2], mCode [i + 3], mCode[i + 4]); size = 5; break; } case VM_SAR + 3: { msg = string.Format("sarp %%%d, %%%d, %%%d", mCode[i + 1], mCode[i + 2], mCode[i + 3]); size = 4; break; } case VM_SAL: { // OP2_DISASM msg = string.Format("sal %%%d, %%%d", mCode[i + 1], mCode[i + 2]); size = 3; break; } case VM_SAL + 1: { msg = string.Format("salpd %%%d, %%%d.*%d, %%%d", mCode[i + 1], mCode[i + 2], mCode [i + 3], mCode[i + 4]); if (mData != null) { com = string.Format("*%d = %s", mCode[i + 3], Utils.VariantToReadableString(mData [mCode[i + 3]])); } size = 5; break; } case VM_SAL + 2: { msg = string.Format("salpi %%%d, %%%d.%%%d, %%%d", mCode[i + 1], mCode[i + 2], mCode [i + 3], mCode[i + 4]); size = 5; break; } case VM_SAL + 3: { msg = string.Format("salp %%%d, %%%d, %%%d", mCode[i + 1], mCode[i + 2], mCode[i + 3]); size = 4; break; } case VM_SR: { // OP2_DISASM msg = string.Format("sr %%%d, %%%d", mCode[i + 1], mCode[i + 2]); size = 3; break; } case VM_SR + 1: { msg = string.Format("srpd %%%d, %%%d.*%d, %%%d", mCode[i + 1], mCode[i + 2], mCode [i + 3], mCode[i + 4]); if (mData != null) { com = string.Format("*%d = %s", mCode[i + 3], Utils.VariantToReadableString(mData [mCode[i + 3]])); } size = 5; break; } case VM_SR + 2: { msg = string.Format("srpi %%%d, %%%d.%%%d, %%%d", mCode[i + 1], mCode[i + 2], mCode [i + 3], mCode[i + 4]); size = 5; break; } case VM_SR + 3: { msg = string.Format("srp %%%d, %%%d, %%%d", mCode[i + 1], mCode[i + 2], mCode[i + 3]); size = 4; break; } case VM_ADD: { // OP2_DISASM msg = string.Format("add %%%d, %%%d", mCode[i + 1], mCode[i + 2]); size = 3; break; } case VM_ADD + 1: { msg = string.Format("addpd %%%d, %%%d.*%d, %%%d", mCode[i + 1], mCode[i + 2], mCode [i + 3], mCode[i + 4]); if (mData != null) { com = string.Format("*%d = %s", mCode[i + 3], Utils.VariantToReadableString(mData [mCode[i + 3]])); } size = 5; break; } case VM_ADD + 2: { msg = string.Format("addpi %%%d, %%%d.%%%d, %%%d", mCode[i + 1], mCode[i + 2], mCode [i + 3], mCode[i + 4]); size = 5; break; } case VM_ADD + 3: { msg = string.Format("addp %%%d, %%%d, %%%d", mCode[i + 1], mCode[i + 2], mCode[i + 3]); size = 4; break; } case VM_SUB: { // OP2_DISASM msg = string.Format("sub %%%d, %%%d", mCode[i + 1], mCode[i + 2]); size = 3; break; } case VM_SUB + 1: { msg = string.Format("subpd %%%d, %%%d.*%d, %%%d", mCode[i + 1], mCode[i + 2], mCode [i + 3], mCode[i + 4]); if (mData != null) { com = string.Format("*%d = %s", mCode[i + 3], Utils.VariantToReadableString(mData [mCode[i + 3]])); } size = 5; break; } case VM_SUB + 2: { msg = string.Format("subpi %%%d, %%%d.%%%d, %%%d", mCode[i + 1], mCode[i + 2], mCode [i + 3], mCode[i + 4]); size = 5; break; } case VM_SUB + 3: { msg = string.Format("subp %%%d, %%%d, %%%d", mCode[i + 1], mCode[i + 2], mCode[i + 3]); size = 4; break; } case VM_MOD: { // OP2_DISASM msg = string.Format("mod %%%d, %%%d", mCode[i + 1], mCode[i + 2]); size = 3; break; } case VM_MOD + 1: { msg = string.Format("modpd %%%d, %%%d.*%d, %%%d", mCode[i + 1], mCode[i + 2], mCode [i + 3], mCode[i + 4]); if (mData != null) { com = string.Format("*%d = %s", mCode[i + 3], Utils.VariantToReadableString(mData [mCode[i + 3]])); } size = 5; break; } case VM_MOD + 2: { msg = string.Format("modpi %%%d, %%%d.%%%d, %%%d", mCode[i + 1], mCode[i + 2], mCode [i + 3], mCode[i + 4]); size = 5; break; } case VM_MOD + 3: { msg = string.Format("modp %%%d, %%%d, %%%d", mCode[i + 1], mCode[i + 2], mCode[i + 3]); size = 4; break; } case VM_DIV: { // OP2_DISASM msg = string.Format("div %%%d, %%%d", mCode[i + 1], mCode[i + 2]); size = 3; break; } case VM_DIV + 1: { msg = string.Format("divpd %%%d, %%%d.*%d, %%%d", mCode[i + 1], mCode[i + 2], mCode [i + 3], mCode[i + 4]); if (mData != null) { com = string.Format("*%d = %s", mCode[i + 3], Utils.VariantToReadableString(mData [mCode[i + 3]])); } size = 5; break; } case VM_DIV + 2: { msg = string.Format("divpi %%%d, %%%d.%%%d, %%%d", mCode[i + 1], mCode[i + 2], mCode [i + 3], mCode[i + 4]); size = 5; break; } case VM_DIV + 3: { msg = string.Format("divp %%%d, %%%d, %%%d", mCode[i + 1], mCode[i + 2], mCode[i + 3]); size = 4; break; } case VM_IDIV: { // OP2_DISASM msg = string.Format("idiv %%%d, %%%d", mCode[i + 1], mCode[i + 2]); size = 3; break; } case VM_IDIV + 1: { msg = string.Format("idivpd %%%d, %%%d.*%d, %%%d", mCode[i + 1], mCode[i + 2], mCode [i + 3], mCode[i + 4]); if (mData != null) { com = string.Format("*%d = %s", mCode[i + 3], Utils.VariantToReadableString(mData [mCode[i + 3]])); } size = 5; break; } case VM_IDIV + 2: { msg = string.Format("idivpi %%%d, %%%d.%%%d, %%%d", mCode[i + 1], mCode[i + 2], mCode [i + 3], mCode[i + 4]); size = 5; break; } case VM_IDIV + 3: { msg = string.Format("idivp %%%d, %%%d, %%%d", mCode[i + 1], mCode[i + 2], mCode[i + 3]); size = 4; break; } case VM_MUL: { // OP2_DISASM msg = string.Format("mul %%%d, %%%d", mCode[i + 1], mCode[i + 2]); size = 3; break; } case VM_MUL + 1: { msg = string.Format("mulpd %%%d, %%%d.*%d, %%%d", mCode[i + 1], mCode[i + 2], mCode [i + 3], mCode[i + 4]); if (mData != null) { com = string.Format("*%d = %s", mCode[i + 3], Utils.VariantToReadableString(mData [mCode[i + 3]])); } size = 5; break; } case VM_MUL + 2: { msg = string.Format("mulpi %%%d, %%%d.%%%d, %%%d", mCode[i + 1], mCode[i + 2], mCode [i + 3], mCode[i + 4]); size = 5; break; } case VM_MUL + 3: { msg = string.Format("mulp %%%d, %%%d, %%%d", mCode[i + 1], mCode[i + 2], mCode[i + 3]); size = 4; break; } case VM_TT: { // OP2_DISASM // instructions that have one operand which represent a register, // except for inc, dec msg = string.Format("tt %%%d", mCode[i + 1]); size = 2; break; } case VM_TF: { msg = string.Format("tf %%%d", mCode[i + 1]); size = 2; break; } case VM_SETF: { msg = string.Format("setf %%%d", mCode[i + 1]); size = 2; break; } case VM_SETNF: { msg = string.Format("setnf %%%d", mCode[i + 1]); size = 2; break; } case VM_LNOT: { msg = string.Format("lnot %%%d", mCode[i + 1]); size = 2; break; } case VM_BNOT: { msg = string.Format("bnot %%%d", mCode[i + 1]); size = 2; break; } case VM_ASC: { msg = string.Format("asc %%%d", mCode[i + 1]); size = 2; break; } case VM_CHR: { msg = string.Format("chr %%%d", mCode[i + 1]); size = 2; break; } case VM_NUM: { msg = string.Format("num %%%d", mCode[i + 1]); size = 2; break; } case VM_CHS: { msg = string.Format("chs %%%d", mCode[i + 1]); size = 2; break; } case VM_CL: { msg = string.Format("cl %%%d", mCode[i + 1]); size = 2; break; } case VM_INV: { msg = string.Format("inv %%%d", mCode[i + 1]); size = 2; break; } case VM_CHKINV: { msg = string.Format("chkinv %%%d", mCode[i + 1]); size = 2; break; } case VM_TYPEOF: { msg = string.Format("typeof %%%d", mCode[i + 1]); size = 2; break; } case VM_EVAL: { msg = string.Format("eval %%%d", mCode[i + 1]); size = 2; break; } case VM_EEXP: { msg = string.Format("eexp %%%d", mCode[i + 1]); size = 2; break; } case VM_INT: { msg = string.Format("int %%%d", mCode[i + 1]); size = 2; break; } case VM_REAL: { msg = string.Format("real %%%d", mCode[i + 1]); size = 2; break; } case VM_STR: { msg = string.Format("str %%%d", mCode[i + 1]); size = 2; break; } case VM_OCTET: { msg = string.Format("octet %%%d", mCode[i + 1]); size = 2; break; } case VM_CCL: { msg = string.Format("ccl %%%d-%%%d", mCode[i + 1], mCode[i + 1] + mCode[i + 2] - 1); size = 3; break; } case VM_INC: { // inc and dec msg = string.Format("inc %%%d", mCode[i + 1]); size = 2; break; } case VM_INC + 1: { msg = string.Format("incpd %%%d, %%%d.*%d", mCode[i + 1], mCode[i + 2], mCode[i + 3]); if (mData != null) { com = string.Format("*%d = %s", mCode[i + 3], Utils.VariantToReadableString(mData [mCode[i + 3]])); } size = 4; break; } case VM_INC + 2: { msg = string.Format("incpi %%%d, %%%d.%%%d", mCode[i + 1], mCode[i + 2], mCode[i + 3]); size = 4; break; } case VM_INC + 3: { msg = string.Format("incp %%%d, %%%d", mCode[i + 1], mCode[i + 2]); size = 3; break; } case VM_DEC: { // inc and dec msg = string.Format("dec %%%d", mCode[i + 1]); size = 2; break; } case VM_DEC + 1: { msg = string.Format("decpd %%%d, %%%d.*%d", mCode[i + 1], mCode[i + 2], mCode[i + 3]); if (mData != null) { com = string.Format("*%d = %s", mCode[i + 3], Utils.VariantToReadableString(mData [mCode[i + 3]])); } size = 4; break; } case VM_DEC + 2: { msg = string.Format("decpi %%%d, %%%d.%%%d", mCode[i + 1], mCode[i + 2], mCode[i + 3]); size = 4; break; } case VM_DEC + 3: { msg = string.Format("decp %%%d, %%%d", mCode[i + 1], mCode[i + 2]); size = 3; break; } case VM_JF: { // instructions that have one operand which represents code area msg = string.Format("jf %09d", mCode[i + 1] + i); size = 2; break; } case VM_JNF: { msg = string.Format("jnf %09d", mCode[i + 1] + i); size = 2; break; } case VM_JMP: { msg = string.Format("jmp %09d", mCode[i + 1] + i); size = 2; break; } case VM_CALL: case VM_CALLD: case VM_CALLI: case VM_NEW: { // function call variants msg = string.Format(mCode[i] == VM_CALL ? "call %%%d, %%%d(" : mCode[i] == VM_CALLD ? "calld %%%d, %%%d.*%d(" : mCode[i] == VM_CALLI ? "calli %%%d, %%%d.%%%d(" : "new %%%d, %%%d(" , mCode[i + 1], mCode[i + 2], mCode[i + 3]); int st; // start of arguments if (mCode[i] == VM_CALLD || mCode[i] == VM_CALLI) { st = 5; } else { st = 4; } int num = mCode[i + st - 1]; // st-1 = argument count bool first = true; string buf = null; int c = 0; if (num == -1) { // omit arg size = st; msg += "..."; } else { if (num == -2) { // expand arg st++; num = mCode[i + st - 1]; size = st + num * 2; for (int j = 0; j < num; j++) { if (!first) { msg += ", "; } first = false; switch (mCode[i + st + j * 2]) { case fatNormal: { buf = string.Format("%%%d", mCode[i + st + j * 2 + 1]); break; } case fatExpand: { buf = string.Format("%%%d*", mCode[i + st + j * 2 + 1]); break; } case fatUnnamedExpand: { buf = "*"; break; } } msg += buf; } } else { // normal operation size = st + num; while (num > 0) { if (!first) { msg += ", "; } first = false; buf = string.Format("%%%d", mCode[i + c + st]); c++; msg += buf; num--; } } } msg += ")"; if (mData != null && mCode[i] == VM_CALLD) { com = string.Format("*%d = %s", mCode[i + 3], Utils.VariantToReadableString(mData [mCode[i + 3]])); } break; } case VM_GPD: case VM_GPDS: { // property get direct msg = string.Format(mCode[i] == VM_GPD ? "gpd %%%d, %%%d.*%d" : "gpds %%%d, %%%d.*%d" , mCode[i + 1], mCode[i + 2], mCode[i + 3]); if (mData != null) { com = string.Format("*%d = %s", mCode[i + 3], Utils.VariantToReadableString(mData [mCode[i + 3]])); } size = 4; break; } case VM_SPD: case VM_SPDE: case VM_SPDEH: case VM_SPDS: { // property set direct msg = string.Format(mCode[i] == VM_SPD ? "spd %%%d.*%d, %%%d" : mCode[i] == VM_SPDE ? "spde %%%d.*%d, %%%d" : mCode[i] == VM_SPDEH ? "spdeh %%%d.*%d, %%%d" : "spds %%%d.*%d, %%%d" , mCode[i + 1], mCode[i + 2], mCode[i + 3]); if (mData != null) { com = string.Format("*%d = %s", mCode[i + 2], Utils.VariantToReadableString(mData [mCode[i + 2]])); } size = 4; break; } case VM_GPI: case VM_GPIS: { // property get indirect msg = string.Format(mCode[i] == VM_GPI ? "gpi %%%d, %%%d.%%%d" : "gpis %%%d, %%%d.%%%d" , mCode[i + 1], mCode[i + 2], mCode[i + 3]); size = 4; break; } case VM_SPI: case VM_SPIE: case VM_SPIS: { // property set indirect msg = string.Format(mCode[i] == VM_SPI ? "spi %%%d.%%%d, %%%d" : mCode[i] == VM_SPIE ? "spie %%%d.%%%d, %%%d" : "spis %%%d.%%%d, %%%d", mCode[i + 1], mCode[i + 2], mCode[i + 3]); size = 4; break; } case VM_SETP: { // property set msg = string.Format("setp %%%d, %%%d", mCode[i + 1], mCode[i + 2]); size = 3; break; } case VM_GETP: { // property get msg = string.Format("getp %%%d, %%%d", mCode[i + 1], mCode[i + 2]); size = 3; break; } case VM_DELD: case VM_TYPEOFD: { // member delete direct / typeof direct msg = string.Format(mCode[i] == VM_DELD ? "deld %%%d, %%%d.*%d" : "typeofd %%%d, %%%d.*%d" , mCode[i + 1], mCode[i + 2], mCode[i + 3]); if (mData != null) { com = string.Format("*%d = %s", mCode[i + 3], Utils.VariantToReadableString(mData [mCode[i + 3]])); } size = 4; break; } case VM_DELI: case VM_TYPEOFI: { // member delete indirect / typeof indirect msg = string.Format(mCode[i] == VM_DELI ? "deli %%%d, %%%d.%%%d" : "typeofi %%%d, %%%d.%%%d" , mCode[i + 1], mCode[i + 2], mCode[i + 3]); size = 4; break; } case VM_SRV: { // set return value msg = string.Format("srv %%%d", mCode[i + 1]); size = 2; break; } case VM_RET: { // return msg = "ret"; size = 1; break; } case VM_ENTRY: { // enter try-protected block msg = string.Format("entry %09d, %%%d", mCode[i + 1] + i, mCode[i + 2]); size = 3; break; } case VM_EXTRY: { // exit from try-protected block msg = "extry"; size = 1; break; } case VM_THROW: { msg = string.Format("throw %%%d", mCode[i + 1]); size = 2; break; } case VM_CHGTHIS: { msg = string.Format("chgthis %%%d, %%%d", mCode[i + 1], mCode[i + 2]); size = 3; break; } case VM_GLOBAL: { msg = string.Format("global %%%d", mCode[i + 1]); size = 2; break; } case VM_ADDCI: { msg = string.Format("addci %%%d, %%%d", mCode[i + 1], mCode[i + 2]); size = 3; break; } case VM_REGMEMBER: { msg = "regmember"; size = 1; break; } case VM_DEBUGGER: { msg = "debugger"; size = 1; break; } default: { msg = string.Format("unknown instruction %d", mCode[i]); size = 1; break; } } OutputFunc(msg, com, i, i, size, data); // call the callback i += size; } }