Exemplo n.º 1
0
        decode_vex_vvvv(ref ud u, ref ud_operand opr, ud_operand_size size)
        {
            byte vvvv;

            Debug.Assert(u.vex_op != 0);
            vvvv = (byte)(((u.vex_op == 0xc4 ? u.vex_b2 : u.vex_b1) >> 3) & 0xf);
            decode_reg(ref u, ref opr, reg_class.REGCLASS_XMM, (byte)(0xf & ~vvvv), size);
        }
Exemplo n.º 2
0
        /*
         * decode_modrm_reg
         *
         *    Decodes reg field of mod/rm byte
         *
         */
        void decode_modrm_reg(ref ud u,
                              ref ud_operand operand,
                              reg_class type,
                              ud_operand_size size)
        {
            byte reg = (byte)((BitOps.REX_R(u._rex) << 3) | BitOps.MODRM_REG(modrm(ref u)));

            decode_reg(ref u, ref operand, type, reg, size);
        }
Exemplo n.º 3
0
 decode_moffset(ref ud u, ud_operand_size size, ref ud_operand opr)
 {
     opr.type  = ud_type.UD_OP_MEM;
     opr.@base = ud_type.UD_NONE;
     opr.index = ud_type.UD_NONE;
     opr.scale = 0;
     opr.size  = (byte)resolve_operand_size(ref u, size);
     decode_mem_disp(ref u, u.adr_mode, ref opr);
 }
Exemplo n.º 4
0
        decode_vex_immreg(ref ud u, ref ud_operand opr, ud_operand_size size)
        {
            byte imm  = (byte)inp_next(ref u);
            byte mask = (byte)(u.dis_mode == 64 ? 0xf : 0x7);

            if (u.error != 0)
            {
                return(u.error);
            }
            Debug.Assert(u.vex_op != 0);
            decode_reg(ref u, ref opr, reg_class.REGCLASS_XMM, (byte)(mask & (imm >> 4)), size);
            return(0);
        }
Exemplo n.º 5
0
        decode_reg(ref ud u,
                   ref ud_operand opr,
                   reg_class type,
                   byte num,
                   ud_operand_size size)
        {
            int reg;

            size = resolve_operand_size(ref u, size);
            switch (type)
            {
            case reg_class.REGCLASS_GPR: reg = (int)decode_gpr(ref u, size, (byte)num); break;

            case reg_class.REGCLASS_MMX: reg = (int)ud_type.UD_R_MM0 + (num & 7); break;

            case reg_class.REGCLASS_XMM: reg = num + (int)(size == ud_operand_size.SZ_QQ ? ud_type.UD_R_YMM0 : ud_type.UD_R_XMM0); break;

            case reg_class.REGCLASS_CR: reg = (int)ud_type.UD_R_CR0 + num; break;

            case reg_class.REGCLASS_DB: reg = (int)ud_type.UD_R_DR0 + num; break;

            case reg_class.REGCLASS_SEG:
            {
                /*
                 * Only 6 segment registers, anything else is an error.
                 */
                if ((num & 7) > 5)
                {
                    u.error        = 1;
                    u.errorMessage = "invalid segment register value\n";
                    return;
                }
                else
                {
                    reg = (int)ud_type.UD_R_ES + (num & 7);
                }
                break;
            }

            default:
                Debug.Assert(false, "invalid register type");
                return;
            }
            opr.type  = ud_type.UD_OP_REG;
            opr.@base = (ud_type)reg;
            opr.size  = (byte)size;
        }
Exemplo n.º 6
0
        decode_imm(ref ud u, ud_operand_size size, ref ud_operand op)
        {
            op.size = (byte)resolve_operand_size(ref u, size);
            op.type = ud_type.UD_OP_IMM;

            switch (op.size)
            {
            case 8: op.lval.@sbyte = (sbyte)inp_uint8(ref u); break;

            case 16: op.lval.uword = inp_uint16(ref u); break;

            case 32: op.lval.udword = inp_uint32(ref u); break;

            case 64: op.lval.uqword = inp_uint64(ref u); break;

            default: return;
            }
        }
Exemplo n.º 7
0
        /* -----------------------------------------------------------------------------
         * decode_gpr() - Returns decoded General Purpose Register
         * -----------------------------------------------------------------------------
         */
        ud_type decode_gpr(ref ud u, ud_operand_size s, byte rm)
        {
            switch ((int)s)
            {
            case 64:
                return(ud_type.UD_R_RAX + rm);

            case 32:
                return(ud_type.UD_R_EAX + rm);

            case 16:
                return(ud_type.UD_R_AX + rm);

            case 8:
                if (u.dis_mode == 64 && u.pfx_rex != 0)
                {
                    if (rm >= 4)
                    {
                        return(ud_type.UD_R_SPL + (rm - 4));
                    }
                    return(ud_type.UD_R_AL + rm);
                }
                else
                {
                    return(ud_type.UD_R_AL + rm);
                }

            case 0:
            default:
                /* invalid size in case of a decode error */
                //Debug.Assert(u.error == 0, "invalid operand size");
                if (u.error == 0)
                {
                    u.error = 1;
                }
                u.errorMessage += Environment.NewLine + "Invalid operand size";
                return(ud_type.UD_NONE);
            }
        }
