From c701fdb4352101573423cea0dbd69ba7558ceb19 Mon Sep 17 00:00:00 2001 From: bird_egop Date: Sun, 13 Apr 2025 01:30:42 +0300 Subject: [PATCH] Added CmpAlImmHandler for CMP AL, imm8 instruction (0x3C) with tests --- .../AddImmToRm32Handler.cs | 0 .../AddImmToRm32SignExtendedHandler.cs | 0 .../AddImmToRm8Handler.cs | 0 .../X86/Handlers/Cmp/CmpAlImmHandler.cs | 56 +++++++++++++++++++ .../CmpImmWithRm32Handler.cs | 0 .../CmpImmWithRm32SignExtendedHandler.cs | 0 .../X86/Handlers/InstructionHandlerFactory.cs | 30 +++++----- .../CmpInstructionHandlerTests.cs | 54 ++++++++++++++++++ .../InstructionHandlerFactoryTests.cs | 6 ++ 9 files changed, 130 insertions(+), 16 deletions(-) rename X86Disassembler/X86/Handlers/{ArithmeticImmediate => Add}/AddImmToRm32Handler.cs (100%) rename X86Disassembler/X86/Handlers/{ArithmeticImmediate => Add}/AddImmToRm32SignExtendedHandler.cs (100%) rename X86Disassembler/X86/Handlers/{ArithmeticImmediate => Add}/AddImmToRm8Handler.cs (100%) create mode 100644 X86Disassembler/X86/Handlers/Cmp/CmpAlImmHandler.cs rename X86Disassembler/X86/Handlers/{ArithmeticImmediate => Cmp}/CmpImmWithRm32Handler.cs (100%) rename X86Disassembler/X86/Handlers/{ArithmeticImmediate => Cmp}/CmpImmWithRm32SignExtendedHandler.cs (100%) create mode 100644 X86DisassemblerTests/CmpInstructionHandlerTests.cs create mode 100644 X86DisassemblerTests/InstructionHandlerFactoryTests.cs diff --git a/X86Disassembler/X86/Handlers/ArithmeticImmediate/AddImmToRm32Handler.cs b/X86Disassembler/X86/Handlers/Add/AddImmToRm32Handler.cs similarity index 100% rename from X86Disassembler/X86/Handlers/ArithmeticImmediate/AddImmToRm32Handler.cs rename to X86Disassembler/X86/Handlers/Add/AddImmToRm32Handler.cs diff --git a/X86Disassembler/X86/Handlers/ArithmeticImmediate/AddImmToRm32SignExtendedHandler.cs b/X86Disassembler/X86/Handlers/Add/AddImmToRm32SignExtendedHandler.cs similarity index 100% rename from X86Disassembler/X86/Handlers/ArithmeticImmediate/AddImmToRm32SignExtendedHandler.cs rename to X86Disassembler/X86/Handlers/Add/AddImmToRm32SignExtendedHandler.cs diff --git a/X86Disassembler/X86/Handlers/ArithmeticImmediate/AddImmToRm8Handler.cs b/X86Disassembler/X86/Handlers/Add/AddImmToRm8Handler.cs similarity index 100% rename from X86Disassembler/X86/Handlers/ArithmeticImmediate/AddImmToRm8Handler.cs rename to X86Disassembler/X86/Handlers/Add/AddImmToRm8Handler.cs diff --git a/X86Disassembler/X86/Handlers/Cmp/CmpAlImmHandler.cs b/X86Disassembler/X86/Handlers/Cmp/CmpAlImmHandler.cs new file mode 100644 index 0000000..567ff55 --- /dev/null +++ b/X86Disassembler/X86/Handlers/Cmp/CmpAlImmHandler.cs @@ -0,0 +1,56 @@ +namespace X86Disassembler.X86.Handlers.Cmp; + +/// +/// Handler for CMP AL, imm8 instruction (0x3C) +/// +public class CmpAlImmHandler : InstructionHandler +{ + /// + /// Initializes a new instance of the CmpAlImmHandler class + /// + /// The buffer containing the code to decode + /// The instruction decoder that owns this handler + /// The length of the buffer + public CmpAlImmHandler(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) + { + return opcode == 0x3C; + } + + /// + /// Decodes a CMP AL, 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 mnemonic + instruction.Mnemonic = "cmp"; + + int position = Decoder.GetPosition(); + + if (position >= Length) + { + return false; + } + + // Read the immediate value + byte imm8 = CodeBuffer[position++]; + Decoder.SetPosition(position); + + // Set the operands + instruction.Operands = $"al, 0x{imm8:X2}"; + + return true; + } +} diff --git a/X86Disassembler/X86/Handlers/ArithmeticImmediate/CmpImmWithRm32Handler.cs b/X86Disassembler/X86/Handlers/Cmp/CmpImmWithRm32Handler.cs similarity index 100% rename from X86Disassembler/X86/Handlers/ArithmeticImmediate/CmpImmWithRm32Handler.cs rename to X86Disassembler/X86/Handlers/Cmp/CmpImmWithRm32Handler.cs diff --git a/X86Disassembler/X86/Handlers/ArithmeticImmediate/CmpImmWithRm32SignExtendedHandler.cs b/X86Disassembler/X86/Handlers/Cmp/CmpImmWithRm32SignExtendedHandler.cs similarity index 100% rename from X86Disassembler/X86/Handlers/ArithmeticImmediate/CmpImmWithRm32SignExtendedHandler.cs rename to X86Disassembler/X86/Handlers/Cmp/CmpImmWithRm32SignExtendedHandler.cs diff --git a/X86Disassembler/X86/Handlers/InstructionHandlerFactory.cs b/X86Disassembler/X86/Handlers/InstructionHandlerFactory.cs index 9285986..6f00136 100644 --- a/X86Disassembler/X86/Handlers/InstructionHandlerFactory.cs +++ b/X86Disassembler/X86/Handlers/InstructionHandlerFactory.cs @@ -16,7 +16,6 @@ using X86Disassembler.X86.Handlers.Ret; using X86Disassembler.X86.Handlers.Test; using X86Disassembler.X86.Handlers.Xchg; using X86Disassembler.X86.Handlers.Xor; -using System.Linq; namespace X86Disassembler.X86.Handlers; @@ -99,11 +98,6 @@ public class InstructionHandlerFactory /// private void RegisterArithmeticImmediateHandlers() { - // ADD handlers - _handlers.Add(new AddImmToRm8Handler(_codeBuffer, _decoder, _length)); - _handlers.Add(new AddImmToRm32Handler(_codeBuffer, _decoder, _length)); - _handlers.Add(new AddImmToRm32SignExtendedHandler(_codeBuffer, _decoder, _length)); - // ADC handlers _handlers.Add(new AdcImmToRm32Handler(_codeBuffer, _decoder, _length)); _handlers.Add(new AdcImmToRm32SignExtendedHandler(_codeBuffer, _decoder, _length)); @@ -119,14 +113,6 @@ public class InstructionHandlerFactory // SUB handlers _handlers.Add(new SubImmFromRm32Handler(_codeBuffer, _decoder, _length)); _handlers.Add(new SubImmFromRm32SignExtendedHandler(_codeBuffer, _decoder, _length)); - - // XOR handlers - _handlers.Add(new XorImmWithRm32Handler(_codeBuffer, _decoder, _length)); - _handlers.Add(new XorImmWithRm32SignExtendedHandler(_codeBuffer, _decoder, _length)); - - // CMP handlers - _handlers.Add(new CmpImmWithRm32Handler(_codeBuffer, _decoder, _length)); - _handlers.Add(new CmpImmWithRm32SignExtendedHandler(_codeBuffer, _decoder, _length)); } /// @@ -185,8 +171,10 @@ public class InstructionHandlerFactory _handlers.Add(new XorEaxImmHandler(_codeBuffer, _decoder, _length)); _handlers.Add(new XorMemRegHandler(_codeBuffer, _decoder, _length)); _handlers.Add(new XorRegMemHandler(_codeBuffer, _decoder, _length)); - _handlers.Add(new XorImmWithRm32Handler(_codeBuffer, _decoder, _length)); - _handlers.Add(new XorImmWithRm32SignExtendedHandler(_codeBuffer, _decoder, _length)); + + // Add XOR immediate handlers + _handlers.Add(new Xor.XorImmWithRm32Handler(_codeBuffer, _decoder, _length)); + _handlers.Add(new Xor.XorImmWithRm32SignExtendedHandler(_codeBuffer, _decoder, _length)); } /// @@ -222,6 +210,11 @@ public class InstructionHandlerFactory // Add Cmp handlers _handlers.Add(new CmpR32Rm32Handler(_codeBuffer, _decoder, _length)); _handlers.Add(new CmpImmWithRm8Handler(_codeBuffer, _decoder, _length)); + _handlers.Add(new CmpAlImmHandler(_codeBuffer, _decoder, _length)); + + // Add CMP immediate handlers from ArithmeticImmediate namespace + _handlers.Add(new CmpImmWithRm32Handler(_codeBuffer, _decoder, _length)); + _handlers.Add(new CmpImmWithRm32SignExtendedHandler(_codeBuffer, _decoder, _length)); } /// @@ -250,6 +243,11 @@ public class InstructionHandlerFactory // Add ADD handlers _handlers.Add(new AddR32Rm32Handler(_codeBuffer, _decoder, _length)); _handlers.Add(new AddRm32R32Handler(_codeBuffer, _decoder, _length)); + + // Add ADD immediate handlers from ArithmeticImmediate namespace + _handlers.Add(new AddImmToRm8Handler(_codeBuffer, _decoder, _length)); + _handlers.Add(new AddImmToRm32Handler(_codeBuffer, _decoder, _length)); + _handlers.Add(new AddImmToRm32SignExtendedHandler(_codeBuffer, _decoder, _length)); } /// diff --git a/X86DisassemblerTests/CmpInstructionHandlerTests.cs b/X86DisassemblerTests/CmpInstructionHandlerTests.cs new file mode 100644 index 0000000..f95e660 --- /dev/null +++ b/X86DisassemblerTests/CmpInstructionHandlerTests.cs @@ -0,0 +1,54 @@ +namespace X86DisassemblerTests; + +using System; +using Xunit; +using X86Disassembler.X86; +using X86Disassembler.X86.Handlers; +using X86Disassembler.X86.Handlers.Cmp; + +/// +/// Tests for CMP instruction handlers +/// +public class CmpInstructionHandlerTests +{ + /// + /// Tests the CmpAlImmHandler for decoding CMP AL, imm8 instructions + /// + [Fact] + public void CmpAlImmHandler_DecodesCmpAlImm8_Correctly() + { + // Arrange + // CMP AL, 0x03 (3C 03) + byte[] codeBuffer = new byte[] { 0x3C, 0x03 }; + var decoder = new InstructionDecoder(codeBuffer, codeBuffer.Length); + + // Act + var instruction = decoder.DecodeInstruction(); + + // Assert + Assert.NotNull(instruction); + Assert.Equal("cmp", instruction.Mnemonic); + // The handler should produce "al, 0xXX" as the operands + Assert.Equal("al, 0x03", instruction.Operands); + } + + /// + /// Tests the CmpAlImmHandler with a different immediate value + /// + [Fact] + public void CmpAlImmHandler_DecodesCmpAlImm8_WithDifferentValue() + { + // Arrange + // CMP AL, 0xFF (3C FF) + byte[] codeBuffer = new byte[] { 0x3C, 0xFF }; + var decoder = new InstructionDecoder(codeBuffer, codeBuffer.Length); + + // Act + var instruction = decoder.DecodeInstruction(); + + // Assert + Assert.NotNull(instruction); + Assert.Equal("cmp", instruction.Mnemonic); + Assert.Equal("al, 0xFF", instruction.Operands); + } +} diff --git a/X86DisassemblerTests/InstructionHandlerFactoryTests.cs b/X86DisassemblerTests/InstructionHandlerFactoryTests.cs new file mode 100644 index 0000000..2fdcd4d --- /dev/null +++ b/X86DisassemblerTests/InstructionHandlerFactoryTests.cs @@ -0,0 +1,6 @@ +namespace X86DisassemblerTests; + +public class InstructionHandlerFactoryTests +{ + +} \ No newline at end of file