/// <summary> /// Writes an instruction to the output stream. /// </summary> /// <param name="instruction">The instruction to write.</param> public void Write(X86Instruction instruction) { var opcode = instruction.OpCode; WriteOpCode(opcode); var mnemonicIndex = Array.IndexOf(opcode.Mnemonics, instruction.Mnemonic); if (mnemonicIndex == -1) throw new ArgumentException("Instruction's mnemonic is not supported by its opcode."); if (opcode.HasRegisterToken) { var token = (byte)(ComputeRegisterTokenPart(opcode.OperandTypes1[mnemonicIndex], opcode.OperandSizes1[mnemonicIndex], instruction.Operand1) | ComputeRegisterTokenPart(opcode.OperandTypes2[mnemonicIndex], opcode.OperandSizes2[mnemonicIndex], instruction.Operand2)); if (opcode.HasOpCodeModifier) { token |= (byte)(mnemonicIndex << 3); } _writer.WriteByte(token); } if (instruction.Operand1 != null) { WriteOperand(opcode.OperandTypes1[mnemonicIndex], opcode.OperandSizes1[mnemonicIndex], instruction.Operand1); if (instruction.Operand2 != null) { WriteOperand(opcode.OperandTypes2[mnemonicIndex], opcode.OperandSizes2[mnemonicIndex], instruction.Operand2); } } }
/// <summary> /// Disassembles the next instruction of the input stream. /// </summary> /// <returns>The disassembled instruction.</returns> public X86Instruction ReadNextInstruction() { long offset = BaseAddress + _reader.Position; byte code1 = _reader.ReadByte(); var instruction = new X86Instruction(offset) { OpCode = ReadOpcode(code1) }; if (instruction.OpCode.Mnemonics == null) { instruction.Operand1 = new X86Operand(code1); return instruction; } var registerToken = instruction.OpCode.HasRegisterToken ? _reader.ReadByte() : (byte)0; var mnemonicIndex = instruction.OpCode.HasOpCodeModifier ? (registerToken >> 3) & 7 : 0; instruction.Mnemonic = instruction.OpCode.Mnemonics[mnemonicIndex]; instruction.Operand1 = ReadOperand(instruction.OpCode.OperandTypes1[mnemonicIndex], instruction.OpCode.OperandSizes1[mnemonicIndex], instruction.OpCode.Op1, registerToken); instruction.Operand2 = ReadOperand(instruction.OpCode.OperandTypes2[mnemonicIndex], instruction.OpCode.OperandSizes2[mnemonicIndex], instruction.OpCode.Op1, registerToken); return instruction; }
private static IEnumerable<X86Instruction> CreateOpCodeRegisterTokenTestInstructions() { var opcode = X86OpCodes.Arithmetic_RegOrMem8_Imm8; for (int index = 0; index < opcode.Mnemonics.Length; index++) { var mnemonic = opcode.Mnemonics[index]; var instruction = new X86Instruction() { OpCode = opcode, Mnemonic = mnemonic, Operand1 = new X86Operand(X86OperandUsage.BytePointer, 0x1337u), Operand2 = new X86Operand((byte)index), }; yield return instruction; } }
private static IEnumerable<X86Instruction> CreateRegOrMemSibTestInstructions(X86OpCode opcode, X86Mnemonic mnemonic) { for (int operandType = 0; operandType < 3; operandType++) { for (int multiplier = 1; multiplier < 16; multiplier*=2) { for (int scaledRegIndex = 0; scaledRegIndex < 8; scaledRegIndex++) { if (scaledRegIndex == 4) continue; var operand1 = new X86Operand(X86OperandUsage.BytePointer, X86Register.Eax, new X86ScaledIndex((X86Register)scaledRegIndex | X86Register.Eax, multiplier)); var operand2 = new X86Operand(X86OperandUsage.Normal, X86Register.Al); var instruction = new X86Instruction() { OpCode = opcode, Mnemonic = mnemonic, Operand1 = operand1, Operand2 = operand2, }; switch (operandType) { case 1: operand1.Offset = 1; operand1.OffsetType = X86OffsetType.Short; break; case 2: operand1.Offset = 0x1337; operand1.OffsetType = X86OffsetType.Long; break; } yield return instruction; } } } }
private static IEnumerable<X86Instruction> CreateRegOrMemTestInstructions(X86OpCode opcode, X86Mnemonic mnemonic, bool flippedOperands) { for (int operandType = 0; operandType < 3; operandType++) { for (int register2Index = 0; register2Index < 8; register2Index++) { for (int register1Index = 0; register1Index < 8; register1Index++) { var operand1 = new X86Operand(X86OperandUsage.BytePointer, (X86Register)register1Index | X86Register.Eax); var operand2 = new X86Operand(X86OperandUsage.Normal, (X86Register)register2Index); var instruction = new X86Instruction() { OpCode = opcode, Mnemonic = mnemonic, }; if (flippedOperands) { instruction.Operand2 = operand1; instruction.Operand1 = operand2; } else { instruction.Operand1 = operand1; instruction.Operand2 = operand2; } switch (register1Index) { case 4: // esp continue; case 5: // ebp if (operandType != 0) continue; operand1.Value = 0x1337u; break; } switch (operandType) { case 1: operand1.Offset = 1; operand1.OffsetType = X86OffsetType.Short; break; case 2: operand1.Offset = 0x1337; operand1.OffsetType = X86OffsetType.Long; break; } yield return instruction; } } } }
/// <summary> /// Formats an instruction to a readable string. /// </summary> /// <param name="formatter">The formatter to use.</param> /// <param name="instruction">The isntruction to format.</param> /// <returns>The formatted operand.</returns> public static string FormatInstruction(this IX86Formatter formatter, X86Instruction instruction) { var mnemonicString = formatter.FormatMnemonic(instruction.Mnemonic); if (instruction.Operand2 == null) { return instruction.Operand1 == null ? mnemonicString : mnemonicString + ' ' + formatter.FormatOperand(instruction.Operand1); } return mnemonicString + ' ' + formatter.FormatOperand(instruction.Operand1) + ", " + formatter.FormatOperand(instruction.Operand2); }
public X86InstructionListViewItem(X86Instruction instruction, byte[] bytes) { Instruction = instruction; Bytes = bytes; }