Exemplo n.º 8
0
        /* -----------------------------------------------------------------------------
         * decode_gpr() - Returns decoded General Purpose Register
         * -----------------------------------------------------------------------------
         */
        ud_type decode_gpr(ref ud u, ud_operand_size s, byte rm)
        {
            switch ((int)s)
            {
            case 64:
                return(ud_type.UD_R_RAX + rm);

            case 32:
                return(ud_type.UD_R_EAX + rm);

            case 16:
                return(ud_type.UD_R_AX + rm);

            case 8:
                if (u.dis_mode == 64 && u.pfx_rex != 0)
                {
                    if (rm >= 4)
                    {
                        return(ud_type.UD_R_SPL + (rm - 4));
                    }
                    return(ud_type.UD_R_AL + rm);
                }
                else
                {
                    return(ud_type.UD_R_AL + rm);
                }

            case 0:
                /* invalid size in case of a decode error */
                Debug.Assert(u.error == 0, "invalid operand size");
                return(ud_type.UD_NONE);

            default:
                Debug.Assert(false, "invalid operand size");
                return(ud_type.UD_NONE);
            }
        }
Exemplo n.º 9
0
        ud_operand_size resolve_operand_size(ref ud u, ud_operand_size oSize)
        {
            switch (oSize)
            {
            case ud_operand_size.SZ_V:
                return((ud_operand_size)u.opr_mode);

            case ud_operand_size.SZ_Z:
                return((ud_operand_size)((u.opr_mode == 16) ? 16 : 32));

            case ud_operand_size.SZ_Y:
                return((ud_operand_size)((u.opr_mode == 16) ? 32 : u.opr_mode));

            case ud_operand_size.SZ_RDQ:
                return((ud_operand_size)((u.dis_mode == 64) ? 64 : 32));

            case ud_operand_size.SZ_X:
                Debug.Assert(u.vex_op != 0);
                return((BitOps.P_VEXL(u.itab_entry.Prefix) > 0 && vex_l(ref u) > 0) ? ud_operand_size.SZ_QQ : ud_operand_size.SZ_DQ);

            default:
                return(oSize);
            }
        }
