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));