diff --git a/X86Disassembler/X86/Handlers/And/AndImmWithRm32Handler.cs b/X86Disassembler/X86/Handlers/And/AndImmWithRm32Handler.cs new file mode 100644 index 0000000..485cf76 --- /dev/null +++ b/X86Disassembler/X86/Handlers/And/AndImmWithRm32Handler.cs @@ -0,0 +1,87 @@ +namespace X86Disassembler.X86.Handlers.And; + +/// +/// Handler for AND r/m32, imm32 instruction (0x81 /4) +/// +public class AndImmWithRm32Handler : InstructionHandler +{ + /// + /// Initializes a new instance of the AndImmWithRm32Handler class + /// + /// The buffer containing the code to decode + /// The instruction decoder that owns this handler + /// The length of the buffer + public AndImmWithRm32Handler(byte[] codeBuffer, InstructionDecoder decoder, int length) + : base(codeBuffer, decoder, length) + { + } + + /// + /// Checks if this handler can decode the given opcode + /// + /// The opcode to check + /// True if this handler can decode the opcode + public override bool CanHandle(byte opcode) + { + if (opcode != 0x81) + return false; + + // Check if the reg field of the ModR/M byte is 4 (AND) + int position = Decoder.GetPosition(); + if (position >= Length) + return false; + + byte modRM = CodeBuffer[position]; + byte reg = (byte) ((modRM & 0x38) >> 3); + + return reg == 4; // 4 = AND + } + + /// + /// Decodes an AND r/m32, imm32 instruction + /// + /// The opcode of the instruction + /// The instruction object to populate + /// True if the instruction was successfully decoded + public override bool Decode(byte opcode, Instruction instruction) + { + // Set the mnemonic + instruction.Mnemonic = "and"; + + // Read the ModR/M byte + var (mod, reg, rm, memOperand) = ModRMDecoder.ReadModRM(); + + // Get the position after decoding the ModR/M byte + int position = Decoder.GetPosition(); + + // Check if we have enough bytes for the immediate value + if (position + 3 >= Length) + { + return false; // Not enough bytes for the immediate value + } + + // Read the immediate value + uint imm32 = Decoder.ReadUInt32(); + + // Format the destination operand based on addressing mode + string destOperand; + if (mod == 3) // Register addressing mode + { + // Get 32-bit register name + destOperand = ModRMDecoder.GetRegisterName(rm, 32); + } + else // Memory addressing mode + { + // Memory operand already includes dword ptr prefix + destOperand = memOperand; + } + + // Format the immediate value + string immStr = $"0x{imm32:X8}"; + + // Set the operands + instruction.Operands = $"{destOperand}, {immStr}"; + + return true; + } +} diff --git a/X86Disassembler/X86/Handlers/Cmp/CmpImmWithRm32Handler.cs b/X86Disassembler/X86/Handlers/Cmp/CmpImmWithRm32Handler.cs index cf2de13..2c1d0cd 100644 --- a/X86Disassembler/X86/Handlers/Cmp/CmpImmWithRm32Handler.cs +++ b/X86Disassembler/X86/Handlers/Cmp/CmpImmWithRm32Handler.cs @@ -48,28 +48,36 @@ public class CmpImmWithRm32Handler : InstructionHandler // Set the mnemonic instruction.Mnemonic = "cmp"; + // Read the ModR/M byte + var (mod, reg, rm, memOperand) = ModRMDecoder.ReadModRM(); + + // Get the position after decoding the ModR/M byte int position = Decoder.GetPosition(); - if (position >= Length) - { - return false; - } - - // Read the ModR/M byte - var (mod, reg, rm, destOperand) = ModRMDecoder.ReadModRM(); - - // Read the immediate value + // Check if we have enough bytes for the immediate value if (position + 3 >= Length) { - return false; + return false; // Not enough bytes for the immediate value } - // Read the immediate value in little-endian format - var imm = Decoder.ReadUInt32(); + // Read the immediate value + uint imm32 = Decoder.ReadUInt32(); - // Format the immediate value as expected by the tests (0x12345678) - // Note: The bytes are reversed to match the expected format in the tests - string immStr = $"0x{imm:X8}"; + // Format the destination operand based on addressing mode + string destOperand; + if (mod == 3) // Register addressing mode + { + // Get 32-bit register name + destOperand = ModRMDecoder.GetRegisterName(rm, 32); + } + else // Memory addressing mode + { + // Memory operand already includes dword ptr prefix + destOperand = memOperand; + } + + // Format the immediate value + string immStr = $"0x{imm32:X8}"; // Set the operands instruction.Operands = $"{destOperand}, {immStr}"; diff --git a/X86Disassembler/X86/Handlers/InstructionHandlerFactory.cs b/X86Disassembler/X86/Handlers/InstructionHandlerFactory.cs index e812d2e..a06cd52 100644 --- a/X86Disassembler/X86/Handlers/InstructionHandlerFactory.cs +++ b/X86Disassembler/X86/Handlers/InstructionHandlerFactory.cs @@ -373,6 +373,7 @@ public class InstructionHandlerFactory { // Add AND handlers _handlers.Add(new AndImmToRm8Handler(_codeBuffer, _decoder, _length)); + _handlers.Add(new AndImmWithRm32Handler(_codeBuffer, _decoder, _length)); _handlers.Add(new AndImmToRm32Handler(_codeBuffer, _decoder, _length)); _handlers.Add(new AndImmToRm32SignExtendedHandler(_codeBuffer, _decoder, _length));