Exemplo n.º 10
0
        decode_operand(ref ud u,
                       ref ud_operand operand,
                       ud_operand_code type,
                       ud_operand_size size)
        {
            operand.type = ud_type.UD_NONE;
            operand._oprcode = type;

            switch (type)
            {
                case ud_operand_code.OP_A:
                    decode_a(ref u, ref operand);
                    break;
                case ud_operand_code.OP_MR:
                    decode_modrm_rm(ref u, ref operand, (byte)reg_class.REGCLASS_GPR,
                                    BitOps.MODRM_MOD(modrm(ref u)) == 3 ?
                                      size.Mx_reg_size() : size.Mx_mem_size());
                    break;
                case ud_operand_code.OP_F:
                    u.br_far = 1;
                    if (BitOps.MODRM_MOD(modrm(ref u)) == 3)
                    {
                        u.error = 1;
                        u.errorMessage = "expected modrm.mod != 3\n";
                    }
                    decode_modrm_rm(ref u, ref operand, reg_class.REGCLASS_GPR, size);
                    break;
                case ud_operand_code.OP_M:
                    if (BitOps.MODRM_MOD(modrm(ref u)) == 3)
                    {
                        u.error = 1;
                        u.errorMessage = "expected modrm.mod != 3\n";
                    }
                    decode_modrm_rm(ref u, ref operand, reg_class.REGCLASS_GPR, size);
                    break;
                case ud_operand_code.OP_E:
                    decode_modrm_rm(ref u, ref operand, reg_class.REGCLASS_GPR, size);
                    break;
                case ud_operand_code.OP_G:
                    decode_modrm_reg(ref u, ref operand, reg_class.REGCLASS_GPR, size);
                    break;
                case ud_operand_code.OP_sI:
                case ud_operand_code.OP_I:
                    decode_imm(ref u, size, ref operand);
                    break;
                case ud_operand_code.OP_I1:
                    operand.type = ud_type.UD_OP_CONST;
                    operand.lval.udword = 1;
                    break;
                case ud_operand_code.OP_N:
                    if (BitOps.MODRM_MOD(modrm(ref u)) != 3)
                    {
                        u.error = 1;
                        u.errorMessage = "expected modrm.mod == 3\n";
                    }
                    decode_modrm_rm(ref u, ref operand, reg_class.REGCLASS_MMX, size);
                    break;
                case ud_operand_code.OP_Q:
                    decode_modrm_rm(ref u, ref operand, reg_class.REGCLASS_MMX, size);
                    break;
                case ud_operand_code.OP_P:
                    decode_modrm_reg(ref u, ref operand, reg_class.REGCLASS_MMX, size);
                    break;
                case ud_operand_code.OP_U:
                    if (BitOps.MODRM_MOD(modrm(ref u)) != 3)
                    {
                        u.error = 1;
                        u.errorMessage = "expected modrm.mod == 3\n";
                    }
                    decode_modrm_rm(ref u, ref operand, reg_class.REGCLASS_XMM, size);
                    break;
                case ud_operand_code.OP_W:
                    decode_modrm_rm(ref u, ref operand, reg_class.REGCLASS_XMM, size);
                    break;
                case ud_operand_code.OP_V:
                    decode_modrm_reg(ref u, ref operand, reg_class.REGCLASS_XMM, size);
                    break;
                case ud_operand_code.OP_H:
                    decode_vex_vvvv(ref u, ref operand, size);
                    break;
                case ud_operand_code.OP_MU:
                    decode_modrm_rm(ref u, ref operand, reg_class.REGCLASS_XMM,
                                    BitOps.MODRM_MOD(modrm(ref u)) == 3 ?
                                      size.Mx_reg_size() : size.Mx_mem_size());
                    break;
                case ud_operand_code.OP_S:
                    decode_modrm_reg(ref u, ref operand, reg_class.REGCLASS_SEG, size);
                    break;
                case ud_operand_code.OP_O:
                    decode_moffset(ref u, size, ref operand);
                    break;
                case ud_operand_code.OP_R0:
                case ud_operand_code.OP_R1:
                case ud_operand_code.OP_R2:
                case ud_operand_code.OP_R3:
                case ud_operand_code.OP_R4:
                case ud_operand_code.OP_R5:
                case ud_operand_code.OP_R6:
                case ud_operand_code.OP_R7:
                    decode_reg(ref u, ref operand, reg_class.REGCLASS_GPR,
                               (byte)((BitOps.REX_B(u._rex) << 3) | (type - ud_operand_code.OP_R0)), size);
                    break;
                case ud_operand_code.OP_AL:
                case ud_operand_code.OP_AX:
                case ud_operand_code.OP_eAX:
                case ud_operand_code.OP_rAX:
                    decode_reg(ref u, ref operand, reg_class.REGCLASS_GPR, 0, size);
                    break;
                case ud_operand_code.OP_CL:
                case ud_operand_code.OP_CX:
                case ud_operand_code.OP_eCX:
                    decode_reg(ref u, ref operand, reg_class.REGCLASS_GPR, 1, size);
                    break;
                case ud_operand_code.OP_DL:
                case ud_operand_code.OP_DX:
                case ud_operand_code.OP_eDX:
                    decode_reg(ref u, ref operand, reg_class.REGCLASS_GPR, 2, size);
                    break;
                case ud_operand_code.OP_ES:
                case ud_operand_code.OP_CS:
                case ud_operand_code.OP_DS:
                case ud_operand_code.OP_SS:
                case ud_operand_code.OP_FS:
                case ud_operand_code.OP_GS:
                    /* in 64bits mode, only fs and gs are allowed */
                    if (u.dis_mode == 64)
                    {
                        if (type != ud_operand_code.OP_FS && type != ud_operand_code.OP_GS)
                        {
                            u.error = 1;
                            u.errorMessage = "invalid segment register in 64bits\n";
                        }
                    }
                    operand.type = ud_type.UD_OP_REG;
                    operand.@base = (type - ud_operand_code.OP_ES) + ud_type.UD_R_ES;
                    operand.size = 16;
                    break;
                case ud_operand_code.OP_J:
                    decode_imm(ref u, size, ref operand);
                    operand.type = ud_type.UD_OP_JIMM;
                    break;
                case ud_operand_code.OP_R:
                    if (BitOps.MODRM_MOD(modrm(ref u)) != 3)
                    {
                        u.error = 1;
                        u.errorMessage = "expected modrm.mod == 3\n";
                    }
                    decode_modrm_rm(ref u, ref operand, reg_class.REGCLASS_GPR, size);
                    break;
                case ud_operand_code.OP_C:
                    decode_modrm_reg(ref u, ref operand, reg_class.REGCLASS_CR, size);
                    break;
                case ud_operand_code.OP_D:
                    decode_modrm_reg(ref u, ref operand, reg_class.REGCLASS_DB, size);
                    break;
                case ud_operand_code.OP_I3:
                    operand.type = ud_type.UD_OP_CONST;
                    operand.lval.@sbyte = 3;
                    break;
                case ud_operand_code.OP_ST0:
                case ud_operand_code.OP_ST1:
                case ud_operand_code.OP_ST2:
                case ud_operand_code.OP_ST3:
                case ud_operand_code.OP_ST4:
                case ud_operand_code.OP_ST5:
                case ud_operand_code.OP_ST6:
                case ud_operand_code.OP_ST7:
                    operand.type = ud_type.UD_OP_REG;
                    operand.@base = (type - ud_operand_code.OP_ST0) + ud_type.UD_R_ST0;
                    operand.size = 80;
                    break;
                case ud_operand_code.OP_L:
                    decode_vex_immreg(ref u, ref operand, size);
                    break;
                default:
                    operand.type = ud_type.UD_NONE;
                    break;
            }
            return operand.type;
        }
