diff --git a/X86Disassembler/X86/Handlers/Group1/CmpImmWithRm8Handler.cs b/X86Disassembler/X86/Handlers/Group1/CmpImmWithRm8Handler.cs new file mode 100644 index 0000000..2cd59f8 --- /dev/null +++ b/X86Disassembler/X86/Handlers/Group1/CmpImmWithRm8Handler.cs @@ -0,0 +1,136 @@ +namespace X86Disassembler.X86.Handlers.Group1; + +/// +/// Handler for CMP r/m8, imm8 instruction (0x80 /7) +/// +public class CmpImmWithRm8Handler : InstructionHandler +{ + /// + /// Initializes a new instance of the CmpImmWithRm8Handler class + /// + /// The buffer containing the code to decode + /// The instruction decoder that owns this handler + /// The length of the buffer + public CmpImmWithRm8Handler(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) + { + if (opcode != 0x80) + return false; + + // Check if the reg field of the ModR/M byte is 7 (CMP) + int position = Decoder.GetPosition(); + if (position >= Length) + return false; + + byte modRM = CodeBuffer[position]; + byte reg = (byte)((modRM & 0x38) >> 3); + + return reg == 7; // 7 = CMP + } + + /// + /// Decodes a CMP r/m8, 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) + { + int position = Decoder.GetPosition(); + + if (position >= Length) + { + return false; + } + + // Read the ModR/M byte + byte modRM = CodeBuffer[position++]; + + // Extract the fields from the ModR/M byte + byte mod = (byte)((modRM & 0xC0) >> 6); + byte reg = (byte)((modRM & 0x38) >> 3); + byte rm = (byte)(modRM & 0x07); + + // CMP r/m8, imm8 is encoded as 80 /7 + if (reg != 7) + { + return false; + } + + // Process SIB and displacement bytes if needed + if (mod != 3 && rm == 4) // SIB byte present + { + if (position >= Length) + { + return false; + } + position++; // Skip SIB byte + } + + // Handle displacement + if ((mod == 1 && position >= Length) || (mod == 2 && position + 3 >= Length)) + { + return false; + } + + if (mod == 1) // 8-bit displacement + { + position++; + } + else if (mod == 2) // 32-bit displacement + { + position += 4; + } + + // Read the immediate byte + if (position >= Length) + { + return false; + } + + byte imm8 = CodeBuffer[position++]; + Decoder.SetPosition(position); + + // Set the mnemonic + instruction.Mnemonic = "cmp"; + + // Get the operand string + string operand; + if (mod != 3) // Memory operand + { + string memOperand = ModRMDecoder.DecodeModRM(mod, rm, true); + + // Replace the size prefix with "byte ptr" + if (memOperand.StartsWith("qword ptr ")) + { + operand = memOperand.Replace("qword ptr ", "byte ptr "); + } + else if (memOperand.StartsWith("dword ptr ")) + { + operand = memOperand.Replace("dword ptr ", "byte ptr "); + } + else + { + operand = $"byte ptr {memOperand}"; + } + } + else // Register operand + { + operand = GetRegister8(rm); + } + + // Set the operands + instruction.Operands = $"{operand}, 0x{imm8:X2}"; + + return true; + } +} diff --git a/X86Disassembler/X86/Handlers/Group1/OrImmWithRm8Handler.cs b/X86Disassembler/X86/Handlers/Group1/OrImmWithRm8Handler.cs new file mode 100644 index 0000000..1012b32 --- /dev/null +++ b/X86Disassembler/X86/Handlers/Group1/OrImmWithRm8Handler.cs @@ -0,0 +1,136 @@ +namespace X86Disassembler.X86.Handlers.Group1; + +/// +/// Handler for OR r/m8, imm8 instruction (0x80 /1) +/// +public class OrImmWithRm8Handler : InstructionHandler +{ + /// + /// Initializes a new instance of the OrImmWithRm8Handler class + /// + /// The buffer containing the code to decode + /// The instruction decoder that owns this handler + /// The length of the buffer + public OrImmWithRm8Handler(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) + { + if (opcode != 0x80) + return false; + + // Check if the reg field of the ModR/M byte is 1 (OR) + int position = Decoder.GetPosition(); + if (position >= Length) + return false; + + byte modRM = CodeBuffer[position]; + byte reg = (byte)((modRM & 0x38) >> 3); + + return reg == 1; // 1 = OR + } + + /// + /// Decodes an OR r/m8, 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) + { + int position = Decoder.GetPosition(); + + if (position >= Length) + { + return false; + } + + // Read the ModR/M byte + byte modRM = CodeBuffer[position++]; + + // Extract the fields from the ModR/M byte + byte mod = (byte)((modRM & 0xC0) >> 6); + byte reg = (byte)((modRM & 0x38) >> 3); + byte rm = (byte)(modRM & 0x07); + + // OR r/m8, imm8 is encoded as 80 /1 + if (reg != 1) + { + return false; + } + + // Process SIB and displacement bytes if needed + if (mod != 3 && rm == 4) // SIB byte present + { + if (position >= Length) + { + return false; + } + position++; // Skip SIB byte + } + + // Handle displacement + if ((mod == 1 && position >= Length) || (mod == 2 && position + 3 >= Length)) + { + return false; + } + + if (mod == 1) // 8-bit displacement + { + position++; + } + else if (mod == 2) // 32-bit displacement + { + position += 4; + } + + // Read the immediate byte + if (position >= Length) + { + return false; + } + + byte imm8 = CodeBuffer[position++]; + Decoder.SetPosition(position); + + // Set the mnemonic + instruction.Mnemonic = "or"; + + // Get the operand string + string operand; + if (mod != 3) // Memory operand + { + string memOperand = ModRMDecoder.DecodeModRM(mod, rm, true); + + // Replace the size prefix with "byte ptr" + if (memOperand.StartsWith("qword ptr ")) + { + operand = memOperand.Replace("qword ptr ", "byte ptr "); + } + else if (memOperand.StartsWith("dword ptr ")) + { + operand = memOperand.Replace("dword ptr ", "byte ptr "); + } + else + { + operand = $"byte ptr {memOperand}"; + } + } + else // Register operand + { + operand = GetRegister8(rm); + } + + // Set the operands + instruction.Operands = $"{operand}, 0x{imm8:X2}"; + + return true; + } +} diff --git a/X86Disassembler/X86/OpcodeMap.cs b/X86Disassembler/X86/OpcodeMap.cs index a157e70..55770c2 100644 --- a/X86Disassembler/X86/OpcodeMap.cs +++ b/X86Disassembler/X86/OpcodeMap.cs @@ -91,9 +91,9 @@ public static class OpcodeMap OneByteOpcodes[0x05] = "add"; // ADD EAX, imm32 // Group 1 instructions (ADD, OR, ADC, SBB, AND, SUB, XOR, CMP) - OneByteOpcodes[0x80] = "group1b"; - OneByteOpcodes[0x81] = "group1d"; - OneByteOpcodes[0x83] = "group1s"; // Sign-extended immediate + OneByteOpcodes[0x80] = "group1b"; // Group 1 8-bit operations with immediate 8-bit + OneByteOpcodes[0x81] = "group1d"; // Group 1 32-bit operations with immediate 32-bit + OneByteOpcodes[0x83] = "group1ds"; // Group 1 32-bit operations with immediate 8-bit sign-extended // Group 3 instructions (TEST, NOT, NEG, MUL, IMUL, DIV, IDIV) OneByteOpcodes[0xF6] = "group3b"; // 8-bit operations