Exemplo n.º 1
0
        public static Instruction DissasembleFromReader(int address, BinaryReader r)
        {
            Instruction ret = new Instruction(address);
            uint        raw = r.ReadUInt32();

            ret.Code = GMCodeUtil.getFromRaw(raw);
            if (DissasembleRawCode(ret, raw))
            {
                switch (ret.Code)
                {
                case GMCode.Call:
                case GMCode.Pop:
                    ret.Operand = r.ReadInt32();
                    break;

                case GMCode.Push:
                {
                    switch (ret.Types[0])
                    {
                    case GM_Type.Long:
                        ret.Operand = r.ReadInt64();
                        break;

                    case GM_Type.Double:
                        ret.Operand = r.ReadDouble();
                        break;

                    case GM_Type.Float:
                        ret.Operand = r.ReadSingle();
                        break;

                    case GM_Type.Bool:
                        ret.Operand = r.ReadInt32() != 0 ? true : false;             // tested, yess this is silly
                        break;

                    case GM_Type.String:
                    case GM_Type.Var:
                    case GM_Type.Int:
                        ret.Operand = r.ReadInt32();
                        break;

                    case GM_Type.Short:
                        break;             // already read in DissasembleRawCode
                    }
                }
                break;
                }
                Debug.Assert(ret.Operand != null);
            }
            return(ret);
        }
Exemplo n.º 2
0
        /// <summary>
        /// Diassembles a raw opcode.
        /// </summary>
        /// <param name="i"></param>
        /// <param name="raw"></param>
        /// <returns>Returns truee if operand is needed</returns>
        public static bool DissasembleRawCode(Instruction i, uint raw)
        {
            i.Code        = GMCodeUtil.getFromRaw(raw);
            i.Types       = null;
            i.Operand     = null;
            i.OperandText = null;                  // we clear eveything just in case
            i._extra      = (short)(0xFFFF & raw); // default for almost eveything
            switch (i.Code)
            {
            case GMCode.Call:
                i.Types = new GM_Type[] { (GM_Type)((raw >> 16) & 15) };
                return(true);

            case GMCode.Exit:
            case GMCode.Ret:
            case GMCode.Not:
            case GMCode.Neg:
            case GMCode.Popz:
                i.Types = new GM_Type[] { (GM_Type)((raw >> 16) & 15) };
                break;

            case GMCode.Pop:
                i.Types = new GM_Type[] { (GM_Type)((raw >> 16) & 15), (GM_Type)((raw >> 20) & 15) };
                return(true);

            case GMCode.Push:
                i.Types = new GM_Type[] { (GM_Type)((raw >> 16) & 15) };
                // this should be in the operand, but just in case make sure extra is right
                if (i.Types[0] == GM_Type.Short)
                {
                    i.Operand = i._extra; // convert it to int
                    break;                // set the operand ourselfs don't need it
                }
                else
                {
                    return(true);     // need to read an operand
                }

            case GMCode.Add:
            case GMCode.Sub:
            case GMCode.Mul:
            case GMCode.Div:
            case GMCode.Mod:
            case GMCode.Or:
            case GMCode.And:
            case GMCode.Dup:
            case GMCode.Sal:
            case GMCode.Seq:
            case GMCode.Sge:
            case GMCode.Sgt:
            case GMCode.Sle:
            case GMCode.Sne:
            case GMCode.Conv:
            case GMCode.Rem:
            case GMCode.Slt:
            case GMCode.Xor:
                i.Types = new GM_Type[] { (GM_Type)((raw >> 16) & 15), (GM_Type)((raw >> 20) & 15) };
                break;

            case GMCode.Break:
                //  i._extra = (int)(0x00FFFFFFF & raw); // never seen the need for more than this
                break;

            case GMCode.B:
            case GMCode.Bf:
            case GMCode.Bt:
                i._extra = i.Address + GMCodeUtil.getBranchOffset(raw);
                break;

            case GMCode.Popenv:
                //  Debug.WriteLine("Popenv: Address: {0}, Extra: {1} {1:X8}  Calc: {2}",i.Address, raw, GMCodeUtil.getBranchOffset(raw));
                if (0xBCF00000 == raw)     // its a popbreak
                {
                    i._extra = 0;
                }
                else
                {
                    i._extra = i.Address + GMCodeUtil.getBranchOffset(raw);
                }
                break;

            case GMCode.Pushenv:
                //    Debug.WriteLine("Pushenv: Address: {0}, Extra: {1} {1:X8}  Calc: {2}",i.Address, raw, GMCodeUtil.getBranchOffset(raw));
                i._extra = i.Address + GMCodeUtil.getBranchOffset(raw);
                break;

            case GMCode.BadOp:
                throw new Exception("Bad opcode?");

            default:
                throw new Exception("Unkonwn opcode");
            }
            return(false);
        }