diff --git a/X86Disassembler/X86/Handlers/ArithmeticHandler.cs b/X86Disassembler/X86/Handlers/ArithmeticHandler.cs new file mode 100644 index 0000000..f4e545e --- /dev/null +++ b/X86Disassembler/X86/Handlers/ArithmeticHandler.cs @@ -0,0 +1,126 @@ +namespace X86Disassembler.X86.Handlers; + +/// +/// Handler for arithmetic and logical instructions (ADD, SUB, AND, OR, XOR, etc.) +/// +public class ArithmeticHandler : InstructionHandler +{ + /// + /// Initializes a new instance of the ArithmeticHandler class + /// + /// The buffer containing the code to decode + /// The instruction decoder that owns this handler + /// The length of the buffer + public ArithmeticHandler(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) + { + // XOR instructions + if (opcode >= 0x30 && opcode <= 0x35) + { + return true; + } + + return false; + } + + /// + /// Decodes an arithmetic or logical 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 based on the opcode + instruction.Mnemonic = OpcodeMap.GetMnemonic(opcode); + + int position = Decoder.GetPosition(); + + if (position >= Length) + { + return false; + } + + switch (opcode) + { + case 0x30: // XOR r/m8, r8 + case 0x31: // XOR r/m32, r32 + { + // Read the ModR/M byte + var (mod, reg, rm, destOperand) = ModRMDecoder.ReadModRM(); + + // Determine the source register + string sourceReg; + if (opcode == 0x30) // 8-bit registers + { + sourceReg = ModRMDecoder.GetRegister8(reg); + } + else // 32-bit registers + { + sourceReg = ModRMDecoder.GetRegister32(reg); + } + + // Set the operands + instruction.Operands = $"{destOperand}, {sourceReg}"; + return true; + } + + case 0x32: // XOR r8, r/m8 + case 0x33: // XOR r32, r/m32 + { + // Read the ModR/M byte + var (mod, reg, rm, srcOperand) = ModRMDecoder.ReadModRM(); + + // Determine the destination register + string destReg; + if (opcode == 0x32) // 8-bit registers + { + destReg = ModRMDecoder.GetRegister8(reg); + } + else // 32-bit registers + { + destReg = ModRMDecoder.GetRegister32(reg); + } + + // Set the operands + instruction.Operands = $"{destReg}, {srcOperand}"; + return true; + } + + case 0x34: // XOR AL, imm8 + { + if (position < Length) + { + byte imm8 = CodeBuffer[position]; + Decoder.SetPosition(position + 1); + instruction.Operands = $"al, 0x{imm8:X2}"; + return true; + } + break; + } + + case 0x35: // XOR EAX, imm32 + { + if (position + 3 < Length) + { + uint imm32 = BitConverter.ToUInt32(CodeBuffer, position); + Decoder.SetPosition(position + 4); + instruction.Operands = $"eax, 0x{imm32:X8}"; + return true; + } + break; + } + } + + return false; + } +} diff --git a/X86Disassembler/X86/InstructionDecoder.cs b/X86Disassembler/X86/InstructionDecoder.cs index f95c21e..e91a948 100644 --- a/X86Disassembler/X86/InstructionDecoder.cs +++ b/X86Disassembler/X86/InstructionDecoder.cs @@ -50,7 +50,8 @@ public class InstructionDecoder new DataTransferHandler(_codeBuffer, this, _length), new ControlFlowHandler(_codeBuffer, this, _length), new Group3Handler(_codeBuffer, this, _length), - new TestHandler(_codeBuffer, this, _length) + new TestHandler(_codeBuffer, this, _length), + new ArithmeticHandler(_codeBuffer, this, _length) }; } diff --git a/X86Disassembler/X86/OpcodeMap.cs b/X86Disassembler/X86/OpcodeMap.cs index bad0108..743c07e 100644 --- a/X86Disassembler/X86/OpcodeMap.cs +++ b/X86Disassembler/X86/OpcodeMap.cs @@ -118,6 +118,14 @@ public class OpcodeMap OneByteOpcodes[0x6A] = "push"; // PUSH imm8 OneByteOpcodes[0xCD] = "int"; // INT imm8 OneByteOpcodes[0xE3] = "jecxz"; // JECXZ rel8 + + // XOR instructions + OneByteOpcodes[0x30] = "xor"; // XOR r/m8, r8 + OneByteOpcodes[0x31] = "xor"; // XOR r/m32, r32 + OneByteOpcodes[0x32] = "xor"; // XOR r8, r/m8 + OneByteOpcodes[0x33] = "xor"; // XOR r32, r/m32 + OneByteOpcodes[0x34] = "xor"; // XOR AL, imm8 + OneByteOpcodes[0x35] = "xor"; // XOR EAX, imm32 } ///