diff --git a/X86Disassembler/X86/Handlers/Dec/DecRegHandler.cs b/X86Disassembler/X86/Handlers/Dec/DecRegHandler.cs new file mode 100644 index 0000000..cb678c8 --- /dev/null +++ b/X86Disassembler/X86/Handlers/Dec/DecRegHandler.cs @@ -0,0 +1,49 @@ +namespace X86Disassembler.X86.Handlers.Dec; + +/// +/// Handler for DEC r32 instructions (0x48-0x4F) +/// +public class DecRegHandler : InstructionHandler +{ + /// + /// Initializes a new instance of the DecRegHandler class + /// + /// The buffer containing the code to decode + /// The instruction decoder that owns this handler + /// The length of the buffer + public DecRegHandler(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) + { + // DEC EAX = 0x48, DEC ECX = 0x49, ..., DEC EDI = 0x4F + return opcode >= 0x48 && opcode <= 0x4F; + } + + /// + /// Decodes a DEC r32 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) + { + // Calculate the register index (0 for EAX, 1 for ECX, etc.) + byte reg = (byte)(opcode - 0x48); + + // Set the mnemonic + instruction.Mnemonic = "dec"; + + // Set the operand (register name) + instruction.Operands = GetRegister32(reg); + + return true; + } +} diff --git a/X86Disassembler/X86/Handlers/InstructionHandlerFactory.cs b/X86Disassembler/X86/Handlers/InstructionHandlerFactory.cs index 2b945a0..70457b8 100644 --- a/X86Disassembler/X86/Handlers/InstructionHandlerFactory.cs +++ b/X86Disassembler/X86/Handlers/InstructionHandlerFactory.cs @@ -2,6 +2,7 @@ using X86Disassembler.X86.Handlers.ArithmeticImmediate; using X86Disassembler.X86.Handlers.ArithmeticUnary; using X86Disassembler.X86.Handlers.Call; using X86Disassembler.X86.Handlers.Cmp; +using X86Disassembler.X86.Handlers.Dec; using X86Disassembler.X86.Handlers.FloatingPoint; using X86Disassembler.X86.Handlers.Jump; using X86Disassembler.X86.Handlers.Lea; @@ -77,6 +78,9 @@ public class InstructionHandlerFactory // Register Cmp handlers RegisterCmpHandlers(); + // Register Dec handlers + RegisterDecHandlers(); + // Register Data Transfer handlers RegisterDataTransferHandlers(); @@ -238,6 +242,15 @@ public class InstructionHandlerFactory _handlers.Add(new CmpR32Rm32Handler(_codeBuffer, _decoder, _length)); } + /// + /// Registers all Dec instruction handlers + /// + private void RegisterDecHandlers() + { + // Add Dec handlers + _handlers.Add(new DecRegHandler(_codeBuffer, _decoder, _length)); + } + /// /// Registers all Data Transfer instruction handlers /// diff --git a/X86Disassembler/X86/OpcodeMap.cs b/X86Disassembler/X86/OpcodeMap.cs index ba54a65..381f81e 100644 --- a/X86Disassembler/X86/OpcodeMap.cs +++ b/X86Disassembler/X86/OpcodeMap.cs @@ -62,6 +62,16 @@ public static class OpcodeMap OneByteOpcodes[0xC6] = "mov"; // MOV r/m8, imm8 OneByteOpcodes[0xC7] = "mov"; // MOV r/m32, imm32 + // DEC instructions + OneByteOpcodes[0x48] = "dec"; // DEC EAX + OneByteOpcodes[0x49] = "dec"; // DEC ECX + OneByteOpcodes[0x4A] = "dec"; // DEC EDX + OneByteOpcodes[0x4B] = "dec"; // DEC EBX + OneByteOpcodes[0x4C] = "dec"; // DEC ESP + OneByteOpcodes[0x4D] = "dec"; // DEC EBP + OneByteOpcodes[0x4E] = "dec"; // DEC ESI + OneByteOpcodes[0x4F] = "dec"; // DEC EDI + // Group 1 instructions (ADD, OR, ADC, SBB, AND, SUB, XOR, CMP) OneByteOpcodes[0x80] = "group1b"; OneByteOpcodes[0x81] = "group1d"; diff --git a/X86DisassemblerTests/DecInstructionTests.cs b/X86DisassemblerTests/DecInstructionTests.cs new file mode 100644 index 0000000..3196208 --- /dev/null +++ b/X86DisassemblerTests/DecInstructionTests.cs @@ -0,0 +1,68 @@ +namespace X86DisassemblerTests; + +using System; +using Xunit; +using X86Disassembler.X86; + +/// +/// Tests for DEC instruction handlers +/// +public class DecInstructionTests +{ + /// + /// Tests the DEC EAX instruction (0x48) + /// + [Fact] + public void TestDecEax() + { + // Arrange + byte[] code = { 0x48 }; // DEC EAX + + // Act + Disassembler disassembler = new Disassembler(code, 0x1000); + var instructions = disassembler.Disassemble(); + + // Assert + Assert.Single(instructions); + Assert.Equal("dec", instructions[0].Mnemonic); + Assert.Equal("eax", instructions[0].Operands); + } + + /// + /// Tests the DEC ECX instruction (0x49) + /// + [Fact] + public void TestDecEcx() + { + // Arrange + byte[] code = { 0x49 }; // DEC ECX + + // Act + Disassembler disassembler = new Disassembler(code, 0x1000); + var instructions = disassembler.Disassemble(); + + // Assert + Assert.Single(instructions); + Assert.Equal("dec", instructions[0].Mnemonic); + Assert.Equal("ecx", instructions[0].Operands); + } + + /// + /// Tests the DEC EDI instruction (0x4F) + /// + [Fact] + public void TestDecEdi() + { + // Arrange + byte[] code = { 0x4F }; // DEC EDI + + // Act + Disassembler disassembler = new Disassembler(code, 0x1000); + var instructions = disassembler.Disassemble(); + + // Assert + Assert.Single(instructions); + Assert.Equal("dec", instructions[0].Mnemonic); + Assert.Equal("edi", instructions[0].Operands); + } +}