Ejemplo n.º 1
0
        public ldasm_data ldasm(byte[] code, int offset, bool is64)
        {
            ldasm_data ldasm = new ldasm_data();
            int        p = offset;
            byte       s = 0, op = 0, f = 0;
            byte       rexw = 0, pr_66 = 0, pr_67 = 0;


            if (code == null)
            {
                return(ldasm);
            }

            /* phase 1: parse prefixies */
            while ((cflags(code[p]) & OP_PREFIX) == OP_PREFIX)
            {
                if (code[p] == 0x66)
                {
                    pr_66 = 1;
                }

                if (code[p] == 0x67)
                {
                    pr_67 = 1;
                }

                p++; s++;
                ldasm.flags |= F_PREFIX;
                if (s == 15)
                {
                    ldasm.flags |= F_INVALID;
                    ldasm.size   = s;
                    return(ldasm);
                }
            }

            /* parse REX prefix */
            if (is64 && code[p] >> 4 == 4)
            {
                ldasm.rex    = code[p];
                rexw         = (byte)((ldasm.rex >> 3) & 1);
                ldasm.flags |= F_REX;
                p++; s++;
            }

            /* can be only one REX prefix */
            if (is64 && code[p] >> 4 == 4)
            {
                ldasm.flags |= F_INVALID;
                s++;
                ldasm.size = s;
                return(ldasm);
            }

            /* phase 2: parse opcode */
            ldasm.opcd_offset = p;
            ldasm.opcd_size   = 1;
            op = code[p++]; s++;

            /* is 2 byte opcede? */
            if (op == 0x0F)
            {
                op = code[p++]; s++;
                ldasm.opcd_size++;
                f = cflags_ex(op);
                if ((f & OP_INVALID) == OP_INVALID)
                {
                    ldasm.flags |= F_INVALID;
                    ldasm.size   = s;
                    return(ldasm);
                }
                /* for SSE instructions */
                if ((f & OP_EXTENDED) == OP_EXTENDED)
                {
                    op = code[p++]; s++;
                    ldasm.opcd_size++;
                }
            }
            else
            {
                f = cflags(op);
                /* pr_66 = pr_67 for opcodes A0-A3 */
                if (op >= 0xA0 && op <= 0xA3)
                {
                    pr_66 = pr_67;
                }
            }

            /* phase 3: parse ModR/M, SIB and DISP */
            if ((f & OP_MODRM) == OP_MODRM)
            {
                byte mod = (byte)(code[p] >> 6);
                byte ro  = (byte)((code[p] & 0x38) >> 3);
                byte rm  = (byte)(code[p] & 7);

                ldasm.modrm  = code[p++]; s++;
                ldasm.flags |= F_MODRM;

                /* in F6,F7 opcodes immediate data present if R/O == 0 */
                if (op == 0xF6 && (ro == 0 || ro == 1))
                {
                    f |= OP_DATA_I8;
                }
                if (op == 0xF7 && (ro == 0 || ro == 1))
                {
                    f |= OP_DATA_I16_I32_I64;
                }

                /* is SIB byte exist? */
                if (mod != 3 && rm == 4 && !((!is64) && (pr_67 == 1)))
                {
                    ldasm.sib    = code[p++]; s++;
                    ldasm.flags |= F_SIB;

                    /* if base == 5 and mod == 0 */
                    if ((ldasm.sib & 7) == 5 && mod == 0)
                    {
                        ldasm.disp_size = 4;
                    }
                }

                switch (mod)
                {
                case 0:
                    if (is64)
                    {
                        if (rm == 5)
                        {
                            ldasm.disp_size = 4;
                            if (is64)
                            {
                                ldasm.flags |= F_RELATIVE;
                            }
                        }
                    }
                    else if (pr_67 == 1)
                    {
                        if (rm == 6)
                        {
                            ldasm.disp_size = 2;
                        }
                    }
                    else
                    {
                        if (rm == 5)
                        {
                            ldasm.disp_size = 4;
                        }
                    }
                    break;

                case 1:
                    ldasm.disp_size = 1;
                    break;

                case 2:
                    if (is64)
                    {
                        ldasm.disp_size = 4;
                    }
                    else if (pr_67 == 1)
                    {
                        ldasm.disp_size = 2;
                    }
                    else
                    {
                        ldasm.disp_size = 4;
                    }
                    break;
                }

                if (ldasm.disp_size > 0)
                {
                    ldasm.disp_offset = p;
                    p           += ldasm.disp_size;
                    s           += ldasm.disp_size;
                    ldasm.flags |= F_DISP;
                }
            }
            /* phase 4: parse immediate data */
            if (rexw > 0 && (f & OP_DATA_I16_I32_I64) == OP_DATA_I16_I32_I64)
            {
                ldasm.imm_size = 8;
            }
            else if ((f & OP_DATA_I16_I32) == OP_DATA_I16_I32 || (f & OP_DATA_I16_I32_I64) == OP_DATA_I16_I32_I64)
            {
                ldasm.imm_size = (byte)(4 - (pr_66 << 1));
            }

            /* if exist, add OP_DATA_I16 and OP_DATA_I8 size */
            ldasm.imm_size += (byte)(f & 3);

            if (ldasm.imm_size > 0)
            {
                s += ldasm.imm_size;
                ldasm.imm_offset = p;
                ldasm.flags     |= F_IMM;
                if ((f & OP_RELATIVE) == OP_RELATIVE)
                {
                    ldasm.flags |= F_RELATIVE;
                }
            }

            /* instruction is too long */
            if (s > 15)
            {
                ldasm.flags |= F_INVALID;
            }
            ldasm.size = s;
            return(ldasm);
        }