Exemplo n.º 11
0
 ud_operand_size resolve_operand_size(ref ud u, ud_operand_size oSize)
 {
     switch (oSize)
     {
         case ud_operand_size.SZ_V:
             return (ud_operand_size)u.opr_mode;
         case ud_operand_size.SZ_Z:
             return (ud_operand_size)((u.opr_mode == 16) ? 16 : 32);
         case ud_operand_size.SZ_Y:
             return (ud_operand_size)((u.opr_mode == 16) ? 32 : u.opr_mode);
         case ud_operand_size.SZ_RDQ:
             return (ud_operand_size)((u.dis_mode == 64) ? 64 : 32);
         case ud_operand_size.SZ_X:
             Debug.Assert(u.vex_op != 0);
             return (BitOps.P_VEXL(u.itab_entry.Prefix) > 0 && vex_l(ref u) > 0) ? ud_operand_size.SZ_QQ : ud_operand_size.SZ_DQ;
         default:
             return oSize;
     }
 }
Exemplo n.º 12
0
 /* -----------------------------------------------------------------------------
  * decode_gpr() - Returns decoded General Purpose Register 
  * -----------------------------------------------------------------------------
  */
 ud_type decode_gpr(ref ud u, ud_operand_size s, byte rm)
 {
     switch ((int)s)
     {
         case 64:
             return ud_type.UD_R_RAX + rm;
         case 32:
             return ud_type.UD_R_EAX + rm;
         case 16:
             return ud_type.UD_R_AX + rm;
         case 8:
             if (u.dis_mode == 64 && u.pfx_rex != 0)
             {
                 if (rm >= 4)
                     return ud_type.UD_R_SPL + (rm - 4);
                 return ud_type.UD_R_AL + rm;
             }
             else return ud_type.UD_R_AL + rm;
         case 0:
             /* invalid size in case of a decode error */
             Debug.Assert(u.error == 0, "invalid operand size");
             return ud_type.UD_NONE;
         default:
             Debug.Assert(false, "invalid operand size");
             return ud_type.UD_NONE;
     }
 }
Exemplo n.º 13
0
        decode_modrm_rm(ref ud u,
                        ref ud_operand op,
                        reg_class type,       /* register type */
                        ud_operand_size size) /* operand size */
        {
            int  offset = 0;
            byte mod, rm;

            /* get mod, r/m and reg fields */
            mod = BitOps.MODRM_MOD(modrm(ref u));
            rm  = (byte)((BitOps.REX_B(u._rex) << 3) | BitOps.MODRM_RM(modrm(ref u)));

            /*
             * If mod is 11b, then the modrm.rm specifies a register.
             *
             */
            if (mod == 3)
            {
                decode_reg(ref u, ref op, type, rm, size);
                return;
            }

            /*
             * !11b => Memory Address
             */
            op.type = ud_type.UD_OP_MEM;
            op.size = (byte)resolve_operand_size(ref u, size);

            if (u.adr_mode == 64)
            {
                op.@base = ud_type.UD_R_RAX + rm;
                if (mod == 1)
                {
                    offset = 8;
                }
                else if (mod == 2)
                {
                    offset = 32;
                }
                else if (mod == 0 && (rm & 7) == 5)
                {
                    op.@base = ud_type.UD_R_RIP;
                    offset   = 32;
                }
                else
                {
                    offset = 0;
                }

                /*
                 * Scale-Index-Base (SIB)
                 */
                if ((rm & 7) == 4)
                {
                    inp_next(ref u);

                    op.@base = ud_type.UD_R_RAX + (BitOps.SIB_B(inp_curr(ref u)) | (BitOps.REX_B(u._rex) << 3));
                    op.index = ud_type.UD_R_RAX + (BitOps.SIB_I(inp_curr(ref u)) | (BitOps.REX_X(u._rex) << 3));

                    /* special conditions for base reference */
                    if (op.index == ud_type.UD_R_RSP)
                    {
                        op.index = ud_type.UD_NONE;
                        op.scale = (byte)ud_type.UD_NONE;
                    }
                    else
                    {
                        op.scale = (byte)((1 << BitOps.SIB_S(inp_curr(ref u))) & ~1);
                    }

                    if (op.@base == ud_type.UD_R_RBP || op.@base == ud_type.UD_R_R13)
                    {
                        if (mod == 0)
                        {
                            op.@base = ud_type.UD_NONE;
                        }
                        if (mod == 1)
                        {
                            offset = 8;
                        }
                        else
                        {
                            offset = 32;
                        }
                    }
                }
                else
                {
                    op.scale = 0;
                    op.index = ud_type.UD_NONE;
                }
            }
            else if (u.adr_mode == 32)
            {
                op.@base = ud_type.UD_R_EAX + rm;
                if (mod == 1)
                {
                    offset = 8;
                }
                else if (mod == 2)
                {
                    offset = 32;
                }
                else if (mod == 0 && rm == 5)
                {
                    op.@base = ud_type.UD_NONE;
                    offset   = 32;
                }
                else
                {
                    offset = 0;
                }

                /* Scale-Index-Base (SIB) */
                if ((rm & 7) == 4)
                {
                    inp_next(ref u);

                    op.scale = (byte)((1 << BitOps.SIB_S(inp_curr(ref u))) & ~1);
                    op.index = ud_type.UD_R_EAX + (BitOps.SIB_I(inp_curr(ref u)) | (BitOps.REX_X(u.pfx_rex) << 3));
                    op.@base = ud_type.UD_R_EAX + (BitOps.SIB_B(inp_curr(ref u)) | (BitOps.REX_B(u.pfx_rex) << 3));

                    if (op.index == ud_type.UD_R_ESP)
                    {
                        op.index = ud_type.UD_NONE;
                        op.scale = (byte)ud_type.UD_NONE;
                    }

                    /* special condition for base reference */
                    if (op.@base == ud_type.UD_R_EBP)
                    {
                        if (mod == 0)
                        {
                            op.@base = ud_type.UD_NONE;
                        }
                        if (mod == 1)
                        {
                            offset = 8;
                        }
                        else
                        {
                            offset = 32;
                        }
                    }
                }
                else
                {
                    op.scale = 0;
                    op.index = ud_type.UD_NONE;
                }
            }
            else
            {
                ud_type[] bases = { ud_type.UD_R_BX, ud_type.UD_R_BX, ud_type.UD_R_BP, ud_type.UD_R_BP,
                                    ud_type.UD_R_SI, ud_type.UD_R_DI, ud_type.UD_R_BP, ud_type.UD_R_BX };
                ud_type[] indices = { ud_type.UD_R_SI, ud_type.UD_R_DI, ud_type.UD_R_SI, ud_type.UD_R_DI,
                                      ud_type.UD_NONE, ud_type.UD_NONE, ud_type.UD_NONE, ud_type.UD_NONE };
                op.@base = bases[rm & 7];
                op.index = indices[rm & 7];
                op.scale = 0;
                if (mod == 0 && rm == 6)
                {
                    offset   = 16;
                    op.@base = ud_type.UD_NONE;
                }
                else if (mod == 1)
                {
                    offset = 8;
                }
                else if (mod == 2)
                {
                    offset = 16;
                }
            }

            if (offset > 0)
            {
                decode_mem_disp(ref u, offset, ref op);
            }
            else
            {
                op.offset = 0;
            }
        }
