From 79bf419c07b7a778ca4d0161d69116dc3f82a8e3 Mon Sep 17 00:00:00 2001 From: bird_egop Date: Sun, 13 Apr 2025 02:23:27 +0300 Subject: [PATCH] Consolidated string instruction handling by enhancing StringInstructionHandler to handle both regular and REP/REPNE prefixed instructions --- .../X86/Handlers/InstructionHandlerFactory.cs | 3 +- .../String/StringInstructionHandler.cs | 56 +++++++++++++++++-- 2 files changed, 51 insertions(+), 8 deletions(-) diff --git a/X86Disassembler/X86/Handlers/InstructionHandlerFactory.cs b/X86Disassembler/X86/Handlers/InstructionHandlerFactory.cs index 2494279..25ddf6e 100644 --- a/X86Disassembler/X86/Handlers/InstructionHandlerFactory.cs +++ b/X86Disassembler/X86/Handlers/InstructionHandlerFactory.cs @@ -305,8 +305,7 @@ public class InstructionHandlerFactory /// private void RegisterStringHandlers() { - // Add String instruction handlers - _handlers.Add(new RepMovsHandler(_codeBuffer, _decoder, _length)); + // Add String instruction handler that handles both regular and REP/REPNE prefixed string instructions _handlers.Add(new StringInstructionHandler(_codeBuffer, _decoder, _length)); } diff --git a/X86Disassembler/X86/Handlers/String/StringInstructionHandler.cs b/X86Disassembler/X86/Handlers/String/StringInstructionHandler.cs index a7b529b..ac26821 100644 --- a/X86Disassembler/X86/Handlers/String/StringInstructionHandler.cs +++ b/X86Disassembler/X86/Handlers/String/StringInstructionHandler.cs @@ -1,7 +1,7 @@ namespace X86Disassembler.X86.Handlers.String; /// -/// Handler for string instructions (MOVS, STOS, LODS, SCAS) +/// Handler for string instructions (MOVS, STOS, LODS, SCAS) with and without REP/REPNE prefixes /// public class StringInstructionHandler : InstructionHandler { @@ -18,6 +18,10 @@ public class StringInstructionHandler : InstructionHandler { 0xAF, "scas" } // 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 /// @@ -37,7 +41,23 @@ public class StringInstructionHandler : InstructionHandler public override bool CanHandle(byte opcode) { // Check if the opcode is a string instruction - return _mnemonics.ContainsKey(opcode); + if (_mnemonics.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) + { + int position = Decoder.GetPosition(); + if (position < Length) + { + byte nextByte = CodeBuffer[position]; + return _mnemonics.ContainsKey(nextByte); + } + } + + return false; } /// @@ -48,10 +68,34 @@ public class StringInstructionHandler : InstructionHandler /// True if the instruction was successfully decoded public override bool Decode(byte opcode, Instruction instruction) { - // Set the mnemonic - if (_mnemonics.TryGetValue(opcode, out string? mnemonic)) + // Check if this is a REP/REPNE prefix + bool hasRepPrefix = opcode == REP_PREFIX || opcode == REPNE_PREFIX; + string prefixString = opcode == REP_PREFIX ? "rep " : (opcode == REPNE_PREFIX ? "repne " : ""); + + // If this is a REP/REPNE prefix, get the actual string instruction opcode + byte stringOpcode = opcode; + if (hasRepPrefix) { - instruction.Mnemonic = mnemonic; + int position = Decoder.GetPosition(); + if (position >= Length) + { + return false; + } + + stringOpcode = CodeBuffer[position]; + if (!_mnemonics.ContainsKey(stringOpcode)) + { + return false; + } + + // Skip the string instruction opcode + Decoder.SetPosition(position + 1); + } + + // Set the mnemonic + if (_mnemonics.TryGetValue(stringOpcode, out string? mnemonic)) + { + instruction.Mnemonic = prefixString + mnemonic; } else { @@ -60,7 +104,7 @@ public class StringInstructionHandler : InstructionHandler } // Set the operands based on the string operation - switch (opcode) + switch (stringOpcode) { case 0xA4: // MOVSB instruction.Operands = "byte ptr [edi], byte ptr [esi]";