public static void sq_v67q64(ref OPERAND_SIZE opsize, ref INSTRUCTION instr, INTERNAL_DATA idata, DISMODE mode) { if (mode == DISMODE.DISASSEMBLE_MODE_64) { sq_q(ref opsize, ref instr, idata, mode); } else { if (idata.prefixes[PREF_ADDRSIZE_INDEX] != 0xFF) { mode ^= (DISMODE.DISASSEMBLE_MODE_16 | DISMODE.DISASSEMBLE_MODE_32); idata.is_addrsize_used = 1; } if (mode == DISMODE.DISASSEMBLE_MODE_16) { sq_w(ref opsize, ref instr, idata, mode); } else { sq_d(ref opsize, ref instr, idata, mode); } } }
static UInt32 parse_operand(ulong origin_offset, ulong offset, INTERNAL_OPERAND iop, INSTRUCTION instr, int op_index, INTERNAL_DATA idata, DISMODE mode) { UInt32 res = 0; OPERAND_SIZE opsize = new OPERAND_SIZE(); if (iop.type != TQ_NULL) { instr.ops[op_index].flags |= OPERAND_FLAG_PRESENT; if (iop.size >= sq_handlers.Count()) { idata.severe_err = ERRS.ERR_INTERNAL; } else { sq_handlers[iop.size](ref opsize, ref instr, idata, mode); } if (iop.size >= tq_handlers.Count()) { idata.severe_err = ERRS.ERR_INTERNAL; } else { res = tq_handlers[iop.type](origin_offset, offset, ref instr, op_index, opsize, idata, mode); } } return res; }
/************************* * Postprocessing routines. ************************** */ static UInt32 post_proc_arpl_movsxd(ulong origin_offset, ulong offset, ref INSTRUCTION instr, INTERNAL_DATA idata, DISMODE mode) { UInt32 res; res = 0; if (mode == DISMODE.DISASSEMBLE_MODE_64) { OPERAND_SIZE opsize = new OPERAND_SIZE(); instr.id = ID_MOVSXD; instr.groups = GRP_GEN | GRP_CONVER; instr.tested_flags = 0; instr.modified_flags = 0; instr.set_flags = 0; instr.cleared_flags = 0; instr.flags &= (ushort)(INSTR_FLAG_MODRM | INSTR_FLAG_SIB); instr.mnemonic = "movsxd"; byte[] bt = assembly.ReadBytes((ulong)instr.opcode_offset + 1, 4); res = (UInt32)( bt[0] + bt[1]*256 + bt[2]*256*256 + bt[3]*256*256*256); offset += res; if ((instr.flags & INSTR_FLAG_MODRM)!=0) { res++; offset++; } if ((instr.flags & INSTR_FLAG_SIB)!=0) { res++; offset++; } instr.ops[0].value.imm.imm64 = 0; instr.ops[1].value.imm.imm64 = 0; instr.ops[0].flags = OPERAND_FLAG_PRESENT; instr.ops[1].flags = OPERAND_FLAG_PRESENT; sq_dqp(ref opsize, ref instr, idata, mode); res += tq_G(origin_offset, offset, ref instr, 0, opsize, idata, mode); sq_d(ref opsize, ref instr, idata, mode); res += tq_E(origin_offset, offset, ref instr, 1, opsize, idata, mode); } return res; }
public static UInt32 tq_Y(ulong origin_offset, ulong offset, ref INSTRUCTION instr, int op_index, OPERAND_SIZE opsize, INTERNAL_DATA idata, DISMODE mode) { instr.ops[op_index].flags |= (byte)OP_TYPE.OPERAND_TYPE_MEM; instr.ops[op_index].size = (ushort)opsize.size; if (mode == DISMODE.DISASSEMBLE_MODE_64) instr.ops[op_index].value.addr.seg = SREG_CODE_CS; else instr.ops[op_index].value.addr.seg = SREG_CODE_ES; instr.ops[op_index].value.addr.mod = ADDR_MOD_BASE; instr.ops[op_index].value.addr.bas = REG_CODE_DI; return 0x0; }
//Get instruction's size. Well, really this is size of implicit operand // that influences on instruction's mnemonic. static void get_instruction_opsize(MULTI_MNEMONIC multi_mnemonic, INSTRUCTION instr, INTERNAL_DATA idata, DISMODE mode) { OPERAND_SIZE opsize = new OPERAND_SIZE(); if (multi_mnemonic.size >= sq_handlers.Count()) { idata.severe_err = ERRS.ERR_INTERNAL; } else { sq_handlers[multi_mnemonic.size](ref opsize, ref instr, idata, mode); } instr.opsize = (byte)opsize.size; //Possible sizes are 2/4/8. }
public static UInt32 tq_T(ulong origin_offset, ulong offset, ref INSTRUCTION instr, int op_index, OPERAND_SIZE opsize, INTERNAL_DATA idata, DISMODE mode) { create_reg_operand(ref instr, op_index, REG_TYPE.REG_TYPE_TR, (byte)((instr.modrm >> 0x3) & 0x7), opsize.size); return 0x0; }
public static UInt32 tq_W(ulong origin_offset, ulong offset, ref INSTRUCTION instr, int op_index, OPERAND_SIZE opsize, INTERNAL_DATA idata, DISMODE mode) { UInt32 res; if ((instr.modrm & 0xC0) == 0xC0) { create_xmmreg_operand(ref instr, op_index, (byte)(instr.modrm & 0x7), opsize.size, PREFIX_REX_B, ref idata, mode); res = 0; } else { res = parse_mem_operand(origin_offset, offset, ref instr, op_index, opsize, idata, mode); } return res; }
public static void sq_wi(ref OPERAND_SIZE opsize, ref INSTRUCTION instr, INTERNAL_DATA idata, DISMODE mode) { opsize.size_in_stream = OP_SIZE.OPERAND_SIZE_16; opsize.size = opsize.size_in_stream; opsize.sign = 0; }
public static void sq_wvqp(ref OPERAND_SIZE opsize, ref INSTRUCTION instr, INTERNAL_DATA idata, DISMODE mode) { if ((instr.modrm & 0xC0) == 0xC0) { sq_vqp(ref opsize, ref instr, idata, mode); } else { sq_w(ref opsize, ref instr, idata, mode); } }
public static void sq_vqp(ref OPERAND_SIZE opsize, ref INSTRUCTION instr, INTERNAL_DATA idata, DISMODE mode) { if (mode == DISMODE.DISASSEMBLE_MODE_64) { opsize.size_in_stream = get_operand_size(instr, ref idata, mode); opsize.size = opsize.size_in_stream; opsize.sign = 0; } else { sq_v(ref opsize, ref instr, idata, mode); } }
public static void sq_vs(ref OPERAND_SIZE opsize, ref INSTRUCTION instr, INTERNAL_DATA idata, DISMODE mode) { if (mode != DISMODE.DISASSEMBLE_MODE_64) { sq_v(ref opsize, ref instr, idata, mode); } else { opsize.size_in_stream = get_operand_size_16_32(ref idata, mode); if (idata.prefixes[PREF_OPSIZE_INDEX] != 0xFF) { opsize.size = OP_SIZE.OPERAND_SIZE_16; } else { opsize.size = OP_SIZE.OPERAND_SIZE_64; } } }
public static void sq_vq64(ref OPERAND_SIZE opsize, ref INSTRUCTION instr, INTERNAL_DATA idata, DISMODE mode) { if (mode == DISMODE.DISASSEMBLE_MODE_64) { sq_q(ref opsize, ref instr, idata, mode); } else { sq_v(ref opsize, ref instr, idata, mode); } }
public static void sq_vds(ref OPERAND_SIZE opsize, ref INSTRUCTION instr, INTERNAL_DATA idata, DISMODE mode) { if (mode == DISMODE.DISASSEMBLE_MODE_64) { opsize.size_in_stream = OP_SIZE.OPERAND_SIZE_32; opsize.size = OP_SIZE.OPERAND_SIZE_64; opsize.sign = 1; } else { sq_v(ref opsize, ref instr, idata, mode); } }
public static void sq_vd64(ref OPERAND_SIZE opsize, ref INSTRUCTION instr, INTERNAL_DATA idata, DISMODE mode) { if (mode != DISMODE.DISASSEMBLE_MODE_64) { sq_v(ref opsize, ref instr, idata, mode); } else { if (idata.prefixes[PREF_OPSIZE_INDEX] != 0xFF) { idata.is_opsize_used = 1; sq_w(ref opsize, ref instr, idata, mode); } else { sq_q(ref opsize, ref instr, idata, mode); } } }
public static UInt32 tq_rSP(ulong origin_offset, ulong offset, ref INSTRUCTION instr, int op_index, OPERAND_SIZE opsize, INTERNAL_DATA idata, DISMODE mode) { create_genreg_operand(ref instr, op_index, REG_CODE_SP, opsize.size, PREFIX_REX_B, ref idata, mode); return 0x0; }
public static UInt32 tq_A(ulong origin_offset, ulong offset, ref INSTRUCTION instr, int op_index, OPERAND_SIZE opsize, INTERNAL_DATA idata, DISMODE mode) { instr.ops[op_index].flags |= (byte)OP_TYPE.OPERAND_TYPE_DIR; instr.ops[op_index].size = (ushort)opsize.size; instr.ops[op_index].value.far_addr.offset = (byte)(offset - origin_offset); //instr.ops[op_index].value.far_addr.far_addr_ab = assembly.Image.ReadBytes(offset, instr.ops[op_index].size); byte[] bt = assembly.ReadBytes(offset, instr.ops[op_index].size); instr.ops[op_index].value.far_addr.far_addr48.Val = 0; foreach (byte bb in bt.Reverse()) { instr.ops[op_index].value.far_addr.far_addr48.Val <<= 8; instr.ops[op_index].value.far_addr.far_addr48.Val += bb; } return instr.ops[op_index].size; }
public static UInt32 tq_SS(ulong origin_offset, ulong offset, ref INSTRUCTION instr, int op_index, OPERAND_SIZE opsize, INTERNAL_DATA idata, DISMODE mode) { create_reg_operand(ref instr, op_index, REG_TYPE.REG_TYPE_SEG, SREG_CODE_SS, opsize.size); return 0; }
public static UInt32 tq_E(ulong origin_offset, ulong offset, ref INSTRUCTION instr, int op_index, OPERAND_SIZE opsize, INTERNAL_DATA idata, DISMODE mode) { return parse_rm_operand(origin_offset, offset, ref instr, op_index, opsize, ref idata, mode); }
public static UInt32 tq_V(ulong origin_offset, ulong offset, ref INSTRUCTION instr, int op_index, OPERAND_SIZE opsize, INTERNAL_DATA idata, DISMODE mode) { create_xmmreg_operand(ref instr, op_index, (byte)((instr.modrm >> 0x3) & 0x7), opsize.size, PREFIX_REX_R, ref idata, mode); return 0; }
public static UInt32 tq_fES(ulong origin_offset, ulong offset, ref INSTRUCTION instr, int op_index, OPERAND_SIZE opsize, INTERNAL_DATA idata, DISMODE mode) { UInt32 res; if ((instr.modrm & 0xC0) == 0xC0) res = tq_fEST(origin_offset, offset, ref instr, op_index, opsize, idata, mode); else res = tq_M(origin_offset, offset, ref instr, op_index, opsize, idata, mode); return res; }
public static UInt32 tq_X(ulong origin_offset, ulong offset, ref INSTRUCTION instr, int op_index, OPERAND_SIZE opsize, INTERNAL_DATA idata, DISMODE mode) { UInt32 res; res = 0; instr.ops[op_index].flags |= (byte)OP_TYPE.OPERAND_TYPE_MEM; instr.ops[op_index].size = (ushort)opsize.size; instr.ops[op_index].value.addr.mod = ADDR_MOD_BASE; instr.ops[op_index].value.addr.bas = REG_CODE_SI; get_seg(ref instr, op_index, idata.prefixes, mode); return 0x0; }
public static UInt32 tq_I(ulong origin_offset, ulong offset, ref INSTRUCTION instr, int op_index, OPERAND_SIZE opsize, INTERNAL_DATA idata, DISMODE mode) { instr.ops[op_index].flags |= (byte)OP_TYPE.OPERAND_TYPE_IMM; instr.ops[op_index].size = (ushort)opsize.size; instr.ops[op_index].value.imm.size = (byte)opsize.size_in_stream; instr.ops[op_index].value.imm .offset = (byte)(offset - origin_offset); //instr.ops[op_index].value.imm.immab = assembly.Image.ReadBytes(offset, opsize.size_in_stream); byte[] bt = assembly.ReadBytes(offset, (int)opsize.size_in_stream); instr.ops[op_index].value.imm.imm64 = 0; foreach (byte bb in bt.Reverse()) { instr.ops[op_index].value.imm.imm64 <<= 8; instr.ops[op_index].value.imm.imm64 += bb; } //!!!memcpy(&(instr.ops[op_index].value.imm.imm8), offset, opsize.size_in_stream); //movsx(ref instr.ops[op_index].value.imm.immab, opsize.size_in_stream, 0x8); return (byte)opsize.size_in_stream; }
public static UInt32 tq_Z(ulong origin_offset, ulong offset, ref INSTRUCTION instr, int op_index, OPERAND_SIZE opsize, INTERNAL_DATA idata, DISMODE mode) { byte[] bt = assembly.ReadBytes(offset - 1, 1); //We already consumed opcode, hence we need to look backward. create_genreg_operand(ref instr, op_index, (byte)(bt[0] & 0x7), opsize.size, PREFIX_REX_B, ref idata, mode); return 0x0; }
public static UInt32 tq_J(ulong origin_offset, ulong offset, ref INSTRUCTION instr, int op_index, OPERAND_SIZE opsize, INTERNAL_DATA idata, DISMODE mode) { instr.ops[op_index].flags |= OPERAND_FLAG_REL; return tq_I(origin_offset, offset, ref instr, op_index, opsize, idata, mode); }
//Parses memory address operand. static UInt32 parse_mem_operand(ulong origin_offset, ulong offset, ref INSTRUCTION instr, int op_index, OPERAND_SIZE opsize, INTERNAL_DATA idata, DISMODE mode) { UInt32 len; instr.ops[op_index].flags |= (byte)OP_TYPE.OPERAND_TYPE_MEM; instr.ops[op_index].size = (ushort)opsize.size; if (instr.addrsize == ADDR_SIZE_16) { len = parse_mem_operand_16(origin_offset, offset, ref instr, op_index, mode); } else { len = parse_mem_operand_32_64(origin_offset, offset, ref instr, op_index, idata, mode); } idata.is_addrsize_used = 1; return len; }
public static UInt32 tq_O(ulong origin_offset, ulong offset, ref INSTRUCTION instr, int op_index, OPERAND_SIZE opsize, INTERNAL_DATA idata, DISMODE mode) { UInt32 res; res = instr.addrsize; instr.ops[op_index].flags |= (byte) OP_TYPE.OPERAND_TYPE_MEM; instr.ops[op_index].size = (ushort)opsize.size; instr.ops[op_index].value.addr.mod = ADDR_MOD_DISP; //instr.disp.value.ab = assembly.Image.ReadBytes(offset, instr.addrsize); byte[] bt = assembly.ReadBytes(offset, instr.addrsize); instr.disp.value.d64 = 0; foreach (byte bb in bt.Reverse()) { instr.disp.value.d64 <<= 8; instr.disp.value.d64 += bb; } get_seg(ref instr, op_index, idata.prefixes, mode); return res; }
//Parses operand accordingly to MODRM value. static UInt32 parse_rm_operand(ulong origin_offset, ulong offset, ref INSTRUCTION instr, int op_index, OPERAND_SIZE opsize, ref INTERNAL_DATA idata, DISMODE mode) { UInt32 len = 0; if ((instr.modrm & 0xC0) == 0xC0) { create_genreg_operand(ref instr, op_index, (byte)(instr.modrm & 0x7), opsize.size, PREFIX_REX_B, ref idata, mode); } else { len = parse_mem_operand(origin_offset, offset, ref instr, op_index, opsize, idata, mode); } return len; }
public static UInt32 tq_R(ulong origin_offset, ulong offset, ref INSTRUCTION instr, int op_index, OPERAND_SIZE opsize, INTERNAL_DATA idata, DISMODE mode) { UInt32 res = parse_rm_operand(origin_offset, offset, ref instr, op_index, opsize, ref idata, mode); if ((instr.modrm & 0xC0) != 0xC0) { idata.err = ERRS.ERR_RM_MEM;//error: rm encodes memory. } return res; }
static UInt32 tq_1(ulong origin_offset, ulong offset, ref INSTRUCTION instr, int op_index, OPERAND_SIZE opsize, INTERNAL_DATA idata, DISMODE mode) { instr.ops[op_index].flags |= (byte)OP_TYPE.OPERAND_TYPE_IMM; instr.ops[op_index].size = (ushort)OP_SIZE.OPERAND_SIZE_8; instr.ops[op_index].value.imm.imm8 = 0x1; return 0x0; }
public static void sq_v(ref OPERAND_SIZE opsize, ref INSTRUCTION instr, INTERNAL_DATA idata, DISMODE mode) { opsize.size_in_stream = get_operand_size_16_32(ref idata, mode); opsize.size = opsize.size_in_stream; opsize.sign = 0; }