Exemplo n.º 14
0
 decode_reg(ref ud u,
            ref ud_operand opr,
            reg_class type,
            byte num,
            ud_operand_size size)
 {
     int reg;
     size = resolve_operand_size(ref u, size);
     switch (type)
     {
         case reg_class.REGCLASS_GPR: reg = (int)decode_gpr(ref u, size, (byte)num); break;
         case reg_class.REGCLASS_MMX: reg = (int)ud_type.UD_R_MM0 + (num & 7); break;
         case reg_class.REGCLASS_XMM: reg = num + (int)(size == ud_operand_size.SZ_QQ ? ud_type.UD_R_YMM0 : ud_type.UD_R_XMM0); break;
         case reg_class.REGCLASS_CR: reg = (int)ud_type.UD_R_CR0 + num; break;
         case reg_class.REGCLASS_DB: reg = (int)ud_type.UD_R_DR0 + num; break;
         case reg_class.REGCLASS_SEG:
             {
                 /*
                  * Only 6 segment registers, anything else is an error.
                  */
                 if ((num & 7) > 5)
                 {
                     u.error = 1;
                     u.errorMessage = "invalid segment register value\n";
                     return;
                 }
                 else
                 {
                     reg = (int)ud_type.UD_R_ES + (num & 7);
                 }
                 break;
             }
         default:
             Debug.Assert(false, "invalid register type");
             return;
     }
     opr.type = ud_type.UD_OP_REG;
     opr.@base = (ud_type)reg;
     opr.size = (byte)size;
 }
Exemplo n.º 15
0
        decode_imm(ref ud u, ud_operand_size size, ref ud_operand op)
        {
            op.size = (byte)resolve_operand_size(ref u, size);
            op.type = ud_type.UD_OP_IMM;

            switch (op.size)
            {
                case 8: op.lval.@sbyte = (sbyte)inp_uint8(ref u); break;
                case 16: op.lval.uword = inp_uint16(ref u); break;
                case 32: op.lval.udword = inp_uint32(ref u); break;
                case 64: op.lval.uqword = inp_uint64(ref u); break;
                default: return;
            }
        }
Exemplo n.º 16
0
 /*
  * decode_modrm_reg
  *
  *    Decodes reg field of mod/rm byte
  * 
  */
 void decode_modrm_reg(ref ud u,
                  ref ud_operand operand,
                  reg_class type,
                  ud_operand_size size)
 {
     byte reg = (byte)((BitOps.REX_R(u._rex) << 3) | BitOps.MODRM_REG(modrm(ref u)));
     decode_reg(ref u, ref operand, type, reg, size);
 }
