public static uint get_instruction(out INSTRUCTION inst, byte[] dat, uint idx, Mode mode) { INST ptr = null; uint index = 0; uint flags = 0; inst = new INSTRUCTION(); get_real_instruction(dat, idx, ref index, ref flags); if (Macros.MASK_EXT(flags) == 0) { inst.opcode = dat[idx + index]; ptr = opcode_tables.inst_table1[inst.opcode]; } else if (Macros.MASK_EXT(flags) == Consts.EXT_CP) { if (dat[idx + index] < 0xc0) { index--; inst.fpuindex = dat[idx + index] - 0xd8; inst.opcode = dat[idx + index + 1]; ptr = opcode_tables.inst_table4[inst.fpuindex][Macros.MASK_MODRM_REG(inst.opcode)]; } else { inst.fpuindex = dat[idx + index - 1] - 0xd8; inst.opcode = dat[idx + index]; ptr = opcode_tables.inst_table4[inst.fpuindex][inst.opcode - 0xb8]; } } else if (Macros.MASK_EXT(flags) == Consts.EXT_T2) { inst.opcode = dat[idx + index]; get_real_instruction2(dat[idx + index], ref flags); ptr = opcode_tables.inst_table2[inst.opcode]; if (Macros.MASK_TYPE_FLAGS((uint)ptr.type) == Consts.TYPE_3) { if (Macros.MASK_PREFIX_OPERAND(flags) == 1) { ptr = opcode_tables.inst_table3_66[inst.opcode]; } else if (Macros.MASK_PREFIX_G1(flags) == 2) { ptr = opcode_tables.inst_table3_f2[inst.opcode]; } else if (Macros.MASK_PREFIX_G1(flags) == 3) { ptr = opcode_tables.inst_table3_f3[inst.opcode]; } } } if (Macros.MASK_EXT(flags) != 0 && (Macros.MASK_EXT(flags) < Consts.EXT_T2)) { inst.opcode = dat[idx + index]; inst.extindex = Macros.MASK_MODRM_REG(dat[idx + index + 1]); switch (Macros.MASK_EXT(flags)) { case Consts.EXT_GC: if (Macros.MASK_PREFIX_OPERAND(flags) == 1) { ptr = opcode_tables.inst_table_ext12_66[inst.extindex]; } else { ptr = opcode_tables.inst_table_ext12[inst.extindex]; } break; case Consts.EXT_GD: if (Macros.MASK_PREFIX_OPERAND(flags) == 1) { ptr = opcode_tables.inst_table_ext13_66[inst.extindex]; } else { ptr = opcode_tables.inst_table_ext13[inst.extindex]; } break; case Consts.EXT_GE: if (Macros.MASK_PREFIX_OPERAND(flags) == 1) { ptr = opcode_tables.inst_table_ext14_66[inst.extindex]; } else { ptr = opcode_tables.inst_table_ext14[inst.extindex]; } break; case Consts.EXT_G7: if (Macros.MASK_MODRM_MOD(dat[idx + index + 1]) == 3) { if (inst.extindex != 1) { return(0); } if (Macros.MASK_MODRM_RM(dat[idx + index + 1]) == 0) { ptr = opcode_tables.inst_monitor; index++; } else if (Macros.MASK_MODRM_RM(dat[idx + index + 1]) == 1) { ptr = opcode_tables.inst_mwait; index++; } else { return(0); } } else { ptr = opcode_tables.inst_table_ext7[inst.extindex]; } break; default: ptr = opcode_tables.inst_table_ext[(Macros.MASK_EXT(flags)) - 1][inst.extindex]; break; } } index++; if (ptr == null) { return(0); } if (ptr.mnemonic == null) { return(0); } if (ptr.modrm) { inst.modrm_offset = index; } inst.type = (InstructionType)Macros.MASK_TYPE_VALUE((uint)ptr.type); inst.eflags_affected = ptr.eflags_affected; inst.eflags_used = ptr.eflags_used; inst.ptr = ptr; if (!get_operand(ptr, ptr.flags1, inst, out inst.op1, dat, index + idx, mode, flags)) { return(0); } if (!get_operand(ptr, ptr.flags2, inst, out inst.op2, dat, index + idx, mode, flags)) { return(0); } if (!get_operand(ptr, ptr.flags3, inst, out inst.op3, dat, index + idx, mode, flags)) { return(0); } inst.iop_read = ptr.iop_read; inst.iop_written = ptr.iop_written; inst.length += index + inst.immbytes + inst.dispbytes; inst.mode = mode; inst.flags = flags; return(inst.length); }
private static bool get_operand(INST inst, uint oflags, INSTRUCTION instruction, out OPERAND op, byte[] data, uint idx, Mode mode, uint iflags) { uint index = 0; bool sib = false; uint scale = 0; uint reg = Consts.REG_NOP; uint basereg = Consts.REG_NOP; uint indexreg = Consts.REG_NOP; uint dispbytes = 0; Mode pmode; op = new OPERAND(); if (oflags == Consts.FLAGS_NONE) { op.type = OperandType.OPERAND_TYPE_NONE; return(true); } op.flags = oflags; op.reg = Consts.REG_NOP; op.basereg = Consts.REG_NOP; op.indexreg = Consts.REG_NOP; op.dispoffset = 0; op.immoffset = 0; if (inst.modrm) { pmode = MODE_CHECK_ADDR(mode, iflags); if (instruction.length == 0) { instruction.modrm = (byte)idx; instruction.length += 1; } reg = Macros.MASK_MODRM_REG(data[idx]); if (Macros.MASK_MODRM_MOD(data[idx]) == 0) { if ((pmode == Mode.MODE_32) && (Macros.MASK_MODRM_RM(data[idx]) == Consts.REG_EBP)) { dispbytes = 4; } if ((pmode == Mode.MODE_16) && (Macros.MASK_MODRM_RM(data[idx]) == Consts.REG_ESI)) { dispbytes = 2; } } else if (Macros.MASK_MODRM_MOD(data[idx]) == 1) { dispbytes = 1; } else if (Macros.MASK_MODRM_MOD(data[idx]) == 2) { dispbytes = (pmode == Mode.MODE_32) ? 4U : 2U; } if (pmode == Mode.MODE_32) { if ((Macros.MASK_MODRM_RM(data[idx]) == Consts.REG_ESP) && (Macros.MASK_MODRM_MOD(data[idx]) != 3)) { sib = true; instruction.sib = data[idx + 1]; if (instruction.length == 1) { instruction.sib = data[idx + 1]; instruction.length += 1; } basereg = Macros.MASK_SIB_BASE(data[idx + 1]); indexreg = Macros.MASK_SIB_INDEX(data[idx + 1]); scale = Macros.MASK_SIB_SCALE(data[idx + 1]) * 2; if (scale == 6) { scale += 2; } if ((basereg == Consts.REG_EBP) && Macros.MASK_MODRM_MOD(data[idx]) == 0) { basereg = Consts.REG_NOP; dispbytes = 4; } if (indexreg == Consts.REG_ESP) { indexreg = Consts.REG_NOP; } } else { if (Macros.MASK_MODRM_MOD(data[idx]) == 0 && (Macros.MASK_MODRM_RM(data[idx]) == Consts.REG_EBP)) { basereg = Consts.REG_NOP; } else { basereg = Macros.MASK_MODRM_RM(data[idx]); } } } else { switch (Macros.MASK_MODRM_RM(data[idx])) { case 0: basereg = Consts.REG_EBX; indexreg = Consts.REG_ESI; break; case 1: basereg = Consts.REG_EBX; indexreg = Consts.REG_EDI; break; case 2: basereg = Consts.REG_EBP; indexreg = Consts.REG_ESI; break; case 3: basereg = Consts.REG_EBP; indexreg = Consts.REG_EDI; break; case 4: basereg = Consts.REG_ESI; indexreg = Consts.REG_NOP; break; case 5: basereg = Consts.REG_EDI; indexreg = Consts.REG_NOP; break; case 6: if (Macros.MASK_MODRM_MOD(data[idx]) == 0) { basereg = Consts.REG_NOP; } else { basereg = Consts.REG_EBP; } indexreg = Consts.REG_NOP; break; case 7: basereg = Consts.REG_EBX; indexreg = Consts.REG_NOP; break; } if (Macros.MASK_MODRM_MOD(data[idx]) == 3) { basereg = Macros.MASK_MODRM_RM(data[idx]); indexreg = Consts.REG_NOP; } } } switch (Macros.MASK_AM(oflags)) { case Consts.AM_REG: op.type = OperandType.OPERAND_TYPE_REGISTER; op.reg = Macros.MASK_REG(oflags); break; case Consts.AM_IND: op.type = OperandType.OPERAND_TYPE_MEMORY; op.basereg = Macros.MASK_REG(oflags); break; case Consts.AM_M: if (Macros.MASK_MODRM_MOD(data[idx]) == 3) { return(false); } goto skip_rest; case Consts.AM_R: if (Macros.MASK_MODRM_MOD(data[idx]) != 3) { return(false); } goto skip_rest; case Consts.AM_Q: case Consts.AM_W: case Consts.AM_E: skip_rest: op.type = OperandType.OPERAND_TYPE_MEMORY; op.dispbytes = dispbytes; instruction.dispbytes = dispbytes; op.basereg = basereg; op.indexreg = indexreg; op.scale = scale; index = (sib) ? 1U : 0U; if (dispbytes != 0) { op.dispoffset = index + 1 + idx; } switch (dispbytes) { case 0: break; case 1: op.displacement = Macros.FETCH8(data, idx + 1 + index); if (op.displacement >= 0x80) { op.displacement |= 0xffffff00; } break; case 2: op.displacement = Macros.FETCH16(data, idx + 1 + index); break; case 4: op.displacement = Macros.FETCH32(data, idx + 1 + index); break; } if ((basereg != Consts.REG_NOP) && (Macros.MASK_MODRM_MOD(data[idx]) == 3)) { op.type = OperandType.OPERAND_TYPE_REGISTER; op.reg = basereg; } break; case Consts.AM_I1: op.type = OperandType.OPERAND_TYPE_IMMEDIATE; op.immbytes = 1; op.immediate = 1; break; case Consts.AM_J: op.type = OperandType.OPERAND_TYPE_IMMEDIATE; oflags |= Consts.F_s; goto am_i; case Consts.AM_I: am_i: op.type = OperandType.OPERAND_TYPE_IMMEDIATE; index = (inst.modrm) ? 1U : 0U; index += (sib) ? 1U : 0U; index += instruction.immbytes; index += instruction.dispbytes; op.immoffset = index + idx; mode = MODE_CHECK_OPERAND(mode, iflags); switch (Macros.MASK_OT(oflags)) { case Consts.OT_b: op.immbytes = 1; op.immediate = Macros.FETCH8(data, idx + index); if ((op.immediate >= 0x80) && (Macros.MASK_FLAGS(oflags) == Consts.F_s)) { op.immediate |= 0xffffff00; } break; case Consts.OT_v: op.immbytes = (mode == Mode.MODE_32) ? 4U : 2U; op.immediate = (mode == Mode.MODE_32) ? Macros.FETCH32(data, idx + index) : Macros.FETCH16(data, idx + index); break; case Consts.OT_w: op.immbytes = 2; op.immediate = Macros.FETCH16(data, idx + index); break; } instruction.immbytes += op.immbytes; break; case Consts.AM_A: op.type = OperandType.OPERAND_TYPE_IMMEDIATE; mode = MODE_CHECK_OPERAND(mode, iflags); op.dispbytes = (mode == Mode.MODE_32) ? 6U : 4U; op.displacement = (mode == Mode.MODE_32) ? Macros.FETCH32(data, idx) : Macros.FETCH16(data, idx); op.section = Macros.FETCH16(data, idx + op.dispbytes - 2); instruction.dispbytes = op.dispbytes; instruction.sectionbytes = 2; break; case Consts.AM_O: op.type = OperandType.OPERAND_TYPE_MEMORY; switch (Macros.MASK_OT(oflags)) { case Consts.OT_b: op.dispbytes = 1; op.displacement = Macros.FETCH8(data, idx); break; case Consts.OT_v: op.dispbytes = (mode == Mode.MODE_32) ? 4U : 2U; op.displacement = (mode == Mode.MODE_32) ? Macros.FETCH32(data, idx) : Macros.FETCH16(data, idx); break; } instruction.dispbytes = op.dispbytes; op.dispoffset = idx; break; case Consts.AM_G: op.type = OperandType.OPERAND_TYPE_REGISTER; op.reg = reg; break; case Consts.AM_C: case Consts.AM_D: case Consts.AM_S: case Consts.AM_T: case Consts.AM_P: case Consts.AM_V: op.type = OperandType.OPERAND_TYPE_REGISTER; op.reg = Macros.MASK_MODRM_REG(instruction.modrm); break; } return(true); }