From acccf5169a165303c8f2acbf73b0747c31f3fcc6 Mon Sep 17 00:00:00 2001 From: bird_egop Date: Sat, 12 Apr 2025 22:34:02 +0300 Subject: [PATCH] Fixed FnstswHandler test by registering the handler in InstructionHandlerFactory --- .../X86/Handlers/InstructionHandlerFactory.cs | 163 ++++++++++++------ .../X86/Handlers/Mov/MovEaxMoffsHandler.cs | 56 ++++++ .../X86/Handlers/Mov/MovMemRegHandler.cs | 70 ++++++++ .../X86/Handlers/Mov/MovMoffsEaxHandler.cs | 56 ++++++ .../X86/Handlers/Mov/MovRegImm32Handler.cs | 56 ++++++ .../X86/Handlers/Mov/MovRegImm8Handler.cs | 56 ++++++ .../X86/Handlers/Mov/MovRegMemHandler.cs | 70 ++++++++ .../X86/Handlers/Pop/PopRegHandler.cs | 49 ++++++ .../X86/Handlers/Push/PushImm32Handler.cs | 52 ++++++ .../X86/Handlers/Push/PushImm8Handler.cs | 52 ++++++ .../X86/Handlers/Push/PushRegHandler.cs | 49 ++++++ .../X86/Handlers/Xchg/XchgEaxRegHandler.cs | 57 ++++++ 12 files changed, 738 insertions(+), 48 deletions(-) create mode 100644 X86Disassembler/X86/Handlers/Mov/MovEaxMoffsHandler.cs create mode 100644 X86Disassembler/X86/Handlers/Mov/MovMemRegHandler.cs create mode 100644 X86Disassembler/X86/Handlers/Mov/MovMoffsEaxHandler.cs create mode 100644 X86Disassembler/X86/Handlers/Mov/MovRegImm32Handler.cs create mode 100644 X86Disassembler/X86/Handlers/Mov/MovRegImm8Handler.cs create mode 100644 X86Disassembler/X86/Handlers/Mov/MovRegMemHandler.cs create mode 100644 X86Disassembler/X86/Handlers/Pop/PopRegHandler.cs create mode 100644 X86Disassembler/X86/Handlers/Push/PushImm32Handler.cs create mode 100644 X86Disassembler/X86/Handlers/Push/PushImm8Handler.cs create mode 100644 X86Disassembler/X86/Handlers/Push/PushRegHandler.cs create mode 100644 X86Disassembler/X86/Handlers/Xchg/XchgEaxRegHandler.cs diff --git a/X86Disassembler/X86/Handlers/InstructionHandlerFactory.cs b/X86Disassembler/X86/Handlers/InstructionHandlerFactory.cs index 248a42e..5a17c85 100644 --- a/X86Disassembler/X86/Handlers/InstructionHandlerFactory.cs +++ b/X86Disassembler/X86/Handlers/InstructionHandlerFactory.cs @@ -1,23 +1,26 @@ using X86Disassembler.X86.Handlers.Call; +using X86Disassembler.X86.Handlers.Group1; +using X86Disassembler.X86.Handlers.Group3; using X86Disassembler.X86.Handlers.Jump; +using X86Disassembler.X86.Handlers.Mov; +using X86Disassembler.X86.Handlers.Pop; +using X86Disassembler.X86.Handlers.Push; using X86Disassembler.X86.Handlers.Ret; using X86Disassembler.X86.Handlers.Test; +using X86Disassembler.X86.Handlers.Xchg; using X86Disassembler.X86.Handlers.Xor; namespace X86Disassembler.X86.Handlers; -using X86Disassembler.X86.Handlers.Group1; -using X86Disassembler.X86.Handlers.Group3; - /// /// Factory for creating instruction handlers /// public class InstructionHandlerFactory { + private readonly List _handlers = new(); private readonly byte[] _codeBuffer; private readonly InstructionDecoder _decoder; private readonly int _length; - private readonly List _handlers = []; /// /// Initializes a new instance of the InstructionHandlerFactory class @@ -31,7 +34,6 @@ public class InstructionHandlerFactory _decoder = decoder; _length = length; - // Register all instruction handlers RegisterHandlers(); } @@ -40,49 +42,38 @@ public class InstructionHandlerFactory /// private void RegisterHandlers() { - // Register Group3 handlers first to ensure they take precedence - // over generic handlers for the same opcodes + // Register group handlers RegisterGroup3Handlers(); - - // Register Group1 handlers RegisterGroup1Handlers(); // Register specific instruction handlers _handlers.Add(new Int3Handler(_codeBuffer, _decoder, _length)); - _handlers.Add(new RetHandler(_codeBuffer, _decoder, _length)); - _handlers.Add(new RetImmHandler(_codeBuffer, _decoder, _length)); - _handlers.Add(new CallRel32Handler(_codeBuffer, _decoder, _length)); + // Register Return handlers + RegisterReturnHandlers(); - // XOR handlers - _handlers.Add(new XorRegMemHandler(_codeBuffer, _decoder, _length)); - _handlers.Add(new XorMemRegHandler(_codeBuffer, _decoder, _length)); - _handlers.Add(new XorAlImmHandler(_codeBuffer, _decoder, _length)); - _handlers.Add(new XorEaxImmHandler(_codeBuffer, _decoder, _length)); - + // Register Call handlers + RegisterCallHandlers(); + + // Register Jump handlers + RegisterJumpHandlers(); + + // Register Test handlers + RegisterTestHandlers(); + + // Register Xor handlers + RegisterXorHandlers(); + + // Register Data Transfer handlers + RegisterDataTransferHandlers(); + + // Register floating point handlers _handlers.Add(new FnstswHandler(_codeBuffer, _decoder, _length)); - - // TEST handlers - _handlers.Add(new TestImmWithRm32Handler(_codeBuffer, _decoder, _length)); - _handlers.Add(new TestImmWithRm8Handler(_codeBuffer, _decoder, _length)); - _handlers.Add(new TestRegMem8Handler(_codeBuffer, _decoder, _length)); - _handlers.Add(new TestRegMemHandler(_codeBuffer, _decoder, _length)); - _handlers.Add(new TestAlImmHandler(_codeBuffer, _decoder, _length)); - _handlers.Add(new TestEaxImmHandler(_codeBuffer, _decoder, _length)); - - // JMP handlers - _handlers.Add(new JmpRel32Handler(_codeBuffer, _decoder, _length)); - _handlers.Add(new JmpRel8Handler(_codeBuffer, _decoder, _length)); - _handlers.Add(new ConditionalJumpHandler(_codeBuffer, _decoder, _length)); - _handlers.Add(new TwoByteConditionalJumpHandler(_codeBuffer, _decoder, _length)); - - // Register group handlers for instructions that share similar decoding logic _handlers.Add(new FloatingPointHandler(_codeBuffer, _decoder, _length)); - _handlers.Add(new DataTransferHandler(_codeBuffer, _decoder, _length)); } /// - /// Registers the Group1 handlers + /// Registers all Group1 instruction handlers /// private void RegisterGroup1Handlers() { @@ -122,7 +113,7 @@ public class InstructionHandlerFactory } /// - /// Registers the Group3 handlers + /// Registers all Group3 instruction handlers /// private void RegisterGroup3Handlers() { @@ -146,20 +137,96 @@ public class InstructionHandlerFactory } /// - /// Gets a handler that can decode the given opcode + /// Registers all Return instruction handlers + /// + private void RegisterReturnHandlers() + { + // Add Return handlers + _handlers.Add(new RetHandler(_codeBuffer, _decoder, _length)); + _handlers.Add(new RetImmHandler(_codeBuffer, _decoder, _length)); + } + + /// + /// Registers all Call instruction handlers + /// + private void RegisterCallHandlers() + { + // Add Call handlers + _handlers.Add(new CallRel32Handler(_codeBuffer, _decoder, _length)); + } + + /// + /// Registers all Jump instruction handlers + /// + private void RegisterJumpHandlers() + { + // JMP handlers + _handlers.Add(new JmpRel32Handler(_codeBuffer, _decoder, _length)); + _handlers.Add(new JmpRel8Handler(_codeBuffer, _decoder, _length)); + _handlers.Add(new ConditionalJumpHandler(_codeBuffer, _decoder, _length)); + _handlers.Add(new TwoByteConditionalJumpHandler(_codeBuffer, _decoder, _length)); + } + + /// + /// Registers all Test instruction handlers + /// + private void RegisterTestHandlers() + { + // TEST handlers + _handlers.Add(new TestImmWithRm32Handler(_codeBuffer, _decoder, _length)); + _handlers.Add(new TestImmWithRm8Handler(_codeBuffer, _decoder, _length)); + _handlers.Add(new TestRegMem8Handler(_codeBuffer, _decoder, _length)); + _handlers.Add(new TestRegMemHandler(_codeBuffer, _decoder, _length)); + _handlers.Add(new TestAlImmHandler(_codeBuffer, _decoder, _length)); + _handlers.Add(new TestEaxImmHandler(_codeBuffer, _decoder, _length)); + } + + /// + /// Registers all Xor instruction handlers + /// + private void RegisterXorHandlers() + { + // Add Xor handlers + _handlers.Add(new XorAlImmHandler(_codeBuffer, _decoder, _length)); + _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)); + } + + /// + /// Registers all Data Transfer instruction handlers + /// + private void RegisterDataTransferHandlers() + { + // Add MOV handlers + _handlers.Add(new MovRegMemHandler(_codeBuffer, _decoder, _length)); + _handlers.Add(new MovMemRegHandler(_codeBuffer, _decoder, _length)); + _handlers.Add(new MovRegImm32Handler(_codeBuffer, _decoder, _length)); + _handlers.Add(new MovRegImm8Handler(_codeBuffer, _decoder, _length)); + _handlers.Add(new MovEaxMoffsHandler(_codeBuffer, _decoder, _length)); + _handlers.Add(new MovMoffsEaxHandler(_codeBuffer, _decoder, _length)); + + // Add PUSH handlers + _handlers.Add(new PushRegHandler(_codeBuffer, _decoder, _length)); + _handlers.Add(new PushImm32Handler(_codeBuffer, _decoder, _length)); + _handlers.Add(new PushImm8Handler(_codeBuffer, _decoder, _length)); + + // Add POP handlers + _handlers.Add(new PopRegHandler(_codeBuffer, _decoder, _length)); + + // Add XCHG handlers + _handlers.Add(new XchgEaxRegHandler(_codeBuffer, _decoder, _length)); + } + + /// + /// Gets the handler that can decode the given opcode /// /// The opcode to decode - /// A handler that can decode the opcode, or null if no handler is found + /// The handler that can decode the opcode, or null if no handler can decode it public IInstructionHandler? GetHandler(byte opcode) { - foreach (var handler in _handlers) - { - if (handler.CanHandle(opcode)) - { - return handler; - } - } - - return null; + return _handlers.FirstOrDefault(h => h.CanHandle(opcode)); } } diff --git a/X86Disassembler/X86/Handlers/Mov/MovEaxMoffsHandler.cs b/X86Disassembler/X86/Handlers/Mov/MovEaxMoffsHandler.cs new file mode 100644 index 0000000..a575de5 --- /dev/null +++ b/X86Disassembler/X86/Handlers/Mov/MovEaxMoffsHandler.cs @@ -0,0 +1,56 @@ +namespace X86Disassembler.X86.Handlers.Mov; + +/// +/// Handler for MOV EAX, moffs32 instruction (0xA1) and MOV AL, moffs8 instruction (0xA0) +/// +public class MovEaxMoffsHandler : InstructionHandler +{ + /// + /// Initializes a new instance of the MovEaxMoffsHandler class + /// + /// The buffer containing the code to decode + /// The instruction decoder that owns this handler + /// The length of the buffer + public MovEaxMoffsHandler(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 == 0xA0 || opcode == 0xA1; + } + + /// + /// Decodes a MOV EAX, moffs32 or MOV AL, moffs8 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 = "mov"; + + // Get the operand size and register name + int operandSize = (opcode == 0xA0) ? 8 : 32; + string regName = (opcode == 0xA0) ? "al" : "eax"; + + // Read the memory offset + uint offset = Decoder.ReadUInt32(); + if (Decoder.GetPosition() > Length) + { + return false; + } + + // Set the operands + instruction.Operands = $"{regName}, [0x{offset:X}]"; + + return true; + } +} diff --git a/X86Disassembler/X86/Handlers/Mov/MovMemRegHandler.cs b/X86Disassembler/X86/Handlers/Mov/MovMemRegHandler.cs new file mode 100644 index 0000000..7342f6e --- /dev/null +++ b/X86Disassembler/X86/Handlers/Mov/MovMemRegHandler.cs @@ -0,0 +1,70 @@ +namespace X86Disassembler.X86.Handlers.Mov; + +/// +/// Handler for MOV r/m32, r32 instruction (0x89) and MOV r/m8, r8 instruction (0x88) +/// +public class MovMemRegHandler : InstructionHandler +{ + /// + /// Initializes a new instance of the MovMemRegHandler class + /// + /// The buffer containing the code to decode + /// The instruction decoder that owns this handler + /// The length of the buffer + public MovMemRegHandler(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 == 0x88 || opcode == 0x89; + } + + /// + /// Decodes a MOV r/m32, r32 or MOV r/m8, r8 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 = "mov"; + + int position = Decoder.GetPosition(); + + if (position >= Length) + { + return false; + } + + // Determine operand size (0 = 8-bit, 1 = 32-bit) + bool operandSize32 = (opcode & 0x01) != 0; + int operandSize = operandSize32 ? 32 : 8; + + // Read the ModR/M byte + var (mod, reg, rm, memOperand) = ModRMDecoder.ReadModRM(); + + // Get register name based on size + string regName = ModRMDecoder.GetRegisterName(reg, operandSize); + + // For mod == 3, both operands are registers + if (mod == 3) + { + string rmRegName = ModRMDecoder.GetRegisterName(rm, operandSize); + instruction.Operands = $"{regName}, {rmRegName}"; + } + else // Memory operand + { + instruction.Operands = $"{regName}, {memOperand}"; + } + + return true; + } +} diff --git a/X86Disassembler/X86/Handlers/Mov/MovMoffsEaxHandler.cs b/X86Disassembler/X86/Handlers/Mov/MovMoffsEaxHandler.cs new file mode 100644 index 0000000..6580207 --- /dev/null +++ b/X86Disassembler/X86/Handlers/Mov/MovMoffsEaxHandler.cs @@ -0,0 +1,56 @@ +namespace X86Disassembler.X86.Handlers.Mov; + +/// +/// Handler for MOV moffs32, EAX instruction (0xA3) and MOV moffs8, AL instruction (0xA2) +/// +public class MovMoffsEaxHandler : InstructionHandler +{ + /// + /// Initializes a new instance of the MovMoffsEaxHandler class + /// + /// The buffer containing the code to decode + /// The instruction decoder that owns this handler + /// The length of the buffer + public MovMoffsEaxHandler(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 == 0xA2 || opcode == 0xA3; + } + + /// + /// Decodes a MOV moffs32, EAX or MOV moffs8, AL 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 = "mov"; + + // Get the operand size and register name + int operandSize = (opcode == 0xA2) ? 8 : 32; + string regName = (opcode == 0xA2) ? "al" : "eax"; + + // Read the memory offset + uint offset = Decoder.ReadUInt32(); + if (Decoder.GetPosition() > Length) + { + return false; + } + + // Set the operands + instruction.Operands = $"[0x{offset:X}], {regName}"; + + return true; + } +} diff --git a/X86Disassembler/X86/Handlers/Mov/MovRegImm32Handler.cs b/X86Disassembler/X86/Handlers/Mov/MovRegImm32Handler.cs new file mode 100644 index 0000000..aa90d2e --- /dev/null +++ b/X86Disassembler/X86/Handlers/Mov/MovRegImm32Handler.cs @@ -0,0 +1,56 @@ +namespace X86Disassembler.X86.Handlers.Mov; + +/// +/// Handler for MOV r32, imm32 instruction (0xB8-0xBF) +/// +public class MovRegImm32Handler : InstructionHandler +{ + /// + /// Initializes a new instance of the MovRegImm32Handler class + /// + /// The buffer containing the code to decode + /// The instruction decoder that owns this handler + /// The length of the buffer + public MovRegImm32Handler(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 >= 0xB8 && opcode <= 0xBF; + } + + /// + /// Decodes a MOV r32, 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 = "mov"; + + // Register is encoded in the low 3 bits of the opcode + int reg = opcode & 0x07; + string regName = ModRMDecoder.GetRegisterName(reg, 32); + + // Read the immediate value + uint imm32 = Decoder.ReadUInt32(); + if (Decoder.GetPosition() > Length) + { + return false; + } + + // Set the operands + instruction.Operands = $"{regName}, 0x{imm32:X}"; + + return true; + } +} diff --git a/X86Disassembler/X86/Handlers/Mov/MovRegImm8Handler.cs b/X86Disassembler/X86/Handlers/Mov/MovRegImm8Handler.cs new file mode 100644 index 0000000..97d1c6b --- /dev/null +++ b/X86Disassembler/X86/Handlers/Mov/MovRegImm8Handler.cs @@ -0,0 +1,56 @@ +namespace X86Disassembler.X86.Handlers.Mov; + +/// +/// Handler for MOV r8, imm8 instruction (0xB0-0xB7) +/// +public class MovRegImm8Handler : InstructionHandler +{ + /// + /// Initializes a new instance of the MovRegImm8Handler class + /// + /// The buffer containing the code to decode + /// The instruction decoder that owns this handler + /// The length of the buffer + public MovRegImm8Handler(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 >= 0xB0 && opcode <= 0xB7; + } + + /// + /// Decodes a MOV r8, 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 = "mov"; + + // Register is encoded in the low 3 bits of the opcode + int reg = opcode & 0x07; + string regName = ModRMDecoder.GetRegisterName(reg, 8); + + // Read the immediate value + byte imm8 = Decoder.ReadByte(); + if (Decoder.GetPosition() > Length) + { + return false; + } + + // Set the operands + instruction.Operands = $"{regName}, 0x{imm8:X2}"; + + return true; + } +} diff --git a/X86Disassembler/X86/Handlers/Mov/MovRegMemHandler.cs b/X86Disassembler/X86/Handlers/Mov/MovRegMemHandler.cs new file mode 100644 index 0000000..7599714 --- /dev/null +++ b/X86Disassembler/X86/Handlers/Mov/MovRegMemHandler.cs @@ -0,0 +1,70 @@ +namespace X86Disassembler.X86.Handlers.Mov; + +/// +/// Handler for MOV r32, r/m32 instruction (0x8B) and MOV r8, r/m8 instruction (0x8A) +/// +public class MovRegMemHandler : InstructionHandler +{ + /// + /// Initializes a new instance of the MovRegMemHandler class + /// + /// The buffer containing the code to decode + /// The instruction decoder that owns this handler + /// The length of the buffer + public MovRegMemHandler(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 == 0x8A || opcode == 0x8B; + } + + /// + /// Decodes a MOV r32, r/m32 or MOV r8, r/m8 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 = "mov"; + + int position = Decoder.GetPosition(); + + if (position >= Length) + { + return false; + } + + // Determine operand size (0 = 8-bit, 1 = 32-bit) + bool operandSize32 = (opcode & 0x01) != 0; + int operandSize = operandSize32 ? 32 : 8; + + // Read the ModR/M byte + var (mod, reg, rm, memOperand) = ModRMDecoder.ReadModRM(); + + // Get register name based on size + string regName = ModRMDecoder.GetRegisterName(reg, operandSize); + + // For mod == 3, both operands are registers + if (mod == 3) + { + string rmRegName = ModRMDecoder.GetRegisterName(rm, operandSize); + instruction.Operands = $"{rmRegName}, {regName}"; + } + else // Memory operand + { + instruction.Operands = $"{memOperand}, {regName}"; + } + + return true; + } +} diff --git a/X86Disassembler/X86/Handlers/Pop/PopRegHandler.cs b/X86Disassembler/X86/Handlers/Pop/PopRegHandler.cs new file mode 100644 index 0000000..ea920e4 --- /dev/null +++ b/X86Disassembler/X86/Handlers/Pop/PopRegHandler.cs @@ -0,0 +1,49 @@ +namespace X86Disassembler.X86.Handlers.Pop; + +/// +/// Handler for POP r32 instruction (0x58-0x5F) +/// +public class PopRegHandler : InstructionHandler +{ + /// + /// Initializes a new instance of the PopRegHandler class + /// + /// The buffer containing the code to decode + /// The instruction decoder that owns this handler + /// The length of the buffer + public PopRegHandler(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 >= 0x58 && opcode <= 0x5F; + } + + /// + /// Decodes a POP 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) + { + // Set the mnemonic + instruction.Mnemonic = "pop"; + + // Register is encoded in the low 3 bits of the opcode + int reg = opcode & 0x07; + string regName = ModRMDecoder.GetRegisterName(reg, 32); + + // Set the operands + instruction.Operands = regName; + + return true; + } +} diff --git a/X86Disassembler/X86/Handlers/Push/PushImm32Handler.cs b/X86Disassembler/X86/Handlers/Push/PushImm32Handler.cs new file mode 100644 index 0000000..dbcd2e1 --- /dev/null +++ b/X86Disassembler/X86/Handlers/Push/PushImm32Handler.cs @@ -0,0 +1,52 @@ +namespace X86Disassembler.X86.Handlers.Push; + +/// +/// Handler for PUSH imm32 instruction (0x68) +/// +public class PushImm32Handler : InstructionHandler +{ + /// + /// Initializes a new instance of the PushImm32Handler class + /// + /// The buffer containing the code to decode + /// The instruction decoder that owns this handler + /// The length of the buffer + public PushImm32Handler(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 == 0x68; + } + + /// + /// Decodes a PUSH 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 = "push"; + + // Read the immediate value + uint imm32 = Decoder.ReadUInt32(); + if (Decoder.GetPosition() > Length) + { + return false; + } + + // Set the operands + instruction.Operands = $"0x{imm32:X}"; + + return true; + } +} diff --git a/X86Disassembler/X86/Handlers/Push/PushImm8Handler.cs b/X86Disassembler/X86/Handlers/Push/PushImm8Handler.cs new file mode 100644 index 0000000..6c4e314 --- /dev/null +++ b/X86Disassembler/X86/Handlers/Push/PushImm8Handler.cs @@ -0,0 +1,52 @@ +namespace X86Disassembler.X86.Handlers.Push; + +/// +/// Handler for PUSH imm8 instruction (0x6A) +/// +public class PushImm8Handler : InstructionHandler +{ + /// + /// Initializes a new instance of the PushImm8Handler class + /// + /// The buffer containing the code to decode + /// The instruction decoder that owns this handler + /// The length of the buffer + public PushImm8Handler(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 == 0x6A; + } + + /// + /// Decodes a PUSH 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 = "push"; + + // Read the immediate value + byte imm8 = Decoder.ReadByte(); + if (Decoder.GetPosition() > Length) + { + return false; + } + + // Set the operands + instruction.Operands = $"0x{imm8:X2}"; + + return true; + } +} diff --git a/X86Disassembler/X86/Handlers/Push/PushRegHandler.cs b/X86Disassembler/X86/Handlers/Push/PushRegHandler.cs new file mode 100644 index 0000000..8a7985f --- /dev/null +++ b/X86Disassembler/X86/Handlers/Push/PushRegHandler.cs @@ -0,0 +1,49 @@ +namespace X86Disassembler.X86.Handlers.Push; + +/// +/// Handler for PUSH r32 instruction (0x50-0x57) +/// +public class PushRegHandler : InstructionHandler +{ + /// + /// Initializes a new instance of the PushRegHandler class + /// + /// The buffer containing the code to decode + /// The instruction decoder that owns this handler + /// The length of the buffer + public PushRegHandler(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 >= 0x50 && opcode <= 0x57; + } + + /// + /// Decodes a PUSH 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) + { + // Set the mnemonic + instruction.Mnemonic = "push"; + + // Register is encoded in the low 3 bits of the opcode + int reg = opcode & 0x07; + string regName = ModRMDecoder.GetRegisterName(reg, 32); + + // Set the operands + instruction.Operands = regName; + + return true; + } +} diff --git a/X86Disassembler/X86/Handlers/Xchg/XchgEaxRegHandler.cs b/X86Disassembler/X86/Handlers/Xchg/XchgEaxRegHandler.cs new file mode 100644 index 0000000..bf46c9e --- /dev/null +++ b/X86Disassembler/X86/Handlers/Xchg/XchgEaxRegHandler.cs @@ -0,0 +1,57 @@ +namespace X86Disassembler.X86.Handlers.Xchg; + +/// +/// Handler for XCHG EAX, r32 instruction (0x90-0x97) +/// +public class XchgEaxRegHandler : InstructionHandler +{ + /// + /// Initializes a new instance of the XchgEaxRegHandler class + /// + /// The buffer containing the code to decode + /// The instruction decoder that owns this handler + /// The length of the buffer + public XchgEaxRegHandler(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 >= 0x90 && opcode <= 0x97; + } + + /// + /// Decodes an XCHG EAX, 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) + { + // Special case for NOP (XCHG EAX, EAX) + if (opcode == 0x90) + { + instruction.Mnemonic = "nop"; + instruction.Operands = ""; + return true; + } + + // Set the mnemonic + instruction.Mnemonic = "xchg"; + + // Register is encoded in the low 3 bits of the opcode + int reg = opcode & 0x07; + string regName = ModRMDecoder.GetRegisterName(reg, 32); + + // Set the operands + instruction.Operands = $"eax, {regName}"; + + return true; + } +}