Exemplo n.º 17
0
        decode_modrm_rm(ref ud u,
                        ref ud_operand op,
                        reg_class type,    /* register type */
                        ud_operand_size size)    /* operand size */
        {
            int offset = 0;
            byte mod, rm;

            /* get mod, r/m and reg fields */
            mod = BitOps.MODRM_MOD(modrm(ref u));
            rm = (byte)((BitOps.REX_B(u._rex) << 3) | BitOps.MODRM_RM(modrm(ref u)));

            /* 
             * If mod is 11b, then the modrm.rm specifies a register.
             *
             */
            if (mod == 3)
            {
                decode_reg(ref u, ref op, type, rm, size);
                return;
            }

            /* 
             * !11b => Memory Address
             */
            op.type = ud_type.UD_OP_MEM;
            op.size = (byte)resolve_operand_size(ref u, size);

            if (u.adr_mode == 64)
            {
                op.@base = ud_type.UD_R_RAX + rm;
                if (mod == 1)
                {
                    offset = 8;
                }
                else if (mod == 2)
                {
                    offset = 32;
                }
                else if (mod == 0 && (rm & 7) == 5)
                {
                    op.@base = ud_type.UD_R_RIP;
                    offset = 32;
                }
                else
                {
                    offset = 0;
                }
                /* 
                 * Scale-Index-Base (SIB) 
                 */
                if ((rm & 7) == 4)
                {
                    inp_next(ref u);

                    op.@base = ud_type.UD_R_RAX + (BitOps.SIB_B(inp_curr(ref u)) | (BitOps.REX_B(u._rex) << 3));
                    op.index = ud_type.UD_R_RAX + (BitOps.SIB_I(inp_curr(ref u)) | (BitOps.REX_X(u._rex) << 3));

                    /* special conditions for base reference */
                    if (op.index == ud_type.UD_R_RSP)
                    {
                        op.index = ud_type.UD_NONE;
                        op.scale = (byte)ud_type.UD_NONE;
                    }
                    else
                    {
                        op.scale = (byte)((1 << BitOps.SIB_S(inp_curr(ref u))) & ~1);
                    }

                    if (op.@base == ud_type.UD_R_RBP || op.@base == ud_type.UD_R_R13)
                    {
                        if (mod == 0)
                        {
                            op.@base = ud_type.UD_NONE;
                        }
                        if (mod == 1)
                        {
                            offset = 8;
                        }
                        else
                        {
                            offset = 32;
                        }
                    }
                }
                else
                {
                    op.scale = 0;
                    op.index = ud_type.UD_NONE;
                }
            }
            else if (u.adr_mode == 32)
            {
                op.@base = ud_type.UD_R_EAX + rm;
                if (mod == 1)
                {
                    offset = 8;
                }
                else if (mod == 2)
                {
                    offset = 32;
                }
                else if (mod == 0 && rm == 5)
                {
                    op.@base = ud_type.UD_NONE;
                    offset = 32;
                }
                else
                {
                    offset = 0;
                }

                /* Scale-Index-Base (SIB) */
                if ((rm & 7) == 4)
                {
                    inp_next(ref u);

                    op.scale = (byte)((1 << BitOps.SIB_S(inp_curr(ref u))) & ~1);
                    op.index = ud_type.UD_R_EAX + (BitOps.SIB_I(inp_curr(ref u)) | (BitOps.REX_X(u.pfx_rex) << 3));
                    op.@base = ud_type.UD_R_EAX + (BitOps.SIB_B(inp_curr(ref u)) | (BitOps.REX_B(u.pfx_rex) << 3));

                    if (op.index == ud_type.UD_R_ESP)
                    {
                        op.index = ud_type.UD_NONE;
                        op.scale = (byte)ud_type.UD_NONE;
                    }

                    /* special condition for base reference */
                    if (op.@base == ud_type.UD_R_EBP)
                    {
                        if (mod == 0)
                        {
                            op.@base = ud_type.UD_NONE;
                        }
                        if (mod == 1)
                        {
                            offset = 8;
                        }
                        else
                        {
                            offset = 32;
                        }
                    }
                }
                else
                {
                    op.scale = 0;
                    op.index = ud_type.UD_NONE;
                }
            }
            else
            {
                ud_type[] bases = { ud_type.UD_R_BX, ud_type.UD_R_BX, ud_type.UD_R_BP, ud_type.UD_R_BP,
                                             ud_type.UD_R_SI, ud_type.UD_R_DI, ud_type.UD_R_BP, ud_type.UD_R_BX };
                ud_type[] indices = { ud_type.UD_R_SI, ud_type.UD_R_DI, ud_type.UD_R_SI, ud_type.UD_R_DI,
                                             ud_type.UD_NONE, ud_type.UD_NONE, ud_type.UD_NONE, ud_type.UD_NONE };
                op.@base = bases[rm & 7];
                op.index = indices[rm & 7];
                op.scale = 0;
                if (mod == 0 && rm == 6)
                {
                    offset = 16;
                    op.@base = ud_type.UD_NONE;
                }
                else if (mod == 1)
                {
                    offset = 8;
                }
                else if (mod == 2)
                {
                    offset = 16;
                }
            }

            if (offset > 0)
            {
                decode_mem_disp(ref u, offset, ref op);
            }
            else
            {
                op.offset = 0;
            }
        }
