public static bool get_operand_displacement(OPERAND op, ref uint disp) { if (op.dispbytes != 0) { disp = op.displacement; return(true); } else { return(false); } }
public static bool get_destination_operand(INSTRUCTION inst, ref OPERAND op) { if (inst.op1.type != OperandType.OPERAND_TYPE_NONE) { op = inst.op1; return(true); } else { return(false); } }
public static bool get_operand_immediate(OPERAND op, ref uint imm) { if (op.immbytes != 0) { imm = op.immediate; return(true); } else { return(false); } }
public static uint get_register_type(OPERAND op) { if (op.type != OperandType.OPERAND_TYPE_REGISTER) { return(0); } switch (Macros.MASK_AM(op.flags)) { case Consts.AM_REG: if (Macros.MASK_FLAGS(op.flags) == Consts.F_r) { return(Consts.REGISTER_TYPE_SEGMENT); } else if (Macros.MASK_FLAGS(op.flags) == Consts.F_f) { return(Consts.REGISTER_TYPE_FPU); } else { return(Consts.REGISTER_TYPE_GEN); } case Consts.AM_E: case Consts.AM_G: case Consts.AM_R: return(Consts.REGISTER_TYPE_GEN); case Consts.AM_C: return(Consts.REGISTER_TYPE_CONTROL); case Consts.AM_D: return(Consts.REGISTER_TYPE_DEBUG); case Consts.AM_S: return(Consts.REGISTER_TYPE_SEGMENT); case Consts.AM_T: return(Consts.REGISTER_TYPE_TEST); case Consts.AM_P: case Consts.AM_Q: return(Consts.REGISTER_TYPE_MMX); case Consts.AM_V: case Consts.AM_W: return(Consts.REGISTER_TYPE_XMM); default: break; } return(0); }
public static string get_operand_string(INSTRUCTION inst, OPERAND op, Format format, uint offset) { StringBuilder ret = new StringBuilder(); Mode mode; uint regtype = 0; uint tmp = 0; if (op.type == OperandType.OPERAND_TYPE_REGISTER) { mode = MODE_CHECK_OPERAND(inst.mode, inst.flags); if (format == Format.FORMAT_ATT) { ret.Append("%%"); } switch (Macros.MASK_AM(op.flags)) { case Consts.AM_REG: if (Macros.MASK_FLAGS(op.flags) == Consts.F_r) { regtype = Consts.REG_SEGMENT; } else if (Macros.MASK_FLAGS(op.flags) == Consts.F_f) { regtype = Consts.REG_FPU; } else { regtype = Consts.REG_GEN_DWORD; } break; case Consts.AM_E: case Consts.AM_G: case Consts.AM_R: regtype = Consts.REG_GEN_DWORD; break; case Consts.AM_C: regtype = Consts.REG_CONTROL; break; case Consts.AM_D: regtype = Consts.REG_DEBUG; break; case Consts.AM_S: regtype = Consts.REG_SEGMENT; break; case Consts.AM_T: regtype = Consts.REG_TEST; break; case Consts.AM_P: case Consts.AM_Q: regtype = Consts.REG_MMX; break; case Consts.AM_V: case Consts.AM_W: regtype = Consts.REG_XMM; break; } if (regtype == Consts.REG_GEN_DWORD) { switch (Macros.MASK_OT(op.flags)) { case Consts.OT_b: ret.Append(Consts.reg_table[Consts.REG_GEN_BYTE, op.reg]); break; case Consts.OT_v: ret.Append((mode == Mode.MODE_32) ? Consts.reg_table[Consts.REG_GEN_DWORD, op.reg] : Consts.reg_table[Consts.REG_GEN_WORD, op.reg]); break; case Consts.OT_w: ret.Append(Consts.reg_table[Consts.REG_GEN_WORD, op.reg]); break; case Consts.OT_d: ret.Append(Consts.reg_table[Consts.REG_GEN_DWORD, op.reg]); break; } } else { ret.Append(Consts.reg_table[regtype, op.reg]); } } else if (op.type == OperandType.OPERAND_TYPE_MEMORY) { mode = MODE_CHECK_ADDR(inst.mode, inst.flags); if (Macros.MASK_PREFIX_G2(inst.flags) != 0) { ret.AppendFormat("{0}{1}:", (format == Format.FORMAT_ATT) ? "%" : "", Consts.reg_table[Consts.REG_SEGMENT, (Macros.MASK_PREFIX_G2(inst.flags)) - 1]); } if (format == Format.FORMAT_ATT) { if (Macros.MASK_PERMS(op.flags) == Consts.P_x) { ret.Append("*"); } if (op.dispbytes != 0) { ret.AppendFormat("0x{0:X}", op.displacement); } if ((op.basereg == Consts.REG_NOP) && (op.indexreg == Consts.REG_NOP)) { return(ret.ToString()); } } ret.Append((format == Format.FORMAT_ATT) ? "(" : "["); if (op.basereg != Consts.REG_NOP) { ret.AppendFormat("{0}{1}", (format == Format.FORMAT_ATT) ? "%" : "", (mode == Mode.MODE_32) ? Consts.reg_table[Consts.REG_GEN_DWORD, op.basereg] : Consts.reg_table[Consts.REG_GEN_WORD, op.basereg]); } if (op.indexreg != Consts.REG_NOP) { if (op.basereg != Consts.REG_NOP) { ret.AppendFormat("{0}{1}", (format == Format.FORMAT_ATT) ? ",%" : "+", (mode == Mode.MODE_32) ? Consts.reg_table[Consts.REG_GEN_DWORD, op.indexreg] : Consts.reg_table[Consts.REG_GEN_WORD, op.indexreg]); } else { ret.AppendFormat("{0}{1}", (format == Format.FORMAT_ATT) ? "%" : "", (mode == Mode.MODE_32) ? Consts.reg_table[Consts.REG_GEN_DWORD, op.indexreg] : Consts.reg_table[Consts.REG_GEN_WORD, op.indexreg]); } switch (op.scale) { case 2: ret.Append((format == Format.FORMAT_ATT) ? ",2" : "*2"); break; case 4: ret.Append((format == Format.FORMAT_ATT) ? ",4" : "*4"); break; case 8: ret.Append((format == Format.FORMAT_ATT) ? ",8" : "*8"); break; } } if (inst.dispbytes != 0 && (format != Format.FORMAT_ATT)) { if ((op.basereg != Consts.REG_NOP) || (op.indexreg != Consts.REG_NOP)) { if ((op.displacement & (1 << (int)(op.dispbytes * 8 - 1))) != 0) { tmp = op.displacement; switch (op.dispbytes) { case 1: tmp = ~tmp & 0xff; break; case 2: tmp = ~tmp & 0xffff; break; case 4: tmp = ~tmp; break; } ret.AppendFormat("-0x{0:X}", tmp + 1); } else { ret.AppendFormat("+0x{0:X}", op.displacement); } } else { ret.AppendFormat("0x{0:X}", op.displacement); } } ret.Append((format == Format.FORMAT_ATT) ? ")" : "]"); } else if (op.type == OperandType.OPERAND_TYPE_IMMEDIATE) { switch (Macros.MASK_AM(op.flags)) { case Consts.AM_J: ret.AppendFormat("0x{0:X}", op.immediate + inst.length + offset); break; case Consts.AM_I1: case Consts.AM_I: if (format == Format.FORMAT_ATT) { ret.Append("$"); } ret.AppendFormat("0x{0:X}", op.immediate); break; case Consts.AM_A: ret.AppendFormat("{0}0x{1:X}:{2}0x{2:X}", (format == Format.FORMAT_ATT) ? "$" : "", op.section, (format == Format.FORMAT_ATT) ? "$" : "", op.displacement); break; } } else { return(null); } return(ret.ToString()); }
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); }
public static uint get_operand_scale(OPERAND op) { return(op.scale); }
public static uint get_operand_indexreg(OPERAND op) { return(op.indexreg); }
public static uint get_operand_basereg(OPERAND op) { return(op.basereg); }
public static uint get_operand_register(OPERAND op) { return(op.reg); }
public static OperandType get_operand_type(OPERAND op) { return(op.type); }