Пример #1
0
        /// <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;
            }
        }