diff --git a/X86DisassemblerTests/CallInstructionTests.cs b/X86DisassemblerTests/CallInstructionTests.cs
new file mode 100644
index 0000000..1e87a0f
--- /dev/null
+++ b/X86DisassemblerTests/CallInstructionTests.cs
@@ -0,0 +1,32 @@
+namespace X86DisassemblerTests;
+
+using System;
+using Xunit;
+using X86Disassembler.X86;
+using X86Disassembler.X86.Handlers;
+
+///
+/// Tests for call instruction handlers
+///
+public class CallInstructionTests
+{
+ ///
+ /// Tests the CallRel32Handler for decoding CALL rel32 instruction
+ ///
+ [Fact]
+ public void CallRel32Handler_DecodesCallRel32_Correctly()
+ {
+ // Arrange
+ // CALL +0x12345678 (E8 78 56 34 12) - Call to address 0x12345678 bytes forward
+ byte[] codeBuffer = new byte[] { 0xE8, 0x78, 0x56, 0x34, 0x12 };
+ var decoder = new InstructionDecoder(codeBuffer, codeBuffer.Length);
+
+ // Act
+ var instruction = decoder.DecodeInstruction();
+
+ // Assert
+ Assert.NotNull(instruction);
+ Assert.Equal("call", instruction.Mnemonic);
+ Assert.Equal("0x1234567D", instruction.Operands); // Current position (5) + offset (0x12345678) = 0x1234567D
+ }
+}
diff --git a/X86DisassemblerTests/Group1InstructionTests.cs b/X86DisassemblerTests/Group1InstructionTests.cs
new file mode 100644
index 0000000..285ee5b
--- /dev/null
+++ b/X86DisassemblerTests/Group1InstructionTests.cs
@@ -0,0 +1,117 @@
+namespace X86DisassemblerTests;
+
+using System;
+using Xunit;
+using X86Disassembler.X86;
+using X86Disassembler.X86.Handlers.Group1;
+
+///
+/// Tests for Group1 instruction handlers
+///
+public class Group1InstructionTests
+{
+ ///
+ /// Tests the AddImmToRm8Handler for decoding ADD r/m8, imm8 instruction
+ ///
+ [Fact]
+ public void AddImmToRm8Handler_DecodesAddRm8Imm8_Correctly()
+ {
+ // Arrange
+ // ADD AL, 0x42 (80 C0 42) - ModR/M byte C0 = 11 000 000 (mod=3, reg=0, rm=0)
+ // mod=3 means direct register addressing, reg=0 indicates ADD operation, rm=0 is AL
+ byte[] codeBuffer = new byte[] { 0x80, 0xC0, 0x42 };
+ var decoder = new InstructionDecoder(codeBuffer, codeBuffer.Length);
+
+ // Act
+ var instruction = decoder.DecodeInstruction();
+
+ // Assert
+ Assert.NotNull(instruction);
+ Assert.Equal("add", instruction.Mnemonic);
+ Assert.Equal("al, 0x42", instruction.Operands);
+ }
+
+ ///
+ /// Tests the AddImmToRm32Handler for decoding ADD r/m32, imm32 instruction
+ ///
+ [Fact]
+ public void AddImmToRm32Handler_DecodesAddRm32Imm32_Correctly()
+ {
+ // Arrange
+ // ADD ECX, 0x12345678 (81 C1 78 56 34 12) - ModR/M byte C1 = 11 000 001 (mod=3, reg=0, rm=1)
+ // mod=3 means direct register addressing, reg=0 indicates ADD operation, rm=1 is ECX
+ byte[] codeBuffer = new byte[] { 0x81, 0xC1, 0x78, 0x56, 0x34, 0x12 };
+ var decoder = new InstructionDecoder(codeBuffer, codeBuffer.Length);
+
+ // Act
+ var instruction = decoder.DecodeInstruction();
+
+ // Assert
+ Assert.NotNull(instruction);
+ Assert.Equal("add", instruction.Mnemonic);
+ Assert.Equal("ecx, 0x12345678", instruction.Operands);
+ }
+
+ ///
+ /// Tests the OrImmToRm8Handler for decoding OR r/m8, imm8 instruction
+ ///
+ [Fact]
+ public void OrImmToRm8Handler_DecodesOrRm8Imm8_Correctly()
+ {
+ // Arrange
+ // OR BL, 0x42 (80 CB 42) - ModR/M byte CB = 11 001 011 (mod=3, reg=1, rm=3)
+ // mod=3 means direct register addressing, reg=1 indicates OR operation, rm=3 is BL
+ byte[] codeBuffer = new byte[] { 0x80, 0xCB, 0x42 };
+ var decoder = new InstructionDecoder(codeBuffer, codeBuffer.Length);
+
+ // Act
+ var instruction = decoder.DecodeInstruction();
+
+ // Assert
+ Assert.NotNull(instruction);
+ Assert.Equal("or", instruction.Mnemonic);
+ Assert.Equal("bl, 0x42", instruction.Operands);
+ }
+
+ ///
+ /// Tests the SubImmFromRm32Handler for decoding SUB r/m32, imm32 instruction
+ ///
+ [Fact]
+ public void SubImmFromRm32Handler_DecodesSubRm32Imm32_Correctly()
+ {
+ // Arrange
+ // SUB EDX, 0x12345678 (81 EA 78 56 34 12) - ModR/M byte EA = 11 101 010 (mod=3, reg=5, rm=2)
+ // mod=3 means direct register addressing, reg=5 indicates SUB operation, rm=2 is EDX
+ byte[] codeBuffer = new byte[] { 0x81, 0xEA, 0x78, 0x56, 0x34, 0x12 };
+ var decoder = new InstructionDecoder(codeBuffer, codeBuffer.Length);
+
+ // Act
+ var instruction = decoder.DecodeInstruction();
+
+ // Assert
+ Assert.NotNull(instruction);
+ Assert.Equal("sub", instruction.Mnemonic);
+ Assert.Equal("edx, 0x12345678", instruction.Operands);
+ }
+
+ ///
+ /// Tests the CmpImmWithRm32Handler for decoding CMP r/m32, imm32 instruction
+ ///
+ [Fact]
+ public void CmpImmWithRm32Handler_DecodesCmpRm32Imm32_Correctly()
+ {
+ // Arrange
+ // CMP EBX, 0x12345678 (81 FB 78 56 34 12) - ModR/M byte FB = 11 111 011 (mod=3, reg=7, rm=3)
+ // mod=3 means direct register addressing, reg=7 indicates CMP operation, rm=3 is EBX
+ byte[] codeBuffer = new byte[] { 0x81, 0xFB, 0x78, 0x56, 0x34, 0x12 };
+ var decoder = new InstructionDecoder(codeBuffer, codeBuffer.Length);
+
+ // Act
+ var instruction = decoder.DecodeInstruction();
+
+ // Assert
+ Assert.NotNull(instruction);
+ Assert.Equal("cmp", instruction.Mnemonic);
+ Assert.Equal("ebx, 0x12345678", instruction.Operands);
+ }
+}
diff --git a/X86DisassemblerTests/Group3InstructionTests.cs b/X86DisassemblerTests/Group3InstructionTests.cs
new file mode 100644
index 0000000..69555b5
--- /dev/null
+++ b/X86DisassemblerTests/Group3InstructionTests.cs
@@ -0,0 +1,138 @@
+namespace X86DisassemblerTests;
+
+using System;
+using Xunit;
+using X86Disassembler.X86;
+using X86Disassembler.X86.Handlers.Group3;
+
+///
+/// Tests for Group3 instruction handlers
+///
+public class Group3InstructionTests
+{
+ ///
+ /// Tests the NotRm32Handler for decoding NOT r/m32 instruction
+ ///
+ [Fact]
+ public void NotRm32Handler_DecodesNotRm32_Correctly()
+ {
+ // Arrange
+ // NOT EAX (F7 D0) - ModR/M byte D0 = 11 010 000 (mod=3, reg=2, rm=0)
+ // mod=3 means direct register addressing, reg=2 indicates NOT operation, rm=0 is EAX
+ byte[] codeBuffer = new byte[] { 0xF7, 0xD0 };
+ var decoder = new InstructionDecoder(codeBuffer, codeBuffer.Length);
+
+ // Act
+ var instruction = decoder.DecodeInstruction();
+
+ // Assert
+ Assert.NotNull(instruction);
+ Assert.Equal("not", instruction.Mnemonic);
+ Assert.Equal("eax", instruction.Operands);
+ }
+
+ ///
+ /// Tests the NegRm32Handler for decoding NEG r/m32 instruction
+ ///
+ [Fact]
+ public void NegRm32Handler_DecodesNegRm32_Correctly()
+ {
+ // Arrange
+ // NEG ECX (F7 D9) - ModR/M byte D9 = 11 011 001 (mod=3, reg=3, rm=1)
+ // mod=3 means direct register addressing, reg=3 indicates NEG operation, rm=1 is ECX
+ byte[] codeBuffer = new byte[] { 0xF7, 0xD9 };
+ var decoder = new InstructionDecoder(codeBuffer, codeBuffer.Length);
+
+ // Act
+ var instruction = decoder.DecodeInstruction();
+
+ // Assert
+ Assert.NotNull(instruction);
+ Assert.Equal("neg", instruction.Mnemonic);
+ Assert.Equal("ecx", instruction.Operands);
+ }
+
+ ///
+ /// Tests the MulRm32Handler for decoding MUL r/m32 instruction
+ ///
+ [Fact]
+ public void MulRm32Handler_DecodesMulRm32_Correctly()
+ {
+ // Arrange
+ // MUL EDX (F7 E2) - ModR/M byte E2 = 11 100 010 (mod=3, reg=4, rm=2)
+ // mod=3 means direct register addressing, reg=4 indicates MUL operation, rm=2 is EDX
+ byte[] codeBuffer = new byte[] { 0xF7, 0xE2 };
+ var decoder = new InstructionDecoder(codeBuffer, codeBuffer.Length);
+
+ // Act
+ var instruction = decoder.DecodeInstruction();
+
+ // Assert
+ Assert.NotNull(instruction);
+ Assert.Equal("mul", instruction.Mnemonic);
+ Assert.Equal("edx", instruction.Operands);
+ }
+
+ ///
+ /// Tests the ImulRm32Handler for decoding IMUL r/m32 instruction
+ ///
+ [Fact]
+ public void ImulRm32Handler_DecodesImulRm32_Correctly()
+ {
+ // Arrange
+ // IMUL EBX (F7 EB) - ModR/M byte EB = 11 101 011 (mod=3, reg=5, rm=3)
+ // mod=3 means direct register addressing, reg=5 indicates IMUL operation, rm=3 is EBX
+ byte[] codeBuffer = new byte[] { 0xF7, 0xEB };
+ var decoder = new InstructionDecoder(codeBuffer, codeBuffer.Length);
+
+ // Act
+ var instruction = decoder.DecodeInstruction();
+
+ // Assert
+ Assert.NotNull(instruction);
+ Assert.Equal("imul", instruction.Mnemonic);
+ Assert.Equal("ebx", instruction.Operands);
+ }
+
+ ///
+ /// Tests the DivRm32Handler for decoding DIV r/m32 instruction
+ ///
+ [Fact]
+ public void DivRm32Handler_DecodesDivRm32_Correctly()
+ {
+ // Arrange
+ // DIV ESP (F7 F4) - ModR/M byte F4 = 11 110 100 (mod=3, reg=6, rm=4)
+ // mod=3 means direct register addressing, reg=6 indicates DIV operation, rm=4 is ESP
+ byte[] codeBuffer = new byte[] { 0xF7, 0xF4 };
+ var decoder = new InstructionDecoder(codeBuffer, codeBuffer.Length);
+
+ // Act
+ var instruction = decoder.DecodeInstruction();
+
+ // Assert
+ Assert.NotNull(instruction);
+ Assert.Equal("div", instruction.Mnemonic);
+ Assert.Equal("esp", instruction.Operands);
+ }
+
+ ///
+ /// Tests the IdivRm32Handler for decoding IDIV r/m32 instruction
+ ///
+ [Fact]
+ public void IdivRm32Handler_DecodesIdivRm32_Correctly()
+ {
+ // Arrange
+ // IDIV EBP (F7 FD) - ModR/M byte FD = 11 111 101 (mod=3, reg=7, rm=5)
+ // mod=3 means direct register addressing, reg=7 indicates IDIV operation, rm=5 is EBP
+ byte[] codeBuffer = new byte[] { 0xF7, 0xFD };
+ var decoder = new InstructionDecoder(codeBuffer, codeBuffer.Length);
+
+ // Act
+ var instruction = decoder.DecodeInstruction();
+
+ // Assert
+ Assert.NotNull(instruction);
+ Assert.Equal("idiv", instruction.Mnemonic);
+ Assert.Equal("ebp", instruction.Operands);
+ }
+}
diff --git a/X86DisassemblerTests/JumpInstructionTests.cs b/X86DisassemblerTests/JumpInstructionTests.cs
new file mode 100644
index 0000000..ed6af46
--- /dev/null
+++ b/X86DisassemblerTests/JumpInstructionTests.cs
@@ -0,0 +1,93 @@
+namespace X86DisassemblerTests;
+
+using System;
+using Xunit;
+using X86Disassembler.X86;
+using X86Disassembler.X86.Handlers.Jump;
+
+///
+/// Tests for jump instruction handlers
+///
+public class JumpInstructionTests
+{
+ ///
+ /// Tests the JmpRel8Handler for decoding JMP rel8 instruction
+ ///
+ [Fact]
+ public void JmpRel8Handler_DecodesJmpRel8_Correctly()
+ {
+ // Arrange
+ // JMP +5 (EB 05) - Jump 5 bytes forward
+ byte[] codeBuffer = new byte[] { 0xEB, 0x05 };
+ var decoder = new InstructionDecoder(codeBuffer, codeBuffer.Length);
+
+ // Act
+ var instruction = decoder.DecodeInstruction();
+
+ // Assert
+ Assert.NotNull(instruction);
+ Assert.Equal("jmp", instruction.Mnemonic);
+ Assert.Equal("0x00000007", instruction.Operands); // Current position (2) + offset (5) = 7
+ }
+
+ ///
+ /// Tests the JmpRel32Handler for decoding JMP rel32 instruction
+ ///
+ [Fact]
+ public void JmpRel32Handler_DecodesJmpRel32_Correctly()
+ {
+ // Arrange
+ // JMP +0x12345678 (E9 78 56 34 12) - Jump 0x12345678 bytes forward
+ byte[] codeBuffer = new byte[] { 0xE9, 0x78, 0x56, 0x34, 0x12 };
+ var decoder = new InstructionDecoder(codeBuffer, codeBuffer.Length);
+
+ // Act
+ var instruction = decoder.DecodeInstruction();
+
+ // Assert
+ Assert.NotNull(instruction);
+ Assert.Equal("jmp", instruction.Mnemonic);
+ Assert.Equal("0x1234567D", instruction.Operands); // Current position (5) + offset (0x12345678) = 0x1234567D
+ }
+
+ ///
+ /// Tests the ConditionalJumpHandler for decoding JZ rel8 instruction
+ ///
+ [Fact]
+ public void ConditionalJumpHandler_DecodesJzRel8_Correctly()
+ {
+ // Arrange
+ // JZ +10 (74 0A) - Jump 10 bytes forward if zero/equal
+ // Note: JZ and JE are equivalent in x86
+ byte[] codeBuffer = new byte[] { 0x74, 0x0A };
+ var decoder = new InstructionDecoder(codeBuffer, codeBuffer.Length);
+
+ // Act
+ var instruction = decoder.DecodeInstruction();
+
+ // Assert
+ Assert.NotNull(instruction);
+ Assert.Equal("jz", instruction.Mnemonic);
+ Assert.Equal("0x0000000C", instruction.Operands); // Current position (2) + offset (10) = 12 (0x0C)
+ }
+
+ ///
+ /// Tests the TwoByteConditionalJumpHandler for decoding JNE rel32 instruction
+ ///
+ [Fact]
+ public void TwoByteConditionalJumpHandler_DecodesJneRel32_Correctly()
+ {
+ // Arrange
+ // JNE +0x12345678 (0F 85 78 56 34 12) - Jump 0x12345678 bytes forward if not equal
+ byte[] codeBuffer = new byte[] { 0x0F, 0x85, 0x78, 0x56, 0x34, 0x12 };
+ var decoder = new InstructionDecoder(codeBuffer, codeBuffer.Length);
+
+ // Act
+ var instruction = decoder.DecodeInstruction();
+
+ // Assert
+ Assert.NotNull(instruction);
+ Assert.Equal("jne", instruction.Mnemonic);
+ Assert.Equal("0x1234567E", instruction.Operands); // Current position (6) + offset (0x12345678) = 0x1234567E
+ }
+}
diff --git a/X86DisassemblerTests/ReturnInstructionTests.cs b/X86DisassemblerTests/ReturnInstructionTests.cs
new file mode 100644
index 0000000..e3eb028
--- /dev/null
+++ b/X86DisassemblerTests/ReturnInstructionTests.cs
@@ -0,0 +1,52 @@
+namespace X86DisassemblerTests;
+
+using System;
+using Xunit;
+using X86Disassembler.X86;
+using X86Disassembler.X86.Handlers;
+
+///
+/// Tests for return instruction handlers
+///
+public class ReturnInstructionTests
+{
+ ///
+ /// Tests the RetHandler for decoding RET instruction
+ ///
+ [Fact]
+ public void RetHandler_DecodesRet_Correctly()
+ {
+ // Arrange
+ // RET (C3) - Return from procedure
+ byte[] codeBuffer = new byte[] { 0xC3 };
+ var decoder = new InstructionDecoder(codeBuffer, codeBuffer.Length);
+
+ // Act
+ var instruction = decoder.DecodeInstruction();
+
+ // Assert
+ Assert.NotNull(instruction);
+ Assert.Equal("ret", instruction.Mnemonic);
+ Assert.Equal("", instruction.Operands);
+ }
+
+ ///
+ /// Tests the RetImmHandler for decoding RET imm16 instruction
+ ///
+ [Fact]
+ public void RetImmHandler_DecodesRetImm16_Correctly()
+ {
+ // Arrange
+ // RET 0x1234 (C2 34 12) - Return from procedure and pop 0x1234 bytes
+ byte[] codeBuffer = new byte[] { 0xC2, 0x34, 0x12 };
+ var decoder = new InstructionDecoder(codeBuffer, codeBuffer.Length);
+
+ // Act
+ var instruction = decoder.DecodeInstruction();
+
+ // Assert
+ Assert.NotNull(instruction);
+ Assert.Equal("ret", instruction.Mnemonic);
+ Assert.Equal("0x1234", instruction.Operands);
+ }
+}
diff --git a/X86DisassemblerTests/XorInstructionTests.cs b/X86DisassemblerTests/XorInstructionTests.cs
new file mode 100644
index 0000000..ac98155
--- /dev/null
+++ b/X86DisassemblerTests/XorInstructionTests.cs
@@ -0,0 +1,94 @@
+namespace X86DisassemblerTests;
+
+using System;
+using Xunit;
+using X86Disassembler.X86;
+using X86Disassembler.X86.Handlers;
+
+///
+/// Tests for XOR instruction handlers
+///
+public class XorInstructionTests
+{
+ ///
+ /// Tests the XorRegMemHandler for decoding XOR r32, r/m32 instruction
+ ///
+ [Fact]
+ public void XorRegMemHandler_DecodesXorR32Rm32_Correctly()
+ {
+ // Arrange
+ // XOR EAX, ECX (33 C1) - ModR/M byte C1 = 11 000 001 (mod=3, reg=0, rm=1)
+ // mod=3 means direct register addressing, reg=0 is EAX, rm=1 is ECX
+ byte[] codeBuffer = new byte[] { 0x33, 0xC1 };
+ var decoder = new InstructionDecoder(codeBuffer, codeBuffer.Length);
+
+ // Act
+ var instruction = decoder.DecodeInstruction();
+
+ // Assert
+ Assert.NotNull(instruction);
+ Assert.Equal("xor", instruction.Mnemonic);
+ Assert.Equal("eax, ecx", instruction.Operands);
+ }
+
+ ///
+ /// Tests the XorMemRegHandler for decoding XOR r/m32, r32 instruction
+ ///
+ [Fact]
+ public void XorMemRegHandler_DecodesXorRm32R32_Correctly()
+ {
+ // Arrange
+ // XOR ECX, EAX (31 C1) - ModR/M byte C1 = 11 000 001 (mod=3, reg=0, rm=1)
+ // mod=3 means direct register addressing, reg=0 is EAX, rm=1 is ECX
+ byte[] codeBuffer = new byte[] { 0x31, 0xC1 };
+ var decoder = new InstructionDecoder(codeBuffer, codeBuffer.Length);
+
+ // Act
+ var instruction = decoder.DecodeInstruction();
+
+ // Assert
+ Assert.NotNull(instruction);
+ Assert.Equal("xor", instruction.Mnemonic);
+ Assert.Equal("ecx, eax", instruction.Operands);
+ }
+
+ ///
+ /// Tests the XorAlImmHandler for decoding XOR AL, imm8 instruction
+ ///
+ [Fact]
+ public void XorAlImmHandler_DecodesXorAlImm8_Correctly()
+ {
+ // Arrange
+ // XOR AL, 0x42 (34 42)
+ byte[] codeBuffer = new byte[] { 0x34, 0x42 };
+ var decoder = new InstructionDecoder(codeBuffer, codeBuffer.Length);
+
+ // Act
+ var instruction = decoder.DecodeInstruction();
+
+ // Assert
+ Assert.NotNull(instruction);
+ Assert.Equal("xor", instruction.Mnemonic);
+ Assert.Equal("al, 0x42", instruction.Operands);
+ }
+
+ ///
+ /// Tests the XorEaxImmHandler for decoding XOR EAX, imm32 instruction
+ ///
+ [Fact]
+ public void XorEaxImmHandler_DecodesXorEaxImm32_Correctly()
+ {
+ // Arrange
+ // XOR EAX, 0x12345678 (35 78 56 34 12)
+ byte[] codeBuffer = new byte[] { 0x35, 0x78, 0x56, 0x34, 0x12 };
+ var decoder = new InstructionDecoder(codeBuffer, codeBuffer.Length);
+
+ // Act
+ var instruction = decoder.DecodeInstruction();
+
+ // Assert
+ Assert.NotNull(instruction);
+ Assert.Equal("xor", instruction.Mnemonic);
+ Assert.Equal("eax, 0x12345678", instruction.Operands);
+ }
+}