0
mirror of https://github.com/sampletext32/ParkanPlayground.git synced 2025-05-21 12:51:18 +03:00

Consolidated string instruction handling by enhancing StringInstructionHandler to handle both regular and REP/REPNE prefixed instructions

This commit is contained in:
bird_egop 2025-04-13 02:23:27 +03:00
parent efd9141b39
commit 79bf419c07
2 changed files with 51 additions and 8 deletions

View File

@ -305,8 +305,7 @@ public class InstructionHandlerFactory
/// </summary> /// </summary>
private void RegisterStringHandlers() private void RegisterStringHandlers()
{ {
// Add String instruction handlers // Add String instruction handler that handles both regular and REP/REPNE prefixed string instructions
_handlers.Add(new RepMovsHandler(_codeBuffer, _decoder, _length));
_handlers.Add(new StringInstructionHandler(_codeBuffer, _decoder, _length)); _handlers.Add(new StringInstructionHandler(_codeBuffer, _decoder, _length));
} }

View File

@ -1,7 +1,7 @@
namespace X86Disassembler.X86.Handlers.String; namespace X86Disassembler.X86.Handlers.String;
/// <summary> /// <summary>
/// Handler for string instructions (MOVS, STOS, LODS, SCAS) /// Handler for string instructions (MOVS, STOS, LODS, SCAS) with and without REP/REPNE prefixes
/// </summary> /// </summary>
public class StringInstructionHandler : InstructionHandler public class StringInstructionHandler : InstructionHandler
{ {
@ -18,6 +18,10 @@ public class StringInstructionHandler : InstructionHandler
{ 0xAF, "scas" } // SCASD { 0xAF, "scas" } // SCASD
}; };
// REP/REPNE prefix opcodes
private const byte REP_PREFIX = 0xF3;
private const byte REPNE_PREFIX = 0xF2;
/// <summary> /// <summary>
/// Initializes a new instance of the StringInstructionHandler class /// Initializes a new instance of the StringInstructionHandler class
/// </summary> /// </summary>
@ -37,7 +41,23 @@ public class StringInstructionHandler : InstructionHandler
public override bool CanHandle(byte opcode) public override bool CanHandle(byte opcode)
{ {
// Check if the opcode is a string instruction // 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;
} }
/// <summary> /// <summary>
@ -48,10 +68,34 @@ public class StringInstructionHandler : InstructionHandler
/// <returns>True if the instruction was successfully decoded</returns> /// <returns>True if the instruction was successfully decoded</returns>
public override bool Decode(byte opcode, Instruction instruction) public override bool Decode(byte opcode, Instruction instruction)
{ {
// Set the mnemonic // Check if this is a REP/REPNE prefix
if (_mnemonics.TryGetValue(opcode, out string? mnemonic)) 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 else
{ {
@ -60,7 +104,7 @@ public class StringInstructionHandler : InstructionHandler
} }
// Set the operands based on the string operation // Set the operands based on the string operation
switch (opcode) switch (stringOpcode)
{ {
case 0xA4: // MOVSB case 0xA4: // MOVSB
instruction.Operands = "byte ptr [edi], byte ptr [esi]"; instruction.Operands = "byte ptr [edi], byte ptr [esi]";