namespace X86Disassembler.X86.Handlers.String; /// /// Handler for string instructions (MOVS, STOS, LODS, SCAS) with and without REP/REPNE prefixes /// public class StringInstructionHandler : InstructionHandler { // Dictionary mapping opcodes to their mnemonics and operands private static readonly Dictionary StringInstructions = new() { { 0xA4, ("movs", "byte ptr [edi], byte ptr [esi]") }, // MOVSB { 0xA5, ("movs", "dword ptr [edi], dword ptr [esi]") }, // MOVSD { 0xAA, ("stos", "byte ptr [edi], al") }, // STOSB { 0xAB, ("stos", "dword ptr [edi], eax") }, // STOSD { 0xAC, ("lods", "al, byte ptr [esi]") }, // LODSB { 0xAD, ("lods", "eax, dword ptr [esi]") }, // LODSD { 0xAE, ("scas", "al, byte ptr [edi]") }, // SCASB { 0xAF, ("scas", "eax, dword ptr [edi]") } // SCASD }; // REP/REPNE prefix opcodes private const byte REP_PREFIX = 0xF3; private const byte REPNE_PREFIX = 0xF2; /// /// Initializes a new instance of the StringInstructionHandler class /// /// The buffer containing the code to decode /// The instruction decoder that owns this handler /// The length of the buffer public StringInstructionHandler(byte[] codeBuffer, InstructionDecoder decoder, int length) : base(codeBuffer, decoder, length) { } /// /// Checks if this handler can handle the given opcode /// /// The opcode to check /// True if this handler can handle the opcode public override bool CanHandle(byte opcode) { // Check if the opcode is a string instruction if (StringInstructions.ContainsKey(opcode)) { return true; } // Check if the opcode is a REP/REPNE prefix followed by a string instruction if (opcode != REP_PREFIX && opcode != REPNE_PREFIX) { return false; } if (!Decoder.CanReadByte()) { return false; } byte nextByte = CodeBuffer[Decoder.GetPosition()]; return StringInstructions.ContainsKey(nextByte); } /// /// Decodes a string instruction /// /// The opcode to decode /// The instruction to populate /// True if the instruction was successfully decoded public override bool Decode(byte opcode, Instruction instruction) { // Check if this is a REP/REPNE prefix bool hasRepPrefix = opcode == REP_PREFIX || opcode == REPNE_PREFIX; string prefixString = ""; // If this is a REP/REPNE prefix, get the actual string instruction opcode byte stringOpcode = opcode; if (hasRepPrefix) { // Set the prefix string based on the prefix opcode prefixString = opcode == REP_PREFIX ? "rep " : "repne "; // Read the next byte (the actual string instruction opcode) if (!Decoder.CanReadByte()) { return false; } stringOpcode = Decoder.ReadByte(); if (!StringInstructions.ContainsKey(stringOpcode)) { return false; } } // Get the mnemonic and operands for the string instruction if (StringInstructions.TryGetValue(stringOpcode, out var instructionInfo)) { // Set the mnemonic with the prefix if present instruction.Mnemonic = prefixString + instructionInfo.Mnemonic; // Set the operands instruction.Operands = instructionInfo.Operands; return true; } // This shouldn't happen if CanHandle is called first return false; } }