Ejemplo n.º 2
0
        public ldasm_data ldasm(byte[] code, int offset, bool is64)
        {
            ldasm_data ldasm = new ldasm_data();
            int p = offset;
            byte s = 0, op = 0, f = 0;
            byte rexw = 0, pr_66 = 0, pr_67 = 0;


            if (code == null)
                return ldasm;

            /* phase 1: parse prefixies */
            while ((cflags(code[p]) & OP_PREFIX) == OP_PREFIX)
            {
                if (code[p] == 0x66)
                {
                    pr_66 = 1;
                }

                if (code[p] == 0x67)
                {
                    pr_67 = 1;
                }

                p++; s++;
                ldasm.flags |= F_PREFIX;
                if (s == 15)
                {
                    ldasm.flags |= F_INVALID;
                    ldasm.size = s;
                    return ldasm;
                }
            }

            /* parse REX prefix */
            if (is64 && code[p] >> 4 == 4)
            {
                ldasm.rex = code[p];
                rexw = (byte)((ldasm.rex >> 3) & 1);
                ldasm.flags |= F_REX;
                p++; s++;
            }

            /* can be only one REX prefix */
            if (is64 && code[p] >> 4 == 4)
            {
                ldasm.flags |= F_INVALID;
                s++;
                ldasm.size = s;
                return ldasm;
            }

            /* phase 2: parse opcode */
            ldasm.opcd_offset = p;
            ldasm.opcd_size = 1;
            op = code[p++]; s++;

            /* is 2 byte opcede? */
            if (op == 0x0F)
            {
                op = code[p++]; s++;
                ldasm.opcd_size++;
                f = cflags_ex(op);
                if ((f & OP_INVALID) == OP_INVALID)
                {
                    ldasm.flags |= F_INVALID;
                    ldasm.size = s;
                    return ldasm;
                }
                /* for SSE instructions */
                if ((f & OP_EXTENDED) == OP_EXTENDED)
                {
                    op = code[p++]; s++;
                    ldasm.opcd_size++;
                }
            }
            else
            {
                f = cflags(op);
                /* pr_66 = pr_67 for opcodes A0-A3 */
                if (op >= 0xA0 && op <= 0xA3)
                    pr_66 = pr_67;
            }

            /* phase 3: parse ModR/M, SIB and DISP */
            if ((f & OP_MODRM) == OP_MODRM)
            {
                byte mod = (byte)(code[p] >> 6);
                byte ro = (byte)((code[p] & 0x38) >> 3);
                byte rm = (byte)(code[p] & 7);

                ldasm.modrm = code[p++]; s++;
                ldasm.flags |= F_MODRM;

                /* in F6,F7 opcodes immediate data present if R/O == 0 */
                if (op == 0xF6 && (ro == 0 || ro == 1))
                    f |= OP_DATA_I8;
                if (op == 0xF7 && (ro == 0 || ro == 1))
                    f |= OP_DATA_I16_I32_I64;

                /* is SIB byte exist? */
                if (mod != 3 && rm == 4 && !((!is64) && (pr_67 == 1)))
                {
                    ldasm.sib = code[p++]; s++;
                    ldasm.flags |= F_SIB;

                    /* if base == 5 and mod == 0 */
                    if ((ldasm.sib & 7) == 5 && mod == 0)
                    {
                        ldasm.disp_size = 4;
                    }
                }

                switch (mod)
                {
                    case 0:
                        if (is64)
                        {
                            if (rm == 5)
                            {
                                ldasm.disp_size = 4;
                                if (is64)
                                    ldasm.flags |= F_RELATIVE;
                            }
                        }
                        else if (pr_67 == 1)
                        {
                            if (rm == 6)
                                ldasm.disp_size = 2;
                        }
                        else
                        {
                            if (rm == 5)
                                ldasm.disp_size = 4;
                        }
                        break;
                    case 1:
                        ldasm.disp_size = 1;
                        break;
                    case 2:
                        if (is64)
                            ldasm.disp_size = 4;
                        else if (pr_67 == 1)
                            ldasm.disp_size = 2;
                        else
                            ldasm.disp_size = 4;
                        break;
                }

                if (ldasm.disp_size > 0)
                {
                    ldasm.disp_offset = p;
                    p += ldasm.disp_size;
                    s += ldasm.disp_size;
                    ldasm.flags |= F_DISP;
                }
            }
            /* phase 4: parse immediate data */
            if (rexw > 0 && (f & OP_DATA_I16_I32_I64) == OP_DATA_I16_I32_I64)
                ldasm.imm_size = 8;
            else if ((f & OP_DATA_I16_I32) == OP_DATA_I16_I32 || (f & OP_DATA_I16_I32_I64) == OP_DATA_I16_I32_I64)
                ldasm.imm_size = (byte)(4 - (pr_66 << 1));

            /* if exist, add OP_DATA_I16 and OP_DATA_I8 size */
            ldasm.imm_size += (byte)(f & 3);

            if (ldasm.imm_size > 0)
            {
                s += ldasm.imm_size;
                ldasm.imm_offset = p;
                ldasm.flags |= F_IMM;
                if ((f & OP_RELATIVE) == OP_RELATIVE)
                    ldasm.flags |= F_RELATIVE;
            }

            /* instruction is too long */
            if (s > 15)
                ldasm.flags |= F_INVALID;
            ldasm.size = s;
            return ldasm;
        }