Exemplo n.º 18
0
 public static ud_operand_size Mx_mem_size(this ud_operand_size size)
 {
     return((ud_operand_size)((int)size >> 8 & 0xff));
 }
Exemplo n.º 19
0
        decode_operand(ref ud u,
                       ref ud_operand operand,
                       ud_operand_code type,
                       ud_operand_size size)
        {
            operand.type     = ud_type.UD_NONE;
            operand._oprcode = type;

            switch (type)
            {
            case ud_operand_code.OP_A:
                decode_a(ref u, ref operand);
                break;

            case ud_operand_code.OP_MR:
                decode_modrm_rm(ref u, ref operand, (byte)reg_class.REGCLASS_GPR,
                                BitOps.MODRM_MOD(modrm(ref u)) == 3 ?
                                size.Mx_reg_size() : size.Mx_mem_size());
                break;

            case ud_operand_code.OP_F:
                u.br_far = 1;
                if (BitOps.MODRM_MOD(modrm(ref u)) == 3)
                {
                    u.error        = 1;
                    u.errorMessage = "expected modrm.mod != 3\n";
                }
                decode_modrm_rm(ref u, ref operand, reg_class.REGCLASS_GPR, size);
                break;

            case ud_operand_code.OP_M:
                if (BitOps.MODRM_MOD(modrm(ref u)) == 3)
                {
                    u.error        = 1;
                    u.errorMessage = "expected modrm.mod != 3\n";
                }
                decode_modrm_rm(ref u, ref operand, reg_class.REGCLASS_GPR, size);
                break;

            case ud_operand_code.OP_E:
                decode_modrm_rm(ref u, ref operand, reg_class.REGCLASS_GPR, size);
                break;

            case ud_operand_code.OP_G:
                decode_modrm_reg(ref u, ref operand, reg_class.REGCLASS_GPR, size);
                break;

            case ud_operand_code.OP_sI:
            case ud_operand_code.OP_I:
                decode_imm(ref u, size, ref operand);
                break;

            case ud_operand_code.OP_I1:
                operand.type        = ud_type.UD_OP_CONST;
                operand.lval.udword = 1;
                break;

            case ud_operand_code.OP_N:
                if (BitOps.MODRM_MOD(modrm(ref u)) != 3)
                {
                    u.error        = 1;
                    u.errorMessage = "expected modrm.mod == 3\n";
                }
                decode_modrm_rm(ref u, ref operand, reg_class.REGCLASS_MMX, size);
                break;

            case ud_operand_code.OP_Q:
                decode_modrm_rm(ref u, ref operand, reg_class.REGCLASS_MMX, size);
                break;

            case ud_operand_code.OP_P:
                decode_modrm_reg(ref u, ref operand, reg_class.REGCLASS_MMX, size);
                break;

            case ud_operand_code.OP_U:
                if (BitOps.MODRM_MOD(modrm(ref u)) != 3)
                {
                    u.error        = 1;
                    u.errorMessage = "expected modrm.mod == 3\n";
                }
                decode_modrm_rm(ref u, ref operand, reg_class.REGCLASS_XMM, size);
                break;

            case ud_operand_code.OP_W:
                decode_modrm_rm(ref u, ref operand, reg_class.REGCLASS_XMM, size);
                break;

            case ud_operand_code.OP_V:
                decode_modrm_reg(ref u, ref operand, reg_class.REGCLASS_XMM, size);
                break;

            case ud_operand_code.OP_H:
                decode_vex_vvvv(ref u, ref operand, size);
                break;

            case ud_operand_code.OP_MU:
                decode_modrm_rm(ref u, ref operand, reg_class.REGCLASS_XMM,
                                BitOps.MODRM_MOD(modrm(ref u)) == 3 ?
                                size.Mx_reg_size() : size.Mx_mem_size());
                break;

            case ud_operand_code.OP_S:
                decode_modrm_reg(ref u, ref operand, reg_class.REGCLASS_SEG, size);
                break;

            case ud_operand_code.OP_O:
                decode_moffset(ref u, size, ref operand);
                break;

            case ud_operand_code.OP_R0:
            case ud_operand_code.OP_R1:
            case ud_operand_code.OP_R2:
            case ud_operand_code.OP_R3:
            case ud_operand_code.OP_R4:
            case ud_operand_code.OP_R5:
            case ud_operand_code.OP_R6:
            case ud_operand_code.OP_R7:
                decode_reg(ref u, ref operand, reg_class.REGCLASS_GPR,
                           (byte)((BitOps.REX_B(u._rex) << 3) | (type - ud_operand_code.OP_R0)), size);
                break;

            case ud_operand_code.OP_AL:
            case ud_operand_code.OP_AX:
            case ud_operand_code.OP_eAX:
            case ud_operand_code.OP_rAX:
                decode_reg(ref u, ref operand, reg_class.REGCLASS_GPR, 0, size);
                break;

            case ud_operand_code.OP_CL:
            case ud_operand_code.OP_CX:
            case ud_operand_code.OP_eCX:
                decode_reg(ref u, ref operand, reg_class.REGCLASS_GPR, 1, size);
                break;

            case ud_operand_code.OP_DL:
            case ud_operand_code.OP_DX:
            case ud_operand_code.OP_eDX:
                decode_reg(ref u, ref operand, reg_class.REGCLASS_GPR, 2, size);
                break;

            case ud_operand_code.OP_ES:
            case ud_operand_code.OP_CS:
            case ud_operand_code.OP_DS:
            case ud_operand_code.OP_SS:
            case ud_operand_code.OP_FS:
            case ud_operand_code.OP_GS:
                /* in 64bits mode, only fs and gs are allowed */
                if (u.dis_mode == 64)
                {
                    if (type != ud_operand_code.OP_FS && type != ud_operand_code.OP_GS)
                    {
                        u.error        = 1;
                        u.errorMessage = "invalid segment register in 64bits\n";
                    }
                }
                operand.type  = ud_type.UD_OP_REG;
                operand.@base = (type - ud_operand_code.OP_ES) + ud_type.UD_R_ES;
                operand.size  = 16;
                break;

            case ud_operand_code.OP_J:
                decode_imm(ref u, size, ref operand);
                operand.type = ud_type.UD_OP_JIMM;
                break;

            case ud_operand_code.OP_R:
                if (BitOps.MODRM_MOD(modrm(ref u)) != 3)
                {
                    u.error        = 1;
                    u.errorMessage = "expected modrm.mod == 3\n";
                }
                decode_modrm_rm(ref u, ref operand, reg_class.REGCLASS_GPR, size);
                break;

            case ud_operand_code.OP_C:
                decode_modrm_reg(ref u, ref operand, reg_class.REGCLASS_CR, size);
                break;

            case ud_operand_code.OP_D:
                decode_modrm_reg(ref u, ref operand, reg_class.REGCLASS_DB, size);
                break;

            case ud_operand_code.OP_I3:
                operand.type        = ud_type.UD_OP_CONST;
                operand.lval.@sbyte = 3;
                break;

            case ud_operand_code.OP_ST0:
            case ud_operand_code.OP_ST1:
            case ud_operand_code.OP_ST2:
            case ud_operand_code.OP_ST3:
            case ud_operand_code.OP_ST4:
            case ud_operand_code.OP_ST5:
            case ud_operand_code.OP_ST6:
            case ud_operand_code.OP_ST7:
                operand.type  = ud_type.UD_OP_REG;
                operand.@base = (type - ud_operand_code.OP_ST0) + ud_type.UD_R_ST0;
                operand.size  = 80;
                break;

            case ud_operand_code.OP_L:
                decode_vex_immreg(ref u, ref operand, size);
                break;

            default:
                operand.type = ud_type.UD_NONE;
                break;
            }
            return(operand.type);
        }
