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; }
static UInt32 post_proc_cmpxchg8b(ulong origin_offset, ulong offset, ref INSTRUCTION instr, INTERNAL_DATA idata, DISMODE mode) { if ((idata.prefixes[PREF_REX_INDEX] != 0xFF) && ((instr.rex & PREFIX_REX_W)!=0)) { idata.is_rex_used = 1; instr.mnemonic = "cmpxchg16b"; instr.ops[0].size = (ushort)OP_SIZE.OPERAND_SIZE_128; } return 0; }
static UInt32 post_proc_nop_pause(ulong origin_offset, ulong offset, ref INSTRUCTION instr, INTERNAL_DATA idata, DISMODE mode) { if (idata.prefixes[PREF_REP_INDEX] == PREF_REPNZ_ID) { instr.id = ID_PAUSE; instr.groups = GRP_CACHECT | GRP_SSE2; idata.prefixes[PREF_REP_INDEX] = 0xFF; instr.mnemonic ="pause"; } return 0; }
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; }
//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; }
//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; }
//Parses instruction's mnemonic. If mnemonic is simple, it is just copied to // struct INSTRUCTION. If mnemonic contains has multi mnemonic indicator (MM_INDICATOR) // at first character then it depends on implicit operand's size. In this case the function // calls get_instruction_opsize and builds choses mnemonic basing on result. static void parse_mnemonic(OPCODE_DESCRIPTOR opcode, INSTRUCTION instr, INTERNAL_DATA idata, DISMODE mode) { if ((opcode.mnemonic.value.Length>0) && (opcode.mnemonic.value[0] != MM_INDICATOR)) { instr.mnemonic = opcode.mnemonic.value; } else { get_instruction_opsize(opcode.mnemonic, instr, idata, mode); instr.mnemonic = opcode.mnemonic.values[bsr(instr.opsize) - 1]; } }
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_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_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_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_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; }
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; }
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); }
//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_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; }
//Reads input stream and iterates through tables looking up appropriate struct OPCODE_DESCRIPTOR. // Byte value at [offset] is used as index, the function checks tables limits and max instruction's length. static UInt32 lookup_opcode(ulong offset, byte table, ref OPCODE_DESCRIPTOR opcode_descr, INTERNAL_DATA idata) { byte max; byte opcode; UInt32 res; res = 0; //opcode_descr = NULL; do { opcode = assembly.ReadBytes(offset, 1)[0]; opcode >>= tables[table].shift; opcode &= tables[table].mask; opcode -= tables[table].min; //It looks strange, but I want that table descriptors contain // "real" values. max = (byte)(tables[table].max - tables[table].min); if (opcode > max) { idata.severe_err = ERRS.ERR_BADCODE; break; } if (res > Dasmer.MAX_INSTRUCTION_LEN) { idata.severe_err = ERRS.ERR_TOO_LONG; break; } if ( (tables[table].props & TBL_PROP_MODRM)==0 ) { res++; offset++; } if ((tables[table].opcodes[opcode].groups & GRP_SWITCH)!=0) { table = (byte)tables[table].opcodes[opcode].props;// &0xFF; continue; } break; } while(true); if (idata.severe_err == ERRS.ERR_OK) opcode_descr = tables[table].opcodes[opcode]; 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; }
//Parses 32/64bit memory address operand. static UInt32 parse_mem_operand_32_64(ulong origin_offset, ulong offset, ref INSTRUCTION instr, int op_index, INTERNAL_DATA idata, DISMODE mode) { UInt32 len = 0; if ((instr.flags & INSTR_FLAG_SIB)!=0) { instr.ops[op_index].value.addr.mod = (byte)(instr.modrm >> 0x6); instr.ops[op_index].value.addr.bas = (byte)(instr.sib & 0x7); instr.ops[op_index].value.addr.index = (byte)((instr.sib >> 3) & 0x7); instr.ops[op_index].value.addr.scale = (byte)(1 << (instr.sib >> 0x6)); if (mode == DISMODE.DISASSEMBLE_MODE_64 && idata.prefixes[PREF_REX_INDEX] != 0xFF) { if ((instr.rex & PREFIX_REX_B)!=0) { instr.ops[op_index].value.addr.bas |= REG_CODE_64; idata.is_rex_used = 1; } if ((instr.rex & PREFIX_REX_X)!=0) { instr.ops[op_index].value.addr.index |= REG_CODE_64; idata.is_rex_used = 1; } } len = get_disp(origin_offset, offset, ref instr, op_index, mode); get_mod_type_sib(ref instr, op_index); } else { instr.ops[op_index].value.addr.mod = (byte)(instr.modrm >> 0x6); instr.ops[op_index].value.addr.bas = (byte)(instr.modrm & 0x7); if (mode == DISMODE.DISASSEMBLE_MODE_64) { if ((idata.prefixes[PREF_REX_INDEX] != 0xFF) && ((instr.rex & PREFIX_REX_B)!=0)) { instr.ops[op_index].value.addr.bas |= REG_CODE_64; idata.is_rex_used = 1; } if ( (instr.ops[op_index].value.addr.mod == 0x0) && ((instr.ops[op_index].value.addr.bas == REG_CODE_BP) || (instr.ops[op_index].value.addr.bas == REG_CODE_R13)) ) { instr.ops[op_index].value.addr.bas = REG_CODE_IP; } } len = get_disp(origin_offset, offset, ref instr, op_index, mode); get_mod_type_modrm(ref instr, op_index); } get_seg(ref instr, op_index, idata.prefixes, mode); return len; }
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; }
//Main function for parsing opcode and prefixes. First of all it parses all prefixes and then // looks up for struct OPCODE_DESCRIPTOR. The following algorithm is used to handle instructions that // use prefixes as opcode extension: // // * Have we prefix that may be opcode extension? // No: Lookup starts from 1byte table. // * Is instruction found? // No: Error. // Yes: Success. // Yes: Lookup starts from 'ext_table_index' table. // * Is instruction found? // No: Lookup starts from 1byte table. // * Is instruction found? // No: Error. // Yes: Success. // Yes: Success. static UInt32 parse_opcode(ulong offset, ref OPCODE_DESCRIPTOR opcode_descr, ref INSTRUCTION instr, INTERNAL_DATA idata, ref DISASM_INOUT_PARAMS param) { byte ext_table_index = 0xFF; byte ext_prefix_index = 0; UInt32 res; UInt32 tmp; res = parse_prefixes(offset, ref instr, idata, ext_table_index, ext_prefix_index, ref param); if (idata.severe_err==0) { instr.opcode_offset = (byte)res; offset += res; if ((ext_table_index != 0xFF) && (offset == 0xF)) { tmp = lookup_opcode(offset, ext_table_index, ref opcode_descr, idata); if ((idata.severe_err==0) && (opcode_descr.id != ID_NULL)) { idata.prefixes[ext_prefix_index] = 0xFF; check_ext_sf_prefixes(idata.prefixes, ref instr, ref param); res += tmp; } else { idata.severe_err = 0; res += lookup_opcode(offset, IDX_1BYTE, ref opcode_descr, idata); } } else { res += lookup_opcode(offset, IDX_1BYTE, ref opcode_descr, idata); } if ((idata.severe_err==0) && (opcode_descr.id == ID_NULL)) { idata.severe_err = ERRS.ERR_BADCODE;//error: invalid opcode. } } return res; }
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; }
//Main function for parsing prefixes. Reads input stream until meets non-prefix byte // or maximum instruction length is exceeded. The function checks if a prefix of the same group // was already met and if so, replaces old prefix with a new one. // Old prefix is added to superfluous prefixes array. // The function also checks if a prefix is opcode-extension. static UInt32 parse_prefixes(ulong offset, ref INSTRUCTION instr, INTERNAL_DATA idata, byte ext_table_index, byte ext_pref_index, ref DISASM_INOUT_PARAMS param) { byte pref_code; byte rex_found; byte pref_id; byte pref_index; UInt32 res; UInt32 tmp; OPCODE_DESCRIPTOR ptr; res = 0; rex_found = 0; while(true) { //pref_code = *offset; pref_code = assembly.ReadBytes(offset, 1)[0]; if (res > Dasmer.MAX_INSTRUCTION_LEN) { idata.severe_err = ERRS.ERR_TOO_LONG;//error: instruction too long. break; } ptr = tables[IDX_1BYTE].opcodes[pref_code]; if ( !( ((ptr.groups & GRP_PREFIX)!=0) || (param.mode == DISMODE.DISASSEMBLE_MODE_64 && (pref_code >= 0x40) && (pref_code <= 0x4F) && (rex_found == 0)))) { break; } else { if (rex_found!=0) { idata.severe_err = ERRS.ERR_REX_NOOPCD;//error: an opcode should follow after rex. break; } if ((rex_found != 0) && (param.mode == DISMODE.DISASSEMBLE_MODE_64)) { if ( (pref_code >= 0x40) && (pref_code <= 0x4F) ) { idata.prefixes[PREF_REX_INDEX] = PREF_REX_ID; instr.rex = pref_code; rex_found = 1; res++; offset++; continue; } } tmp = tq_handlers[ptr.ops[0].type](0, 0, ref instr, 0, new OPERAND_SIZE(), new INTERNAL_DATA(), param.mode); pref_index = (byte)(tmp >> 8); pref_id = (byte)tmp;// &0xFF; if (idata.prefixes[pref_index] != 0xFF) { add_sf_prefix(idata.prefixes, pref_index, ref instr, ref param); } idata.prefixes[pref_index] = pref_id; //Used later for prefix table switch. if (ptr.id == ID_66 || ptr.id == ID_REPZ || ptr.id == ID_REPNZ) { ext_table_index =(byte)(ptr.props); ext_pref_index = pref_index; } res++; offset++; } } return res; }
public UInt32 disassemble(ulong offset, ref IInstruction instr1, ref DISASM_INOUT_PARAMS param) { UInt32 len; UInt32 res; OPCODE_DESCRIPTOR opcode = new OPCODE_DESCRIPTOR(); INTERNAL_DATA idata = new INTERNAL_DATA(0xFF); INSTRUCTION instr = instr1 as INSTRUCTION; //Setup everything. //memset(instr, 0x0, sizeof(*instr)); //memset(&idata, 0x0, sizeof(idata)); //memset(idata.prefixes, 0xFF, sizeof(idata.prefixes)); param.sf_prefixes_len = 0; param.errcode = 0; len = res = 0; //Lookup opcode. res = parse_opcode(offset, ref opcode, ref instr, idata, ref param); if (idata.severe_err != ERRS.ERR_OK) { param.errcode = idata.severe_err; return 0; } len += res; if (len > Dasmer.MAX_INSTRUCTION_LEN) { param.errcode = ERRS.ERR_TOO_LONG; return 0; } get_address_size(ref instr, idata.prefixes, param.mode); //Parse MODRM and SIB bytes. len += parse_modrm_sib(offset + len, ref instr, opcode); if (len > Dasmer.MAX_INSTRUCTION_LEN) { param.errcode = ERRS.ERR_TOO_LONG; return 0; } //Copy flags, eflags, id, groups. copy_eflags(ref instr, ref opcode); copy_instr_flags(ref instr, ref opcode); instr.id = opcode.id; instr.groups = opcode.groups; //Parse mnemonic. parse_mnemonic(opcode, instr, idata, param.mode); if (idata.severe_err != ERRS.ERR_OK) { param.errcode = idata.severe_err; return 0; } //Deal with operands. res = parse_operand(offset, offset + len, opcode.ops[0], instr, 0, idata, param.mode); if (idata.severe_err != ERRS.ERR_OK) { param.errcode = idata.severe_err; return 0; } len += res; if (len > Dasmer.MAX_INSTRUCTION_LEN) { param.errcode = ERRS.ERR_TOO_LONG; return 0; } res = parse_operand(offset, offset + len, opcode.ops[1], instr, 1, idata, param.mode); if (idata.severe_err != ERRS.ERR_OK) { param.errcode = idata.severe_err; return 0; } len += res; if (len > Dasmer.MAX_INSTRUCTION_LEN) { param.errcode = ERRS.ERR_TOO_LONG; return 0; } res = parse_operand(offset, offset + len, opcode.ops[2], instr, 2, idata, param.mode); if (idata.severe_err != ERRS.ERR_OK) { param.errcode = idata.severe_err; return 0; } len += res; if (len > Dasmer.MAX_INSTRUCTION_LEN) { param.errcode = ERRS.ERR_TOO_LONG; return 0; } //Do postprocessing if necessary. if ((opcode.props & PROP_POST_PROC)!=0) { res = postprocs[opcode.props >> POST_PROC_SHIFT](offset, offset, ref instr, idata, param.mode); if (idata.severe_err != ERRS.ERR_OK) { param.errcode = idata.severe_err; return 0; } if (res>0) { len = res; if (len > Dasmer.MAX_INSTRUCTION_LEN) { param.errcode = ERRS.ERR_TOO_LONG; return 0; } } } //Check if REX is superfluous. if ((param.mode == DISMODE.DISASSEMBLE_MODE_64) && (idata.is_rex_used != 0)) add_sf_prefix_value(idata.prefixes, PREF_REX_INDEX, instr.rex, ref instr, ref param); //Check if segment prefix is superfluous. check_seg_sf_prefixes(instr, idata.prefixes, param); //Check if opsize is superfluous. if ((idata.is_opsize_used!=0) && idata.prefixes[PREF_OPSIZE_INDEX] != 0xFF) add_sf_prefix(idata.prefixes, PREF_OPSIZE_INDEX, ref instr, ref param); //Check if addrsize is superfluous. if ((idata.is_addrsize_used!=0) && idata.prefixes[PREF_ADDRSIZE_INDEX] != 0xFF) add_sf_prefix(idata.prefixes, PREF_ADDRSIZE_INDEX, ref instr, ref param); //Convert prefixes to output representation. convert_prefixes(instr, idata.prefixes); //Copy error if exists. param.errcode = idata.err; //And post checks. if ((param.arch & opcode.arch)!=0) param.errcode = ERRS.ERR_ANOT_ARCH;//error: another architecture. else if ( ((instr.prefixes & INSTR_PREFIX_LOCK)!=0) && ((opcode.props & PROP_LOCK)==0) ) param.errcode = ERRS.ERR_NON_LOCKABLE;//error: prefix lock non-lockable instruction. else if (((opcode.props & PROP_I64) != 0) && (param.mode == DISMODE.DISASSEMBLE_MODE_64)) param.errcode = ERRS.ERR_16_32_ONLY;//error: instruction is 16/32bit mode only. else if (((opcode.props & PROP_O64) != 0) && (param.mode != DISMODE.DISASSEMBLE_MODE_64)) param.errcode = ERRS.ERR_64_ONLY;//error: instruction is 64bit mode only. apply_disasm_options(ref instr, len, param); instr.bytes = assembly.ReadBytes(offset, (int)len); instr.Addr = (ulong)offset; return len; }
/************************* * 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; }
static void create_genreg_operand(ref INSTRUCTION instr, int op_index, byte code, OP_SIZE size, byte rex, ref INTERNAL_DATA idata, DISMODE mode) { if (mode == DISMODE.DISASSEMBLE_MODE_64 && idata.prefixes[PREF_REX_INDEX] != 0xFF) { if (code > REG_CODE_BX && size == OP_SIZE.OPERAND_SIZE_8) { code |= REG_CODE_64; code += 0x4; idata.is_rex_used = 1; } if ((instr.rex & rex)!=0) { code |= REG_CODE_64; idata.is_rex_used = 1; } } create_reg_operand(ref instr, op_index, REG_TYPE.REG_TYPE_GEN, code, size); }
static UInt32 post_proc_multinop(ulong origin_offset, ulong offset, ref INSTRUCTION instr, INTERNAL_DATA idata, DISMODE mode) { instr.ops[0].flags &= (byte)~OPERAND_FLAG_PRESENT; instr.ops[1].flags &= (byte)~OPERAND_FLAG_PRESENT; instr.ops[2].flags &= (byte)~OPERAND_FLAG_PRESENT; return 0; }
static void create_xmmreg_operand(ref INSTRUCTION instr, int op_index, byte code, OP_SIZE size, byte rex, ref INTERNAL_DATA idata, DISMODE mode) { if ((mode == DISMODE.DISASSEMBLE_MODE_64) && (idata.prefixes[PREF_REX_INDEX] != 0xFF)) { if ((instr.rex & rex)!=0) { code |= REG_CODE_64; idata.is_rex_used = 1; } } create_reg_operand(ref instr, op_index, REG_TYPE.REG_TYPE_XMM, code, size); }
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 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; }