diff --git a/X86Disassembler/X86/Handlers/Add/AddImmToRm16Handler.cs b/X86Disassembler/X86/Handlers/Add/AddImmToRm16Handler.cs
new file mode 100644
index 0000000..f8baeda
--- /dev/null
+++ b/X86Disassembler/X86/Handlers/Add/AddImmToRm16Handler.cs
@@ -0,0 +1,83 @@
+using X86Disassembler.X86.Operands;
+
+namespace X86Disassembler.X86.Handlers.Add;
+
+///
+/// Handler for ADD r/m16, imm16 instruction (opcode 81 /0 with 0x66 prefix)
+///
+public class AddImmToRm16Handler : InstructionHandler
+{
+ ///
+ /// Initializes a new instance of the AddImmToRm16Handler class
+ ///
+ /// The instruction decoder that owns this handler
+ public AddImmToRm16Handler(InstructionDecoder decoder)
+ : base(decoder)
+ {
+ }
+
+ ///
+ /// 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)
+ {
+ // ADD r/m16, imm16 is encoded as 0x81 with 0x66 prefix
+ if (opcode != 0x81)
+ {
+ return false;
+ }
+
+ // Only handle when the operand size prefix is present
+ if (!Decoder.HasOperandSizePrefix())
+ return false;
+
+ // Check if the reg field of the ModR/M byte is 0 (ADD)
+ if (!Decoder.CanReadByte())
+ return false;
+
+ var reg = ModRMDecoder.PeakModRMReg();
+
+ return reg == 0; // 0 = ADD
+ }
+
+ ///
+ /// Decodes a ADD r/m16, imm16 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 instruction type
+ instruction.Type = InstructionType.Add;
+
+ // Check if we can read the ModR/M byte
+ if (!Decoder.CanReadByte())
+ {
+ return false;
+ }
+
+ // Read the ModR/M byte
+ var (_, _, _, destOperand) = ModRMDecoder.ReadModRM16();
+
+ // Check if we have enough bytes for the immediate value
+ if (!Decoder.CanReadUShort())
+ {
+ return false;
+ }
+
+ // Read the immediate value
+ ushort imm16 = Decoder.ReadUInt16();
+
+ // Set the structured operands
+ instruction.StructuredOperands =
+ [
+ destOperand,
+ OperandFactory.CreateImmediateOperand(imm16)
+ ];
+
+ return true;
+ }
+}
diff --git a/X86Disassembler/X86/Handlers/Add/AddImmToRm16SignExtendedHandler.cs b/X86Disassembler/X86/Handlers/Add/AddImmToRm16SignExtendedHandler.cs
new file mode 100644
index 0000000..6920065
--- /dev/null
+++ b/X86Disassembler/X86/Handlers/Add/AddImmToRm16SignExtendedHandler.cs
@@ -0,0 +1,85 @@
+using X86Disassembler.X86.Operands;
+
+namespace X86Disassembler.X86.Handlers.Add;
+
+///
+/// Handler for ADD r/m16, imm8 instruction (opcode 83 /0 with 0x66 prefix)
+///
+public class AddImmToRm16SignExtendedHandler : InstructionHandler
+{
+ ///
+ /// Initializes a new instance of the AddImmToRm16SignExtendedHandler class
+ ///
+ /// The instruction decoder that owns this handler
+ public AddImmToRm16SignExtendedHandler(InstructionDecoder decoder)
+ : base(decoder)
+ {
+ }
+
+ ///
+ /// 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)
+ {
+ // ADD r/m16, imm8 is encoded as 0x83 with 0x66 prefix
+ if (opcode != 0x83)
+ {
+ return false;
+ }
+
+ // Only handle when the operand size prefix is present
+ if (!Decoder.HasOperandSizePrefix())
+ return false;
+
+ // Check if the reg field of the ModR/M byte is 0 (ADD)
+ if (!Decoder.CanReadByte())
+ return false;
+
+ var reg = ModRMDecoder.PeakModRMReg();
+
+ return reg == 0; // 0 = ADD
+ }
+
+ ///
+ /// Decodes a ADD r/m16, imm8 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 instruction type
+ instruction.Type = InstructionType.Add;
+
+ // Check if we can read the ModR/M byte
+ if (!Decoder.CanReadByte())
+ {
+ return false;
+ }
+
+ // Read the ModR/M byte
+ var (_, _, _, destOperand) = ModRMDecoder.ReadModRM16();
+
+ // Check if we have enough bytes for the immediate value
+ if (!Decoder.CanRead(1))
+ {
+ return false;
+ }
+
+ // Read the immediate value (sign-extended from 8-bit to 16-bit)
+ sbyte imm8 = (sbyte)Decoder.ReadByte();
+ short signExtendedImm = imm8;
+ uint immValue = (ushort)signExtendedImm; // Convert to uint for the operand factory
+
+ // Set the structured operands
+ instruction.StructuredOperands =
+ [
+ destOperand,
+ OperandFactory.CreateImmediateOperand(immValue)
+ ];
+
+ return true;
+ }
+}
diff --git a/X86Disassembler/X86/Handlers/InstructionHandlerFactory.cs b/X86Disassembler/X86/Handlers/InstructionHandlerFactory.cs
index 2fca9b4..d749d48 100644
--- a/X86Disassembler/X86/Handlers/InstructionHandlerFactory.cs
+++ b/X86Disassembler/X86/Handlers/InstructionHandlerFactory.cs
@@ -292,20 +292,22 @@ public class InstructionHandlerFactory
///
private void RegisterAddHandlers()
{
- // Add ADD handlers
- _handlers.Add(new AddR32Rm32Handler(_decoder));
- _handlers.Add(new AddRm32R32Handler(_decoder));
- _handlers.Add(new AddEaxImmHandler(_decoder));
+ // Add ADD register-to-register handlers (32-bit)
+ _handlers.Add(new AddR32Rm32Handler(_decoder)); // ADD r32, r/m32 (opcode 03)
+ _handlers.Add(new AddRm32R32Handler(_decoder)); // ADD r/m32, r32 (opcode 01)
+ _handlers.Add(new AddEaxImmHandler(_decoder)); // ADD EAX, imm32 (opcode 05)
- // Add 8-bit ADD handlers
- _handlers.Add(new AddRm8R8Handler(_decoder)); // ADD r/m8, r8 (opcode 00)
- _handlers.Add(new AddR8Rm8Handler(_decoder)); // ADD r8, r/m8 (opcode 02)
- _handlers.Add(new AddAlImmHandler(_decoder)); // ADD AL, imm8 (opcode 04)
+ // Add ADD register-to-register handlers (8-bit)
+ _handlers.Add(new AddRm8R8Handler(_decoder)); // ADD r/m8, r8 (opcode 00)
+ _handlers.Add(new AddR8Rm8Handler(_decoder)); // ADD r8, r/m8 (opcode 02)
+ _handlers.Add(new AddAlImmHandler(_decoder)); // ADD AL, imm8 (opcode 04)
- // Add ADD immediate handlers from ArithmeticImmediate namespace
- _handlers.Add(new AddImmToRm8Handler(_decoder));
- _handlers.Add(new AddImmToRm32Handler(_decoder));
- _handlers.Add(new AddImmToRm32SignExtendedHandler(_decoder));
+ // Add ADD immediate handlers
+ _handlers.Add(new AddImmToRm8Handler(_decoder)); // ADD r/m8, imm8 (opcode 80 /0)
+ _handlers.Add(new AddImmToRm16Handler(_decoder)); // ADD r/m16, imm16 (opcode 81 /0 with 0x66 prefix)
+ _handlers.Add(new AddImmToRm16SignExtendedHandler(_decoder)); // ADD r/m16, imm8 (opcode 83 /0 with 0x66 prefix)
+ _handlers.Add(new AddImmToRm32Handler(_decoder)); // ADD r/m32, imm32 (opcode 81 /0)
+ _handlers.Add(new AddImmToRm32SignExtendedHandler(_decoder)); // ADD r/m32, imm8 (opcode 83 /0)
}
///