Exemplo n.º 20
0
 decode_vex_immreg(ref ud u, ref ud_operand opr, ud_operand_size size)
 {
     byte imm = (byte)inp_next(ref u);
     byte mask = (byte)(u.dis_mode == 64 ? 0xf : 0x7);
     if (u.error != 0) return u.error;
     Debug.Assert(u.vex_op != 0);
     decode_reg(ref u, ref opr, reg_class.REGCLASS_XMM, (byte)(mask & (imm >> 4)), size);
     return 0;
 }
Exemplo n.º 21
0
 decode_vex_vvvv(ref ud u, ref ud_operand opr, ud_operand_size size)
 {
     byte vvvv;
     Debug.Assert(u.vex_op != 0);
     vvvv = (byte)(((u.vex_op == 0xc4 ? u.vex_b2 : u.vex_b1) >> 3) & 0xf);
     decode_reg(ref u, ref opr, reg_class.REGCLASS_XMM, (byte)(0xf & ~vvvv), size);
 }
Exemplo n.º 22
0
 decode_moffset(ref ud u, ud_operand_size size, ref ud_operand opr)
 {
     opr.type = ud_type.UD_OP_MEM;
     opr.@base = ud_type.UD_NONE;
     opr.index = ud_type.UD_NONE;
     opr.scale = 0;
     opr.size = (byte)resolve_operand_size(ref u, size);
     decode_mem_disp(ref u, u.adr_mode, ref opr);
 }
 public ud_itab_entry_operand(ud_operand_code type, ud_operand_size size)
 {
     this.type = type;
     this.size = size;
 }
Exemplo n.º 24
0
 public static ud_operand_size Mx_reg_size(this ud_operand_size size)
 {
     return((ud_operand_size)((int)size & 0xff));
 }