public Number(INSTRUCTION instruction) { if (INSTRUCTION.ONE <= instruction && instruction <= INSTRUCTION.EIGHT) { this.instruction = instruction; } }
public void ShowInstruction(INSTRUCTION instruction) { switch (instruction) { case INSTRUCTION.TopLeft: ShowInstruction(new Vector2(110, -110), new Vector2(0, 1), new Vector2(0, 1), Quaternion.Euler(0, 0, 180), "top left"); break; case INSTRUCTION.BottomLeft: ShowInstruction(new Vector2(110, 110), new Vector2(0, 0), new Vector2(0, 0), Quaternion.Euler(0, 0, 270), "bottom left"); break; case INSTRUCTION.BottomRight: ShowInstruction(new Vector2(-110, 110), new Vector2(1, 0), new Vector2(1, 0), Quaternion.Euler(0, 0, 0), "bottom right"); break; case INSTRUCTION.Trigger: _instruction.SetActive(true); _instructionArrow.gameObject.SetActive(false); _instructionNote.gameObject.SetActive(false); _instructionText.text = "Click the trigger to begin"; break; case INSTRUCTION.None: default: _instruction.SetActive(false); break; } }
public IHttpActionResult PostINSTRUCTION(INSTRUCTION iNSTRUCTION) { if (!ModelState.IsValid) { return(BadRequest(ModelState)); } db.INSTRUCTION.Add(iNSTRUCTION); try { db.SaveChanges(); } catch (DbUpdateException) { if (INSTRUCTIONExists(iNSTRUCTION.id_instruction)) { return(Conflict()); } else { throw; } } return(CreatedAtRoute("DefaultApi", new { id = iNSTRUCTION.id_instruction }, iNSTRUCTION)); }
public Action(INSTRUCTION instruction) { if (instruction == INSTRUCTION.PLUS || instruction == INSTRUCTION.MINUS || instruction == INSTRUCTION.PLAY) { this.instruction = instruction; } }
public IHttpActionResult PutINSTRUCTION(int id, INSTRUCTION iNSTRUCTION) { if (!ModelState.IsValid) { return(BadRequest(ModelState)); } if (id != iNSTRUCTION.id_instruction) { return(BadRequest()); } db.Entry(iNSTRUCTION).State = EntityState.Modified; try { db.SaveChanges(); } catch (DbUpdateConcurrencyException) { if (!INSTRUCTIONExists(id)) { return(NotFound()); } else { throw; } } return(StatusCode(HttpStatusCode.NoContent)); }
public IHttpActionResult GetINSTRUCTION(int id) { INSTRUCTION iNSTRUCTION = db.INSTRUCTION.Find(id); if (iNSTRUCTION == null) { return(NotFound()); } return(Ok(iNSTRUCTION)); }
protected INSTRUCTION typeCheck(INSTRUCTION instruction) // check the type of instruction { if (INSTRUCTION.ONE <= instruction && instruction <= INSTRUCTION.EIGHT) { return(INSTRUCTION.NUMBER); } else { return(INSTRUCTION.ACTION); } }
public IHttpActionResult DeleteINSTRUCTION(int id) { INSTRUCTION iNSTRUCTION = db.INSTRUCTION.Find(id); if (iNSTRUCTION == null) { return(NotFound()); } db.INSTRUCTION.Remove(iNSTRUCTION); db.SaveChanges(); return(Ok(iNSTRUCTION)); }
public Instruction make(INSTRUCTION instruction) { Instruction _tmp; INSTRUCTION type = typeCheck(instruction); if (type == INSTRUCTION.ACTION) { _tmp = new Action(instruction); } else { _tmp = new Number(instruction); } return(this + _tmp); }
public static InstructionCollection Disassemble(byte[] codes) { InstructionCollection ret = new InstructionCollection(); uint idx = 0; while (idx < codes.Length) { INSTRUCTION inst = new INSTRUCTION(); uint len = libdasm.libdasm.get_instruction(out inst, codes, idx, Mode.MODE_32); Instruction wrapper = new Instruction(ret, inst); ret.Add(wrapper); idx += len; } return(ret); }
//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; }
//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; }
//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]; } }
//Parses 16bit memory address operand. static UInt32 parse_mem_operand_16(ulong origin_offset, ulong offset, ref INSTRUCTION instr, int op_index, DISMODE mode) { byte len; int index; instr.ops[op_index].value.addr.mod = (byte)(instr.modrm >> 0x6); len = get_disp(origin_offset, offset, ref instr, op_index, mode); index = (instr.modrm >> 0x3 & 0x18) | (instr.modrm & 0x7); instr.ops[op_index].value.addr.seg = addrs_16bit[index].seg; instr.ops[op_index].value.addr.mod = addrs_16bit[index].mod; instr.ops[op_index].value.addr.bas = addrs_16bit[index].bas; instr.ops[op_index].value.addr.index = addrs_16bit[index].index; instr.ops[op_index].value.addr.scale = addrs_16bit[index].scale; return len; }
//Calculates segment for memory addressing operands accordingly to //mode, segment override prefixes and address base register. static void get_seg(ref INSTRUCTION instr, int op_index, byte[] prefixes, DISMODE mode) { if (prefixes[PREF_SEG_INDEX] == 0xFF) { if (mode == DISMODE.DISASSEMBLE_MODE_64) { instr.ops[op_index].value.addr.seg = SREG_CODE_CS; } else { if ( (instr.ops[op_index].value.addr.mod & ADDR_MOD_BASE)==0 ) { instr.ops[op_index].value.addr.seg = SREG_CODE_DS; } else { if ((instr.ops[op_index].value.addr.bas != REG_CODE_BP) && (instr.ops[op_index].value.addr.bas != REG_CODE_SP)) { instr.ops[op_index].value.addr.seg = SREG_CODE_DS; } else { instr .ops[op_index].value.addr.seg = SREG_CODE_SS; } } } } else { if (mode != DISMODE.DISASSEMBLE_MODE_64) { instr.ops[op_index].value.addr.seg = sregs[prefixes[PREF_SEG_INDEX]]; } else { if (prefixes[PREF_SEG_INDEX] == PREF_FS_ID || prefixes[PREF_SEG_INDEX] == PREF_GS_ID) { instr.ops[op_index].value.addr.seg = sregs[prefixes[PREF_SEG_INDEX]]; } else { instr.ops[op_index].value.addr.seg = SREG_CODE_CS; } } } }
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 LoadData(string input) { mainForm.Reset(); mainForm.ResetDataGrid(); int index = 0; int scanSector = 0; input = Regex.Replace(input, @"%.*", ""); // removes comments string[] splitInput = Regex.Split(input, @"\s+"); mainForm.PrintOutput("Reading Input File:" + NEW_LINE, true); mainForm.PrintOutput(NEW_LINE + "Initial Data Value --" + NEW_LINE, true); if (langVersion == 'a') { foreach (string s in splitInput) { if (Regex.IsMatch(s, @"\s+") || s == String.Empty) { continue; } if (s == "+9999999999") { if (scanSector == 0) { mainForm.PrintOutput(NEW_LINE + "Program Instructions --" + NEW_LINE, true); } else if (scanSector == 1) { mainForm.PrintOutput(NEW_LINE + "Input Data --" + NEW_LINE, true); } index = 0; scanSector++; continue; } if (s.Length != 11) { mainForm.PrintOutput("Invalid input length of " + s.Length + " on line " + index + NEW_LINE, false); mainForm.PrintOutput("Ending parse of input file" + NEW_LINE, false); return; } if (scanSector == 0) { int d = int.Parse(s.Substring(1)); data[index] = d; mainForm.AddToDataGrid(index, d); } else if (scanSector == 1) { INSTRUCTION instr = ParseInstruction(s); instrmem[index] = instr; mainForm.AddToProgramGrid(instr.instr, instr.op1.ToString("D3"), instr.op2.ToString("D3"), instr.op3.ToString("D3")); } else if (scanSector == 2) { int d = int.Parse(s.Substring(1)); card[index] = d; mainForm.AddToInputGrid(s); } mainForm.PrintOutput(s + NEW_LINE, true); index++; } } else if (langVersion == 'b') { Stack <string> newInput = new Stack <string>(splitInput.Reverse()); while (newInput.Count > 0) { string s = newInput.Pop(); if (Regex.IsMatch(s, @"\s+") || s == String.Empty) { continue; // skip empty lines } if (s == "+9999999999") { if (scanSector == 0) { mainForm.PrintOutput(NEW_LINE + "Program Instructions --" + NEW_LINE, true); } else if (scanSector == 1) { mainForm.PrintOutput(NEW_LINE + "Input Data --" + NEW_LINE, true); } index = 0; scanSector++; continue; } if (s.Length != 11) { mainForm.PrintOutput("Invalid input length of " + s.Length + " on line " + index + NEW_LINE, false); mainForm.PrintOutput("Ending parse of input file" + NEW_LINE, false); return; } mainForm.PrintOutput(s + NEW_LINE, true); if (scanSector == 0) // data cards { int c = int.Parse(s.Substring(2, 3)); // op1 int n = int.Parse(s.Substring(5, 3)); // op2 SYMBOL_TABLE[c] = index; string s2 = newInput.Pop(); int d = int.Parse(s2.Substring(1)); for (int i = 0; i < n; i++) { data[index + i] = d; mainForm.AddToDataGrid(c + i, d); mainForm.PrintOutput(s2 + NEW_LINE, true); } index = index + n; } else if (scanSector == 1) // instruction cards { INSTRUCTION instr = ParseInstruction(s); if (instr.instr == "-7") { if (LABEL_TABLE[instr.op1] > 0) { mainForm.PrintOutput("ERROR: Duplicate Label " + instr.op1 + NEW_LINE, true); return; } LABEL_TABLE[instr.op1] = index; } else if ((instr.instr[0] == '+') && ((instr.instr[1] == '4') || (instr.instr[1] == '5') || (instr.instr[1] == '7'))) { if (LABEL_TABLE[instr.op3] < 0) { LABEL_TABLE[instr.op3] = -2; // referenced, but not defined } } else if ((instr.instr[0] == '-') && ((instr.instr[1] == '4') || (instr.instr[1] == '5'))) { if (LABEL_TABLE[instr.op3] < 0) { LABEL_TABLE[instr.op3] = -2; // referenced, but not defined } } instrmem[index] = instr; mainForm.AddToProgramGrid(instr.instr, instr.op1.ToString("D3"), instr.op2.ToString("D3"), instr.op3.ToString("D3")); index++; } else if (scanSector == 2) // input cards { int d = int.Parse(s.Substring(1)); card[index] = d; mainForm.AddToInputGrid(s); index++; } } foreach (int i in LABEL_TABLE) { if (i == -2) { mainForm.PrintOutput("ERROR: Use of undefined label " + i + NEW_LINE, true); return; } } } isLoaded = true; mainForm.ProgramLoaded(); }
/************************* * 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 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; }
//Calculates displacement's size and copies it to struct DISPLACEMENT. static byte get_disp(ulong origin_offset, ulong offset, ref INSTRUCTION instr, int op_index, DISMODE mode) { byte len = 0; switch(instr.ops[op_index].value.addr.mod) { case 0x0: if (instr.ops[op_index].value.addr.bas == REG_CODE_BP) len = instr.addrsize; else len = 0x0; break; case 0x1: len = 0x1; break; case 0x2: len = instr.addrsize; break; } if (len == 8) len = 4; instr.disp.size = len; if (len!=0) { //instr.disp.value.ab = assembly.Image.ReadBytes(offset, len); byte[] bt = assembly.ReadBytes(offset, len); instr.disp.value.d64 = 0; foreach (byte bb in bt.Reverse()) { instr.disp.value.d64 <<= 8; instr.disp.value.d64 += bb; } movsx(ref instr.disp.value.d64, len, 0x8); instr.disp.offset = (byte)(offset - origin_offset); } return len; }
internal Instruction(InstructionCollection coll, INSTRUCTION inst) { this.coll = coll; this.inst = inst; }
//Builds ADDR.mod field from instruction's MODRM byte. static void get_mod_type_modrm(ref INSTRUCTION instr, int op_index) { if (instr.ops[op_index].value.addr.mod != 0x0) { instr.ops[op_index].value.addr.mod = (byte)(ADDR_MOD_BASE | ADDR_MOD_DISP); } else { if ((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.mod = ADDR_MOD_DISP; } else { instr.ops[op_index].value.addr.mod = ADDR_MOD_BASE; } } }
//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. }
//Applies disassembling options. static void apply_disasm_options(ref INSTRUCTION instr, UInt32 len, DISASM_INOUT_PARAMS param) { for (int i = 0; i < 3; i++) { if ((param.options & Dasmer.DISASM_OPTION_APPLY_REL) != 0) { if ((instr.ops[i].flags & OPERAND_FLAG_REL)!=0) { instr.ops[i].value.imm.imm64 += len + param.bas; } } if ((param.options & Dasmer.DISASM_OPTION_OPTIMIZE_DISP) != 0) { if (((instr.ops[i].flags & (byte)OP_TYPE.OPERAND_TYPE_MEM)!=0) && (instr.ops[i].value.addr.mod != ADDR_MOD_DISP)) { if (instr.disp.value.d64 == 0x0) instr.ops[i].value.addr.mod &= (byte)(~(uint)ADDR_MOD_DISP); } } } }
//Builds ADDR.mod field from instruction's SIB byte. static void get_mod_type_sib(ref INSTRUCTION instr, int op_index) { if (instr.ops[op_index].value.addr.index == REG_CODE_SP) { get_mod_type_modrm(ref instr, op_index); } else { if (instr.ops[op_index].value.addr.mod == 0) { if ((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.mod = (byte)(ADDR_MOD_IDX | ADDR_MOD_DISP); } else { instr.ops[op_index].value.addr.mod = (byte)(ADDR_MOD_BASE | ADDR_MOD_IDX); } } else { instr.ops[op_index].value.addr.mod = (byte)(ADDR_MOD_BASE | ADDR_MOD_IDX | ADDR_MOD_DISP); } } }
//Checks opcode-extension prefixes (repz, repnz, opsize) are superfluous. static void check_ext_sf_prefixes(byte[] prefixes, ref INSTRUCTION instr, ref DISASM_INOUT_PARAMS param) { if (prefixes[PREF_OPSIZE_INDEX] != 0xFF) add_sf_prefix(prefixes, PREF_OPSIZE_INDEX, ref instr, ref param); if (prefixes[PREF_REP_INDEX] != 0xFF) add_sf_prefix(prefixes, PREF_OPSIZE_INDEX, ref instr, ref param); }
//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; }
//Checks if segment override prefix is superfluous. static void check_seg_sf_prefixes(INSTRUCTION instr, byte[] prefixes, DISASM_INOUT_PARAMS param) { uint i; bool mem_op_found = false; if (prefixes[PREF_SEG_INDEX] != 0xFF) { for (i = 0; i < 3; i++) { if ((instr.ops[i].flags & (byte)OP_TYPE.OPERAND_TYPE_MEM)!=0) { if (param.mode == DISMODE.DISASSEMBLE_MODE_64) { if ( !((prefixes[PREF_SEG_INDEX] == PREF_FS_ID) || (prefixes[PREF_SEG_INDEX] == PREF_GS_ID)) ) { add_sf_prefix(prefixes, PREF_SEG_INDEX, ref instr, ref param); } } else { if ( (instr.ops[i].value.addr.mod & ADDR_MOD_BASE)==0 ) { if (instr.ops[i].value.addr.seg == SREG_CODE_DS) add_sf_prefix(prefixes, PREF_SEG_INDEX, ref instr, ref param); } else { if ((instr.ops[i].value.addr.bas == REG_CODE_BP) || (instr.ops[i].value.addr.bas == REG_CODE_SP)) { if (instr.ops[i].value.addr.seg == SREG_CODE_SS) add_sf_prefix(prefixes, PREF_SEG_INDEX, ref instr, ref param); } else { if (instr.ops[i].value.addr.seg == SREG_CODE_DS) add_sf_prefix(prefixes, PREF_SEG_INDEX, ref instr, ref param); } } } mem_op_found = true; } } if (!mem_op_found) add_sf_prefix(prefixes, PREF_SEG_INDEX, ref instr, ref param); } }
//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; }
//Converts prefixes from internal to external representation. static void convert_prefixes(INSTRUCTION instr, byte[] prefixes) { for (int i = 0; i < PREFIX_COUNT; i++) { if (prefixes[i] != 0xFF) instr.prefixes |= pref_bits[prefixes[i]]; } }
//Copies MODRM and SIB bytes to struct INSTRUCTION. static byte parse_modrm_sib(ulong offset, ref INSTRUCTION instr, OPCODE_DESCRIPTOR opcode) { byte len = 0; if ((opcode.props & PROP_MODRM)!=0) { len++; instr.flags |= INSTR_FLAG_MODRM; //instr.modrm = *offset; instr.modrm = assembly.ReadBytes(offset, 1)[0]; if (instr.addrsize != ADDR_SIZE_16) { if ((instr.modrm & 0x7) == 0x4 && (instr.modrm & 0xC0) != 0xC0) { len++; instr.flags |= INSTR_FLAG_SIB; //instr.sib = offset[1]; instr.sib = instr.modrm = assembly.ReadBytes(offset, 2)[1]; } } } return len; }
static void copy_eflags(ref INSTRUCTION instr, ref OPCODE_DESCRIPTOR opcode) { instr.tested_flags = opcode.tested_flags; instr.modified_flags = opcode.modified_flags; instr.set_flags = opcode.set_flags; instr.cleared_flags = opcode.cleared_flags; instr.undefined_flags = opcode.undefined_flags; }
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; }
//Copies instruction's flags from struct OPCODE_DESCRIPTOR to struct INSTRUCTION. static void copy_instr_flags(ref INSTRUCTION instr, ref OPCODE_DESCRIPTOR opcode) { if ((opcode.props & PROP_IOPL)!=0) instr.flags |= INSTR_FLAG_IOPL; if ((opcode.props & PROP_RING0)!=0) instr.flags |= INSTR_FLAG_RING0; if ((opcode.props & PROP_SERIAL)!=0) instr.flags |= INSTR_FLAG_SERIAL; if ((opcode.props & PROP_UNDOC) != 0) instr.flags |= INSTR_FLAG_UNDOC; }
//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; }
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_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; }
//Creates OPERAND_TYPE_REG operand of given type. static void create_reg_operand(ref INSTRUCTION instr, int op_index, REG_TYPE type, byte code, OP_SIZE size) { instr.ops[op_index].flags |= (byte)OP_TYPE.OPERAND_TYPE_REG; instr.ops[op_index].value.reg.type = type; instr.ops[op_index].value.reg.code = code; instr.ops[op_index].size = (ushort)size; }
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 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 string dump_addr(INSTRUCTION instr, OPERAND op) { string res = "["; if ((op.value.addr.mod & ADDR_MOD_BASE)!=0) { res += dump_reg_gen(op.value.addr.bas, instr.addrsize); } if ((op.value.addr.mod & ADDR_MOD_IDX)!=0) { if ((op.value.addr.mod & ADDR_MOD_BASE)!=0) { res += "+"; } res += dump_reg_gen(op.value.addr.index, instr.addrsize); if (op.value.addr.scale != 0x1) { res += '*' + op.value.addr.scale.ToString("X"); } } if ((op.value.addr.mod & ADDR_MOD_DISP)!=0) { if ((op.value.addr.mod & ~ADDR_MOD_DISP)!=0) { res += '+'; } res += "0x"+instr.disp.value.d64.ToString("X"); } res += ']'; return res; }
//Returns address size. Address size is common for all operands. static void get_address_size(ref INSTRUCTION instr, byte[] prefixes, DISMODE mode) { if (mode == DISMODE.DISASSEMBLE_MODE_64) { if (prefixes[PREF_ADDRSIZE_INDEX] != 0xFF) instr.addrsize = ADDR_SIZE_32; else instr.addrsize = ADDR_SIZE_64; } else { if (prefixes[PREF_ADDRSIZE_INDEX] != 0xFF) mode ^= (DISMODE.DISASSEMBLE_MODE_16 | DISMODE.DISASSEMBLE_MODE_32); if (mode == DISMODE.DISASSEMBLE_MODE_16) instr.addrsize = ADDR_SIZE_16; else instr.addrsize = ADDR_SIZE_32; } }