namespace X86Disassembler.X86.Handlers; /// /// Handler for Group 3 instructions (TEST, NOT, NEG, MUL, IMUL, DIV, IDIV) /// public class Group3Handler : InstructionHandler { /// /// Initializes a new instance of the Group3Handler class /// /// The buffer containing the code to decode /// The instruction decoder that owns this handler /// The length of the buffer public Group3Handler(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 OpcodeMap.IsGroup3Opcode(opcode); } /// /// Decodes a Group 3 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) { int position = Decoder.GetPosition(); if (position >= Length) { return false; } // Read the ModR/M byte var (mod, reg, rm, destOperand) = ModRMDecoder.ReadModRM(); // Determine the operation based on reg field instruction.Mnemonic = OpcodeMap.Group3Operations[reg]; // For TEST instruction (reg = 0), we need to read an immediate value if (reg == 0) // TEST { position = Decoder.GetPosition(); string immOperand; switch (opcode) { case 0xF6: // 8-bit TEST if (position < Length) { byte imm8 = CodeBuffer[position]; Decoder.SetPosition(position + 1); immOperand = $"0x{imm8:X2}"; } else { immOperand = "???"; } break; case 0xF7: // 32-bit TEST if (position + 3 < Length) { uint imm32 = BitConverter.ToUInt32(CodeBuffer, position); Decoder.SetPosition(position + 4); immOperand = $"0x{imm32:X8}"; } else { immOperand = "???"; } break; default: return false; } // Set the operands instruction.Operands = $"{destOperand}, {immOperand}"; } else { // For other Group 3 instructions (NOT, NEG, MUL, etc.), there's only one operand instruction.Operands = destOperand; } return true; } }