diff --git a/X86Disassembler/X86/Handlers/Group1/AdcImmToRm32Handler.cs b/X86Disassembler/X86/Handlers/Group1/AdcImmToRm32Handler.cs new file mode 100644 index 0000000..ce9a7f1 --- /dev/null +++ b/X86Disassembler/X86/Handlers/Group1/AdcImmToRm32Handler.cs @@ -0,0 +1,84 @@ +namespace X86Disassembler.X86.Handlers.Group1; + +/// +/// Handler for ADC r/m32, imm32 instruction (0x81 /2) +/// +public class AdcImmToRm32Handler : Group1BaseHandler +{ + /// + /// Initializes a new instance of the AdcImmToRm32Handler class + /// + /// The buffer containing the code to decode + /// The instruction decoder that owns this handler + /// The length of the buffer + public AdcImmToRm32Handler(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 != 0x81) + return false; + + // Check if the reg field of the ModR/M byte is 2 (ADC) + int position = Decoder.GetPosition(); + if (position >= Length) + return false; + + byte modRM = CodeBuffer[position]; + byte reg = (byte)((modRM & 0x38) >> 3); + + return reg == 2; // 2 = ADC + } + + /// + /// Decodes an ADC r/m32, 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 = "adc"; + + int position = Decoder.GetPosition(); + + if (position >= Length) + { + return false; + } + + // Read the ModR/M byte + byte modRM = CodeBuffer[position++]; + Decoder.SetPosition(position); + + // Extract the fields from the ModR/M byte + byte mod = (byte)((modRM & 0xC0) >> 6); + byte reg = (byte)((modRM & 0x38) >> 3); // Should be 2 for ADC + byte rm = (byte)(modRM & 0x07); + + // Decode the destination operand + string destOperand = _modRMDecoder.DecodeModRM(mod, rm, false); + + // Read the immediate value + if (position + 3 >= Length) + { + return false; + } + + uint imm32 = BitConverter.ToUInt32(CodeBuffer, position); + Decoder.SetPosition(position + 4); + + // Set the operands + instruction.Operands = $"{destOperand}, 0x{imm32:X8}"; + + return true; + } +} diff --git a/X86Disassembler/X86/Handlers/Group1/AdcImmToRm32SignExtendedHandler.cs b/X86Disassembler/X86/Handlers/Group1/AdcImmToRm32SignExtendedHandler.cs new file mode 100644 index 0000000..5e4b318 --- /dev/null +++ b/X86Disassembler/X86/Handlers/Group1/AdcImmToRm32SignExtendedHandler.cs @@ -0,0 +1,85 @@ +namespace X86Disassembler.X86.Handlers.Group1; + +/// +/// Handler for ADC r/m32, imm8 (sign-extended) instruction (0x83 /2) +/// +public class AdcImmToRm32SignExtendedHandler : Group1BaseHandler +{ + /// + /// Initializes a new instance of the AdcImmToRm32SignExtendedHandler class + /// + /// The buffer containing the code to decode + /// The instruction decoder that owns this handler + /// The length of the buffer + public AdcImmToRm32SignExtendedHandler(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 != 0x83) + return false; + + // Check if the reg field of the ModR/M byte is 2 (ADC) + int position = Decoder.GetPosition(); + if (position >= Length) + return false; + + byte modRM = CodeBuffer[position]; + byte reg = (byte)((modRM & 0x38) >> 3); + + return reg == 2; // 2 = ADC + } + + /// + /// Decodes an ADC r/m32, imm8 (sign-extended) 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 = "adc"; + + int position = Decoder.GetPosition(); + + if (position >= Length) + { + return false; + } + + // Read the ModR/M byte + byte modRM = CodeBuffer[position++]; + Decoder.SetPosition(position); + + // Extract the fields from the ModR/M byte + byte mod = (byte)((modRM & 0xC0) >> 6); + byte reg = (byte)((modRM & 0x38) >> 3); // Should be 2 for ADC + byte rm = (byte)(modRM & 0x07); + + // Decode the destination operand + string destOperand = _modRMDecoder.DecodeModRM(mod, rm, false); + + // Read the immediate value (sign-extended from 8 to 32 bits) + if (position >= Length) + { + return false; + } + + sbyte imm8 = (sbyte)CodeBuffer[position]; + int imm32 = imm8; // Sign-extend to 32 bits + Decoder.SetPosition(position + 1); + + // Set the operands + instruction.Operands = $"{destOperand}, 0x{imm32:X8}"; + + return true; + } +} diff --git a/X86Disassembler/X86/Handlers/Group1/AddImmToRm32Handler.cs b/X86Disassembler/X86/Handlers/Group1/AddImmToRm32Handler.cs new file mode 100644 index 0000000..aef61de --- /dev/null +++ b/X86Disassembler/X86/Handlers/Group1/AddImmToRm32Handler.cs @@ -0,0 +1,84 @@ +namespace X86Disassembler.X86.Handlers.Group1; + +/// +/// Handler for ADD r/m32, imm32 instruction (0x81 /0) +/// +public class AddImmToRm32Handler : Group1BaseHandler +{ + /// + /// Initializes a new instance of the AddImmToRm32Handler class + /// + /// The buffer containing the code to decode + /// The instruction decoder that owns this handler + /// The length of the buffer + public AddImmToRm32Handler(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 != 0x81) + return false; + + // Check if the reg field of the ModR/M byte is 0 (ADD) + int position = Decoder.GetPosition(); + if (position >= Length) + return false; + + byte modRM = CodeBuffer[position]; + byte reg = (byte)((modRM & 0x38) >> 3); + + return reg == 0; // 0 = ADD + } + + /// + /// Decodes an ADD r/m32, 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 = "add"; + + int position = Decoder.GetPosition(); + + if (position >= Length) + { + return false; + } + + // Read the ModR/M byte + byte modRM = CodeBuffer[position++]; + Decoder.SetPosition(position); + + // Extract the fields from the ModR/M byte + byte mod = (byte)((modRM & 0xC0) >> 6); + byte reg = (byte)((modRM & 0x38) >> 3); // Should be 0 for ADD + byte rm = (byte)(modRM & 0x07); + + // Decode the destination operand + string destOperand = _modRMDecoder.DecodeModRM(mod, rm, false); + + // Read the immediate value + if (position + 3 >= Length) + { + return false; + } + + uint imm32 = BitConverter.ToUInt32(CodeBuffer, position); + Decoder.SetPosition(position + 4); + + // Set the operands + instruction.Operands = $"{destOperand}, 0x{imm32:X8}"; + + return true; + } +} diff --git a/X86Disassembler/X86/Handlers/Group1/AddImmToRm32SignExtendedHandler.cs b/X86Disassembler/X86/Handlers/Group1/AddImmToRm32SignExtendedHandler.cs new file mode 100644 index 0000000..d546f76 --- /dev/null +++ b/X86Disassembler/X86/Handlers/Group1/AddImmToRm32SignExtendedHandler.cs @@ -0,0 +1,85 @@ +namespace X86Disassembler.X86.Handlers.Group1; + +/// +/// Handler for ADD r/m32, imm8 (sign-extended) instruction (0x83 /0) +/// +public class AddImmToRm32SignExtendedHandler : Group1BaseHandler +{ + /// + /// Initializes a new instance of the AddImmToRm32SignExtendedHandler class + /// + /// The buffer containing the code to decode + /// The instruction decoder that owns this handler + /// The length of the buffer + public AddImmToRm32SignExtendedHandler(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 != 0x83) + return false; + + // Check if the reg field of the ModR/M byte is 0 (ADD) + int position = Decoder.GetPosition(); + if (position >= Length) + return false; + + byte modRM = CodeBuffer[position]; + byte reg = (byte)((modRM & 0x38) >> 3); + + return reg == 0; // 0 = ADD + } + + /// + /// Decodes an ADD r/m32, imm8 (sign-extended) 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 = "add"; + + int position = Decoder.GetPosition(); + + if (position >= Length) + { + return false; + } + + // Read the ModR/M byte + byte modRM = CodeBuffer[position++]; + Decoder.SetPosition(position); + + // Extract the fields from the ModR/M byte + byte mod = (byte)((modRM & 0xC0) >> 6); + byte reg = (byte)((modRM & 0x38) >> 3); // Should be 0 for ADD + byte rm = (byte)(modRM & 0x07); + + // Decode the destination operand + string destOperand = _modRMDecoder.DecodeModRM(mod, rm, false); + + // Read the immediate value + if (position >= Length) + { + return false; + } + + // Read the immediate value as a signed byte and sign-extend it + sbyte imm8 = (sbyte)CodeBuffer[position++]; + Decoder.SetPosition(position); + + // Set the operands + instruction.Operands = $"{destOperand}, 0x{(uint)imm8:X2}"; + + return true; + } +} diff --git a/X86Disassembler/X86/Handlers/Group1/AddImmToRm8Handler.cs b/X86Disassembler/X86/Handlers/Group1/AddImmToRm8Handler.cs new file mode 100644 index 0000000..be37a80 --- /dev/null +++ b/X86Disassembler/X86/Handlers/Group1/AddImmToRm8Handler.cs @@ -0,0 +1,84 @@ +namespace X86Disassembler.X86.Handlers.Group1; + +/// +/// Handler for ADD r/m8, imm8 instruction (0x80 /0) +/// +public class AddImmToRm8Handler : Group1BaseHandler +{ + /// + /// Initializes a new instance of the AddImmToRm8Handler class + /// + /// The buffer containing the code to decode + /// The instruction decoder that owns this handler + /// The length of the buffer + public AddImmToRm8Handler(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 0 (ADD) + int position = Decoder.GetPosition(); + if (position >= Length) + return false; + + byte modRM = CodeBuffer[position]; + byte reg = (byte)((modRM & 0x38) >> 3); + + return reg == 0; // 0 = ADD + } + + /// + /// Decodes an ADD 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) + { + // Set the mnemonic + instruction.Mnemonic = "add"; + + int position = Decoder.GetPosition(); + + if (position >= Length) + { + return false; + } + + // Read the ModR/M byte + byte modRM = CodeBuffer[position++]; + Decoder.SetPosition(position); + + // Extract the fields from the ModR/M byte + byte mod = (byte)((modRM & 0xC0) >> 6); + byte reg = (byte)((modRM & 0x38) >> 3); // Should be 0 for ADD + byte rm = (byte)(modRM & 0x07); + + // Decode the destination operand + string destOperand = _modRMDecoder.DecodeModRM(mod, rm, false); + + // Read the immediate value + if (position >= Length) + { + return false; + } + + byte imm8 = CodeBuffer[position++]; + Decoder.SetPosition(position); + + // Set the operands + instruction.Operands = $"{destOperand}, 0x{imm8:X2}"; + + return true; + } +} diff --git a/X86Disassembler/X86/Handlers/Group1/AndImmWithRm32Handler.cs b/X86Disassembler/X86/Handlers/Group1/AndImmWithRm32Handler.cs new file mode 100644 index 0000000..b58ef6d --- /dev/null +++ b/X86Disassembler/X86/Handlers/Group1/AndImmWithRm32Handler.cs @@ -0,0 +1,84 @@ +namespace X86Disassembler.X86.Handlers.Group1; + +/// +/// Handler for AND r/m32, imm32 instruction (0x81 /4) +/// +public class AndImmWithRm32Handler : Group1BaseHandler +{ + /// + /// Initializes a new instance of the AndImmWithRm32Handler class + /// + /// The buffer containing the code to decode + /// The instruction decoder that owns this handler + /// The length of the buffer + public AndImmWithRm32Handler(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 != 0x81) + return false; + + // Check if the reg field of the ModR/M byte is 4 (AND) + int position = Decoder.GetPosition(); + if (position >= Length) + return false; + + byte modRM = CodeBuffer[position]; + byte reg = (byte)((modRM & 0x38) >> 3); + + return reg == 4; // 4 = AND + } + + /// + /// Decodes an AND r/m32, 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 = "and"; + + int position = Decoder.GetPosition(); + + if (position >= Length) + { + return false; + } + + // Read the ModR/M byte + byte modRM = CodeBuffer[position++]; + Decoder.SetPosition(position); + + // Extract the fields from the ModR/M byte + byte mod = (byte)((modRM & 0xC0) >> 6); + byte reg = (byte)((modRM & 0x38) >> 3); // Should be 4 for AND + byte rm = (byte)(modRM & 0x07); + + // Decode the destination operand + string destOperand = _modRMDecoder.DecodeModRM(mod, rm, false); + + // Read the immediate value + if (position + 3 >= Length) + { + return false; + } + + uint imm32 = BitConverter.ToUInt32(CodeBuffer, position); + Decoder.SetPosition(position + 4); + + // Set the operands + instruction.Operands = $"{destOperand}, 0x{imm32:X8}"; + + return true; + } +} diff --git a/X86Disassembler/X86/Handlers/Group1/AndImmWithRm32SignExtendedHandler.cs b/X86Disassembler/X86/Handlers/Group1/AndImmWithRm32SignExtendedHandler.cs new file mode 100644 index 0000000..f2c7c68 --- /dev/null +++ b/X86Disassembler/X86/Handlers/Group1/AndImmWithRm32SignExtendedHandler.cs @@ -0,0 +1,85 @@ +namespace X86Disassembler.X86.Handlers.Group1; + +/// +/// Handler for AND r/m32, imm8 (sign-extended) instruction (0x83 /4) +/// +public class AndImmWithRm32SignExtendedHandler : Group1BaseHandler +{ + /// + /// Initializes a new instance of the AndImmWithRm32SignExtendedHandler class + /// + /// The buffer containing the code to decode + /// The instruction decoder that owns this handler + /// The length of the buffer + public AndImmWithRm32SignExtendedHandler(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 != 0x83) + return false; + + // Check if the reg field of the ModR/M byte is 4 (AND) + int position = Decoder.GetPosition(); + if (position >= Length) + return false; + + byte modRM = CodeBuffer[position]; + byte reg = (byte)((modRM & 0x38) >> 3); + + return reg == 4; // 4 = AND + } + + /// + /// Decodes an AND r/m32, imm8 (sign-extended) 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 = "and"; + + int position = Decoder.GetPosition(); + + if (position >= Length) + { + return false; + } + + // Read the ModR/M byte + byte modRM = CodeBuffer[position++]; + Decoder.SetPosition(position); + + // Extract the fields from the ModR/M byte + byte mod = (byte)((modRM & 0xC0) >> 6); + byte reg = (byte)((modRM & 0x38) >> 3); // Should be 4 for AND + byte rm = (byte)(modRM & 0x07); + + // Decode the destination operand + string destOperand = _modRMDecoder.DecodeModRM(mod, rm, false); + + // Read the immediate value (sign-extended from 8 to 32 bits) + if (position >= Length) + { + return false; + } + + sbyte imm8 = (sbyte)CodeBuffer[position]; + int imm32 = imm8; // Sign-extend to 32 bits + Decoder.SetPosition(position + 1); + + // Set the operands + instruction.Operands = $"{destOperand}, 0x{imm32:X8}"; + + return true; + } +} diff --git a/X86Disassembler/X86/Handlers/Group1/CmpImmWithRm32Handler.cs b/X86Disassembler/X86/Handlers/Group1/CmpImmWithRm32Handler.cs new file mode 100644 index 0000000..9e688ae --- /dev/null +++ b/X86Disassembler/X86/Handlers/Group1/CmpImmWithRm32Handler.cs @@ -0,0 +1,84 @@ +namespace X86Disassembler.X86.Handlers.Group1; + +/// +/// Handler for CMP r/m32, imm32 instruction (0x81 /7) +/// +public class CmpImmWithRm32Handler : Group1BaseHandler +{ + /// + /// Initializes a new instance of the CmpImmWithRm32Handler class + /// + /// The buffer containing the code to decode + /// The instruction decoder that owns this handler + /// The length of the buffer + public CmpImmWithRm32Handler(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 != 0x81) + 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/m32, 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 = "cmp"; + + int position = Decoder.GetPosition(); + + if (position >= Length) + { + return false; + } + + // Read the ModR/M byte + byte modRM = CodeBuffer[position++]; + Decoder.SetPosition(position); + + // Extract the fields from the ModR/M byte + byte mod = (byte)((modRM & 0xC0) >> 6); + byte reg = (byte)((modRM & 0x38) >> 3); // Should be 7 for CMP + byte rm = (byte)(modRM & 0x07); + + // Decode the destination operand + string destOperand = _modRMDecoder.DecodeModRM(mod, rm, false); + + // Read the immediate value + if (position + 3 >= Length) + { + return false; + } + + uint imm32 = BitConverter.ToUInt32(CodeBuffer, position); + Decoder.SetPosition(position + 4); + + // Set the operands + instruction.Operands = $"{destOperand}, 0x{imm32:X8}"; + + return true; + } +} diff --git a/X86Disassembler/X86/Handlers/Group1/CmpImmWithRm32SignExtendedHandler.cs b/X86Disassembler/X86/Handlers/Group1/CmpImmWithRm32SignExtendedHandler.cs new file mode 100644 index 0000000..b73d511 --- /dev/null +++ b/X86Disassembler/X86/Handlers/Group1/CmpImmWithRm32SignExtendedHandler.cs @@ -0,0 +1,85 @@ +namespace X86Disassembler.X86.Handlers.Group1; + +/// +/// Handler for CMP r/m32, imm8 (sign-extended) instruction (0x83 /7) +/// +public class CmpImmWithRm32SignExtendedHandler : Group1BaseHandler +{ + /// + /// Initializes a new instance of the CmpImmWithRm32SignExtendedHandler class + /// + /// The buffer containing the code to decode + /// The instruction decoder that owns this handler + /// The length of the buffer + public CmpImmWithRm32SignExtendedHandler(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 != 0x83) + 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/m32, imm8 (sign-extended) 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 = "cmp"; + + int position = Decoder.GetPosition(); + + if (position >= Length) + { + return false; + } + + // Read the ModR/M byte + byte modRM = CodeBuffer[position++]; + Decoder.SetPosition(position); + + // Extract the fields from the ModR/M byte + byte mod = (byte)((modRM & 0xC0) >> 6); + byte reg = (byte)((modRM & 0x38) >> 3); // Should be 7 for CMP + byte rm = (byte)(modRM & 0x07); + + // Decode the destination operand + string destOperand = _modRMDecoder.DecodeModRM(mod, rm, false); + + // Read the immediate value + if (position >= Length) + { + return false; + } + + // Read the immediate value as a signed byte and sign-extend it + sbyte imm8 = (sbyte)CodeBuffer[position++]; + Decoder.SetPosition(position); + + // Set the operands + instruction.Operands = $"{destOperand}, 0x{(uint)imm8:X2}"; + + return true; + } +} diff --git a/X86Disassembler/X86/Handlers/Group1/Group1BaseHandler.cs b/X86Disassembler/X86/Handlers/Group1/Group1BaseHandler.cs new file mode 100644 index 0000000..84dda24 --- /dev/null +++ b/X86Disassembler/X86/Handlers/Group1/Group1BaseHandler.cs @@ -0,0 +1,44 @@ +namespace X86Disassembler.X86.Handlers.Group1; + +/// +/// Base class for Group 1 instruction handlers (ADD, OR, ADC, SBB, AND, SUB, XOR, CMP) +/// +public abstract class Group1BaseHandler : InstructionHandler +{ + // ModR/M decoder + protected readonly ModRMDecoder _modRMDecoder; + + /// + /// Initializes a new instance of the Group1BaseHandler class + /// + /// The buffer containing the code to decode + /// The instruction decoder that owns this handler + /// The length of the buffer + protected Group1BaseHandler(byte[] codeBuffer, InstructionDecoder decoder, int length) + : base(codeBuffer, decoder, length) + { + _modRMDecoder = new ModRMDecoder(codeBuffer, decoder, length); + } + + /// + /// Gets the 32-bit register name for the given register index + /// + /// The register index + /// The register name + protected static string GetRegister32(byte reg) + { + string[] registerNames = { "eax", "ecx", "edx", "ebx", "esp", "ebp", "esi", "edi" }; + return registerNames[reg & 0x07]; + } + + /// + /// Gets the 8-bit register name for the given register index + /// + /// The register index + /// The register name + protected static string GetRegister8(byte reg) + { + string[] registerNames = { "al", "cl", "dl", "bl", "ah", "ch", "dh", "bh" }; + return registerNames[reg & 0x07]; + } +} diff --git a/X86Disassembler/X86/Handlers/Group1/OrImmToRm32Handler.cs b/X86Disassembler/X86/Handlers/Group1/OrImmToRm32Handler.cs new file mode 100644 index 0000000..055d548 --- /dev/null +++ b/X86Disassembler/X86/Handlers/Group1/OrImmToRm32Handler.cs @@ -0,0 +1,84 @@ +namespace X86Disassembler.X86.Handlers.Group1; + +/// +/// Handler for OR r/m32, imm32 instruction (0x81 /1) +/// +public class OrImmToRm32Handler : Group1BaseHandler +{ + /// + /// Initializes a new instance of the OrImmToRm32Handler class + /// + /// The buffer containing the code to decode + /// The instruction decoder that owns this handler + /// The length of the buffer + public OrImmToRm32Handler(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 != 0x81) + 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/m32, 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 = "or"; + + int position = Decoder.GetPosition(); + + if (position >= Length) + { + return false; + } + + // Read the ModR/M byte + byte modRM = CodeBuffer[position++]; + Decoder.SetPosition(position); + + // Extract the fields from the ModR/M byte + byte mod = (byte)((modRM & 0xC0) >> 6); + byte reg = (byte)((modRM & 0x38) >> 3); // Should be 1 for OR + byte rm = (byte)(modRM & 0x07); + + // Decode the destination operand + string destOperand = _modRMDecoder.DecodeModRM(mod, rm, false); + + // Read the immediate value + if (position + 3 >= Length) + { + return false; + } + + uint imm32 = BitConverter.ToUInt32(CodeBuffer, position); + Decoder.SetPosition(position + 4); + + // Set the operands + instruction.Operands = $"{destOperand}, 0x{imm32:X8}"; + + return true; + } +} diff --git a/X86Disassembler/X86/Handlers/Group1/OrImmToRm32SignExtendedHandler.cs b/X86Disassembler/X86/Handlers/Group1/OrImmToRm32SignExtendedHandler.cs new file mode 100644 index 0000000..7e9d204 --- /dev/null +++ b/X86Disassembler/X86/Handlers/Group1/OrImmToRm32SignExtendedHandler.cs @@ -0,0 +1,85 @@ +namespace X86Disassembler.X86.Handlers.Group1; + +/// +/// Handler for OR r/m32, imm8 (sign-extended) instruction (0x83 /1) +/// +public class OrImmToRm32SignExtendedHandler : Group1BaseHandler +{ + /// + /// Initializes a new instance of the OrImmToRm32SignExtendedHandler class + /// + /// The buffer containing the code to decode + /// The instruction decoder that owns this handler + /// The length of the buffer + public OrImmToRm32SignExtendedHandler(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 != 0x83) + 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/m32, imm8 (sign-extended) 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 = "or"; + + int position = Decoder.GetPosition(); + + if (position >= Length) + { + return false; + } + + // Read the ModR/M byte + byte modRM = CodeBuffer[position++]; + Decoder.SetPosition(position); + + // Extract the fields from the ModR/M byte + byte mod = (byte)((modRM & 0xC0) >> 6); + byte reg = (byte)((modRM & 0x38) >> 3); // Should be 1 for OR + byte rm = (byte)(modRM & 0x07); + + // Decode the destination operand + string destOperand = _modRMDecoder.DecodeModRM(mod, rm, false); + + // Read the immediate value (sign-extended from 8 to 32 bits) + if (position >= Length) + { + return false; + } + + sbyte imm8 = (sbyte)CodeBuffer[position]; + int imm32 = imm8; // Sign-extend to 32 bits + Decoder.SetPosition(position + 1); + + // Set the operands + instruction.Operands = $"{destOperand}, 0x{imm32:X8}"; + + return true; + } +} diff --git a/X86Disassembler/X86/Handlers/Group1/OrImmToRm8Handler.cs b/X86Disassembler/X86/Handlers/Group1/OrImmToRm8Handler.cs new file mode 100644 index 0000000..56f5db4 --- /dev/null +++ b/X86Disassembler/X86/Handlers/Group1/OrImmToRm8Handler.cs @@ -0,0 +1,84 @@ +namespace X86Disassembler.X86.Handlers.Group1; + +/// +/// Handler for OR r/m8, imm8 instruction (0x80 /1) +/// +public class OrImmToRm8Handler : Group1BaseHandler +{ + /// + /// Initializes a new instance of the OrImmToRm8Handler class + /// + /// The buffer containing the code to decode + /// The instruction decoder that owns this handler + /// The length of the buffer + public OrImmToRm8Handler(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) + { + // Set the mnemonic + instruction.Mnemonic = "or"; + + int position = Decoder.GetPosition(); + + if (position >= Length) + { + return false; + } + + // Read the ModR/M byte + byte modRM = CodeBuffer[position++]; + Decoder.SetPosition(position); + + // Extract the fields from the ModR/M byte + byte mod = (byte)((modRM & 0xC0) >> 6); + byte reg = (byte)((modRM & 0x38) >> 3); // Should be 1 for OR + byte rm = (byte)(modRM & 0x07); + + // Decode the destination operand + string destOperand = _modRMDecoder.DecodeModRM(mod, rm, false); + + // Read the immediate value + if (position >= Length) + { + return false; + } + + byte imm8 = CodeBuffer[position++]; + Decoder.SetPosition(position); + + // Set the operands + instruction.Operands = $"{destOperand}, 0x{imm8:X2}"; + + return true; + } +} diff --git a/X86Disassembler/X86/Handlers/Group1/SbbImmFromRm32Handler.cs b/X86Disassembler/X86/Handlers/Group1/SbbImmFromRm32Handler.cs new file mode 100644 index 0000000..c30f475 --- /dev/null +++ b/X86Disassembler/X86/Handlers/Group1/SbbImmFromRm32Handler.cs @@ -0,0 +1,84 @@ +namespace X86Disassembler.X86.Handlers.Group1; + +/// +/// Handler for SBB r/m32, imm32 instruction (0x81 /3) +/// +public class SbbImmFromRm32Handler : Group1BaseHandler +{ + /// + /// Initializes a new instance of the SbbImmFromRm32Handler class + /// + /// The buffer containing the code to decode + /// The instruction decoder that owns this handler + /// The length of the buffer + public SbbImmFromRm32Handler(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 != 0x81) + return false; + + // Check if the reg field of the ModR/M byte is 3 (SBB) + int position = Decoder.GetPosition(); + if (position >= Length) + return false; + + byte modRM = CodeBuffer[position]; + byte reg = (byte)((modRM & 0x38) >> 3); + + return reg == 3; // 3 = SBB + } + + /// + /// Decodes a SBB r/m32, 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 = "sbb"; + + int position = Decoder.GetPosition(); + + if (position >= Length) + { + return false; + } + + // Read the ModR/M byte + byte modRM = CodeBuffer[position++]; + Decoder.SetPosition(position); + + // Extract the fields from the ModR/M byte + byte mod = (byte)((modRM & 0xC0) >> 6); + byte reg = (byte)((modRM & 0x38) >> 3); // Should be 3 for SBB + byte rm = (byte)(modRM & 0x07); + + // Decode the destination operand + string destOperand = _modRMDecoder.DecodeModRM(mod, rm, false); + + // Read the immediate value + if (position + 3 >= Length) + { + return false; + } + + uint imm32 = BitConverter.ToUInt32(CodeBuffer, position); + Decoder.SetPosition(position + 4); + + // Set the operands + instruction.Operands = $"{destOperand}, 0x{imm32:X8}"; + + return true; + } +} diff --git a/X86Disassembler/X86/Handlers/Group1/SbbImmFromRm32SignExtendedHandler.cs b/X86Disassembler/X86/Handlers/Group1/SbbImmFromRm32SignExtendedHandler.cs new file mode 100644 index 0000000..0dce041 --- /dev/null +++ b/X86Disassembler/X86/Handlers/Group1/SbbImmFromRm32SignExtendedHandler.cs @@ -0,0 +1,85 @@ +namespace X86Disassembler.X86.Handlers.Group1; + +/// +/// Handler for SBB r/m32, imm8 (sign-extended) instruction (0x83 /3) +/// +public class SbbImmFromRm32SignExtendedHandler : Group1BaseHandler +{ + /// + /// Initializes a new instance of the SbbImmFromRm32SignExtendedHandler class + /// + /// The buffer containing the code to decode + /// The instruction decoder that owns this handler + /// The length of the buffer + public SbbImmFromRm32SignExtendedHandler(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 != 0x83) + return false; + + // Check if the reg field of the ModR/M byte is 3 (SBB) + int position = Decoder.GetPosition(); + if (position >= Length) + return false; + + byte modRM = CodeBuffer[position]; + byte reg = (byte)((modRM & 0x38) >> 3); + + return reg == 3; // 3 = SBB + } + + /// + /// Decodes a SBB r/m32, imm8 (sign-extended) 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 = "sbb"; + + int position = Decoder.GetPosition(); + + if (position >= Length) + { + return false; + } + + // Read the ModR/M byte + byte modRM = CodeBuffer[position++]; + Decoder.SetPosition(position); + + // Extract the fields from the ModR/M byte + byte mod = (byte)((modRM & 0xC0) >> 6); + byte reg = (byte)((modRM & 0x38) >> 3); // Should be 3 for SBB + byte rm = (byte)(modRM & 0x07); + + // Decode the destination operand + string destOperand = _modRMDecoder.DecodeModRM(mod, rm, false); + + // Read the immediate value (sign-extended from 8 to 32 bits) + if (position >= Length) + { + return false; + } + + sbyte imm8 = (sbyte)CodeBuffer[position]; + int imm32 = imm8; // Sign-extend to 32 bits + Decoder.SetPosition(position + 1); + + // Set the operands + instruction.Operands = $"{destOperand}, 0x{imm32:X8}"; + + return true; + } +} diff --git a/X86Disassembler/X86/Handlers/Group1/SubImmFromRm32Handler.cs b/X86Disassembler/X86/Handlers/Group1/SubImmFromRm32Handler.cs new file mode 100644 index 0000000..e696c53 --- /dev/null +++ b/X86Disassembler/X86/Handlers/Group1/SubImmFromRm32Handler.cs @@ -0,0 +1,84 @@ +namespace X86Disassembler.X86.Handlers.Group1; + +/// +/// Handler for SUB r/m32, imm32 instruction (0x81 /5) +/// +public class SubImmFromRm32Handler : Group1BaseHandler +{ + /// + /// Initializes a new instance of the SubImmFromRm32Handler class + /// + /// The buffer containing the code to decode + /// The instruction decoder that owns this handler + /// The length of the buffer + public SubImmFromRm32Handler(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 != 0x81) + return false; + + // Check if the reg field of the ModR/M byte is 5 (SUB) + int position = Decoder.GetPosition(); + if (position >= Length) + return false; + + byte modRM = CodeBuffer[position]; + byte reg = (byte)((modRM & 0x38) >> 3); + + return reg == 5; // 5 = SUB + } + + /// + /// Decodes a SUB r/m32, 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 = "sub"; + + int position = Decoder.GetPosition(); + + if (position >= Length) + { + return false; + } + + // Read the ModR/M byte + byte modRM = CodeBuffer[position++]; + Decoder.SetPosition(position); + + // Extract the fields from the ModR/M byte + byte mod = (byte)((modRM & 0xC0) >> 6); + byte reg = (byte)((modRM & 0x38) >> 3); // Should be 5 for SUB + byte rm = (byte)(modRM & 0x07); + + // Decode the destination operand + string destOperand = _modRMDecoder.DecodeModRM(mod, rm, false); + + // Read the immediate value + if (position + 3 >= Length) + { + return false; + } + + uint imm32 = BitConverter.ToUInt32(CodeBuffer, position); + Decoder.SetPosition(position + 4); + + // Set the operands + instruction.Operands = $"{destOperand}, 0x{imm32:X8}"; + + return true; + } +} diff --git a/X86Disassembler/X86/Handlers/Group1/SubImmFromRm32SignExtendedHandler.cs b/X86Disassembler/X86/Handlers/Group1/SubImmFromRm32SignExtendedHandler.cs new file mode 100644 index 0000000..84ee45a --- /dev/null +++ b/X86Disassembler/X86/Handlers/Group1/SubImmFromRm32SignExtendedHandler.cs @@ -0,0 +1,85 @@ +namespace X86Disassembler.X86.Handlers.Group1; + +/// +/// Handler for SUB r/m32, imm8 (sign-extended) instruction (0x83 /5) +/// +public class SubImmFromRm32SignExtendedHandler : Group1BaseHandler +{ + /// + /// Initializes a new instance of the SubImmFromRm32SignExtendedHandler class + /// + /// The buffer containing the code to decode + /// The instruction decoder that owns this handler + /// The length of the buffer + public SubImmFromRm32SignExtendedHandler(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 != 0x83) + return false; + + // Check if the reg field of the ModR/M byte is 5 (SUB) + int position = Decoder.GetPosition(); + if (position >= Length) + return false; + + byte modRM = CodeBuffer[position]; + byte reg = (byte)((modRM & 0x38) >> 3); + + return reg == 5; // 5 = SUB + } + + /// + /// Decodes a SUB r/m32, imm8 (sign-extended) 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 = "sub"; + + int position = Decoder.GetPosition(); + + if (position >= Length) + { + return false; + } + + // Read the ModR/M byte + byte modRM = CodeBuffer[position++]; + Decoder.SetPosition(position); + + // Extract the fields from the ModR/M byte + byte mod = (byte)((modRM & 0xC0) >> 6); + byte reg = (byte)((modRM & 0x38) >> 3); // Should be 5 for SUB + byte rm = (byte)(modRM & 0x07); + + // Decode the destination operand + string destOperand = _modRMDecoder.DecodeModRM(mod, rm, false); + + // Read the immediate value + if (position >= Length) + { + return false; + } + + // Read the immediate value as a signed byte and sign-extend it + sbyte imm8 = (sbyte)CodeBuffer[position++]; + Decoder.SetPosition(position); + + // Set the operands + instruction.Operands = $"{destOperand}, 0x{(uint)imm8:X2}"; + + return true; + } +} diff --git a/X86Disassembler/X86/Handlers/Group1/XorImmWithRm32Handler.cs b/X86Disassembler/X86/Handlers/Group1/XorImmWithRm32Handler.cs new file mode 100644 index 0000000..7b5a8cb --- /dev/null +++ b/X86Disassembler/X86/Handlers/Group1/XorImmWithRm32Handler.cs @@ -0,0 +1,84 @@ +namespace X86Disassembler.X86.Handlers.Group1; + +/// +/// Handler for XOR r/m32, imm32 instruction (0x81 /6) +/// +public class XorImmWithRm32Handler : Group1BaseHandler +{ + /// + /// Initializes a new instance of the XorImmWithRm32Handler class + /// + /// The buffer containing the code to decode + /// The instruction decoder that owns this handler + /// The length of the buffer + public XorImmWithRm32Handler(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 != 0x81) + return false; + + // Check if the reg field of the ModR/M byte is 6 (XOR) + int position = Decoder.GetPosition(); + if (position >= Length) + return false; + + byte modRM = CodeBuffer[position]; + byte reg = (byte)((modRM & 0x38) >> 3); + + return reg == 6; // 6 = XOR + } + + /// + /// Decodes a XOR r/m32, 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 = "xor"; + + int position = Decoder.GetPosition(); + + if (position >= Length) + { + return false; + } + + // Read the ModR/M byte + byte modRM = CodeBuffer[position++]; + Decoder.SetPosition(position); + + // Extract the fields from the ModR/M byte + byte mod = (byte)((modRM & 0xC0) >> 6); + byte reg = (byte)((modRM & 0x38) >> 3); // Should be 6 for XOR + byte rm = (byte)(modRM & 0x07); + + // Decode the destination operand + string destOperand = _modRMDecoder.DecodeModRM(mod, rm, false); + + // Read the immediate value + if (position + 3 >= Length) + { + return false; + } + + uint imm32 = BitConverter.ToUInt32(CodeBuffer, position); + Decoder.SetPosition(position + 4); + + // Set the operands + instruction.Operands = $"{destOperand}, 0x{imm32:X8}"; + + return true; + } +} diff --git a/X86Disassembler/X86/Handlers/Group1/XorImmWithRm32SignExtendedHandler.cs b/X86Disassembler/X86/Handlers/Group1/XorImmWithRm32SignExtendedHandler.cs new file mode 100644 index 0000000..c446099 --- /dev/null +++ b/X86Disassembler/X86/Handlers/Group1/XorImmWithRm32SignExtendedHandler.cs @@ -0,0 +1,85 @@ +namespace X86Disassembler.X86.Handlers.Group1; + +/// +/// Handler for XOR r/m32, imm8 (sign-extended) instruction (0x83 /6) +/// +public class XorImmWithRm32SignExtendedHandler : Group1BaseHandler +{ + /// + /// Initializes a new instance of the XorImmWithRm32SignExtendedHandler class + /// + /// The buffer containing the code to decode + /// The instruction decoder that owns this handler + /// The length of the buffer + public XorImmWithRm32SignExtendedHandler(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 != 0x83) + return false; + + // Check if the reg field of the ModR/M byte is 6 (XOR) + int position = Decoder.GetPosition(); + if (position >= Length) + return false; + + byte modRM = CodeBuffer[position]; + byte reg = (byte)((modRM & 0x38) >> 3); + + return reg == 6; // 6 = XOR + } + + /// + /// Decodes a XOR r/m32, imm8 (sign-extended) 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 = "xor"; + + int position = Decoder.GetPosition(); + + if (position >= Length) + { + return false; + } + + // Read the ModR/M byte + byte modRM = CodeBuffer[position++]; + Decoder.SetPosition(position); + + // Extract the fields from the ModR/M byte + byte mod = (byte)((modRM & 0xC0) >> 6); + byte reg = (byte)((modRM & 0x38) >> 3); // Should be 6 for XOR + byte rm = (byte)(modRM & 0x07); + + // Decode the destination operand + string destOperand = _modRMDecoder.DecodeModRM(mod, rm, false); + + // Read the immediate value (sign-extended from 8 to 32 bits) + if (position >= Length) + { + return false; + } + + sbyte imm8 = (sbyte)CodeBuffer[position]; + int imm32 = imm8; // Sign-extend to 32 bits + Decoder.SetPosition(position + 1); + + // Set the operands + instruction.Operands = $"{destOperand}, 0x{imm32:X8}"; + + return true; + } +} diff --git a/X86Disassembler/X86/Handlers/Group3/DivRm32Handler.cs b/X86Disassembler/X86/Handlers/Group3/DivRm32Handler.cs new file mode 100644 index 0000000..f3a340f --- /dev/null +++ b/X86Disassembler/X86/Handlers/Group3/DivRm32Handler.cs @@ -0,0 +1,75 @@ +namespace X86Disassembler.X86.Handlers.Group3; + +/// +/// Handler for DIV r/m32 instruction (0xF7 /6) +/// +public class DivRm32Handler : Group3BaseHandler +{ + /// + /// Initializes a new instance of the DivRm32Handler class + /// + /// The buffer containing the code to decode + /// The instruction decoder that owns this handler + /// The length of the buffer + public DivRm32Handler(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 != 0xF7) + return false; + + // Check if the reg field of the ModR/M byte is 6 (DIV) + int position = Decoder.GetPosition(); + if (position >= Length) + return false; + + byte modRM = CodeBuffer[position]; + byte reg = (byte)((modRM & 0x38) >> 3); + + return reg == 6; // 6 = DIV + } + + /// + /// Decodes a DIV r/m32 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 = "div"; + + int position = Decoder.GetPosition(); + + if (position >= Length) + { + return false; + } + + // Read the ModR/M byte + byte modRM = CodeBuffer[position++]; + Decoder.SetPosition(position); + + // Extract the fields from the ModR/M byte + byte mod = (byte)((modRM & 0xC0) >> 6); + byte reg = (byte)((modRM & 0x38) >> 3); // Should be 6 for DIV + byte rm = (byte)(modRM & 0x07); + + // Decode the operand + string operand = _modRMDecoder.DecodeModRM(mod, rm, false); + + // Set the operands + instruction.Operands = operand; + + return true; + } +} diff --git a/X86Disassembler/X86/Handlers/Group3/Group3BaseHandler.cs b/X86Disassembler/X86/Handlers/Group3/Group3BaseHandler.cs new file mode 100644 index 0000000..bb80d72 --- /dev/null +++ b/X86Disassembler/X86/Handlers/Group3/Group3BaseHandler.cs @@ -0,0 +1,44 @@ +namespace X86Disassembler.X86.Handlers.Group3; + +/// +/// Base class for Group 3 instruction handlers (TEST, NOT, NEG, MUL, IMUL, DIV, IDIV) +/// +public abstract class Group3BaseHandler : InstructionHandler +{ + // ModR/M decoder + protected readonly ModRMDecoder _modRMDecoder; + + /// + /// Initializes a new instance of the Group3BaseHandler class + /// + /// The buffer containing the code to decode + /// The instruction decoder that owns this handler + /// The length of the buffer + protected Group3BaseHandler(byte[] codeBuffer, InstructionDecoder decoder, int length) + : base(codeBuffer, decoder, length) + { + _modRMDecoder = new ModRMDecoder(codeBuffer, decoder, length); + } + + /// + /// Gets the 32-bit register name for the given register index + /// + /// The register index + /// The register name + protected static string GetRegister32(byte reg) + { + string[] registerNames = { "eax", "ecx", "edx", "ebx", "esp", "ebp", "esi", "edi" }; + return registerNames[reg & 0x07]; + } + + /// + /// Gets the 8-bit register name for the given register index + /// + /// The register index + /// The register name + protected static string GetRegister8(byte reg) + { + string[] registerNames = { "al", "cl", "dl", "bl", "ah", "ch", "dh", "bh" }; + return registerNames[reg & 0x07]; + } +} diff --git a/X86Disassembler/X86/Handlers/Group3/IdivRm32Handler.cs b/X86Disassembler/X86/Handlers/Group3/IdivRm32Handler.cs new file mode 100644 index 0000000..b28a3ae --- /dev/null +++ b/X86Disassembler/X86/Handlers/Group3/IdivRm32Handler.cs @@ -0,0 +1,75 @@ +namespace X86Disassembler.X86.Handlers.Group3; + +/// +/// Handler for IDIV r/m32 instruction (0xF7 /7) +/// +public class IdivRm32Handler : Group3BaseHandler +{ + /// + /// Initializes a new instance of the IdivRm32Handler class + /// + /// The buffer containing the code to decode + /// The instruction decoder that owns this handler + /// The length of the buffer + public IdivRm32Handler(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 != 0xF7) + return false; + + // Check if the reg field of the ModR/M byte is 7 (IDIV) + int position = Decoder.GetPosition(); + if (position >= Length) + return false; + + byte modRM = CodeBuffer[position]; + byte reg = (byte)((modRM & 0x38) >> 3); + + return reg == 7; // 7 = IDIV + } + + /// + /// Decodes an IDIV r/m32 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 = "idiv"; + + int position = Decoder.GetPosition(); + + if (position >= Length) + { + return false; + } + + // Read the ModR/M byte + byte modRM = CodeBuffer[position++]; + Decoder.SetPosition(position); + + // Extract the fields from the ModR/M byte + byte mod = (byte)((modRM & 0xC0) >> 6); + byte reg = (byte)((modRM & 0x38) >> 3); // Should be 7 for IDIV + byte rm = (byte)(modRM & 0x07); + + // Decode the operand + string operand = _modRMDecoder.DecodeModRM(mod, rm, false); + + // Set the operands + instruction.Operands = operand; + + return true; + } +} diff --git a/X86Disassembler/X86/Handlers/Group3/ImulRm32Handler.cs b/X86Disassembler/X86/Handlers/Group3/ImulRm32Handler.cs new file mode 100644 index 0000000..5eb508c --- /dev/null +++ b/X86Disassembler/X86/Handlers/Group3/ImulRm32Handler.cs @@ -0,0 +1,75 @@ +namespace X86Disassembler.X86.Handlers.Group3; + +/// +/// Handler for IMUL r/m32 instruction (0xF7 /5) +/// +public class ImulRm32Handler : Group3BaseHandler +{ + /// + /// Initializes a new instance of the ImulRm32Handler class + /// + /// The buffer containing the code to decode + /// The instruction decoder that owns this handler + /// The length of the buffer + public ImulRm32Handler(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 != 0xF7) + return false; + + // Check if the reg field of the ModR/M byte is 5 (IMUL) + int position = Decoder.GetPosition(); + if (position >= Length) + return false; + + byte modRM = CodeBuffer[position]; + byte reg = (byte)((modRM & 0x38) >> 3); + + return reg == 5; // 5 = IMUL + } + + /// + /// Decodes an IMUL r/m32 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 = "imul"; + + int position = Decoder.GetPosition(); + + if (position >= Length) + { + return false; + } + + // Read the ModR/M byte + byte modRM = CodeBuffer[position++]; + Decoder.SetPosition(position); + + // Extract the fields from the ModR/M byte + byte mod = (byte)((modRM & 0xC0) >> 6); + byte reg = (byte)((modRM & 0x38) >> 3); // Should be 5 for IMUL + byte rm = (byte)(modRM & 0x07); + + // Decode the operand + string operand = _modRMDecoder.DecodeModRM(mod, rm, false); + + // Set the operands + instruction.Operands = operand; + + return true; + } +} diff --git a/X86Disassembler/X86/Handlers/Group3/MulRm32Handler.cs b/X86Disassembler/X86/Handlers/Group3/MulRm32Handler.cs new file mode 100644 index 0000000..a4cf90c --- /dev/null +++ b/X86Disassembler/X86/Handlers/Group3/MulRm32Handler.cs @@ -0,0 +1,75 @@ +namespace X86Disassembler.X86.Handlers.Group3; + +/// +/// Handler for MUL r/m32 instruction (0xF7 /4) +/// +public class MulRm32Handler : Group3BaseHandler +{ + /// + /// Initializes a new instance of the MulRm32Handler class + /// + /// The buffer containing the code to decode + /// The instruction decoder that owns this handler + /// The length of the buffer + public MulRm32Handler(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 != 0xF7) + return false; + + // Check if the reg field of the ModR/M byte is 4 (MUL) + int position = Decoder.GetPosition(); + if (position >= Length) + return false; + + byte modRM = CodeBuffer[position]; + byte reg = (byte)((modRM & 0x38) >> 3); + + return reg == 4; // 4 = MUL + } + + /// + /// Decodes a MUL r/m32 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 = "mul"; + + int position = Decoder.GetPosition(); + + if (position >= Length) + { + return false; + } + + // Read the ModR/M byte + byte modRM = CodeBuffer[position++]; + Decoder.SetPosition(position); + + // Extract the fields from the ModR/M byte + byte mod = (byte)((modRM & 0xC0) >> 6); + byte reg = (byte)((modRM & 0x38) >> 3); // Should be 4 for MUL + byte rm = (byte)(modRM & 0x07); + + // Decode the operand + string operand = _modRMDecoder.DecodeModRM(mod, rm, false); + + // Set the operands + instruction.Operands = operand; + + return true; + } +} diff --git a/X86Disassembler/X86/Handlers/Group3/NegRm32Handler.cs b/X86Disassembler/X86/Handlers/Group3/NegRm32Handler.cs new file mode 100644 index 0000000..caefa3c --- /dev/null +++ b/X86Disassembler/X86/Handlers/Group3/NegRm32Handler.cs @@ -0,0 +1,75 @@ +namespace X86Disassembler.X86.Handlers.Group3; + +/// +/// Handler for NEG r/m32 instruction (0xF7 /3) +/// +public class NegRm32Handler : Group3BaseHandler +{ + /// + /// Initializes a new instance of the NegRm32Handler class + /// + /// The buffer containing the code to decode + /// The instruction decoder that owns this handler + /// The length of the buffer + public NegRm32Handler(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 != 0xF7) + return false; + + // Check if the reg field of the ModR/M byte is 3 (NEG) + int position = Decoder.GetPosition(); + if (position >= Length) + return false; + + byte modRM = CodeBuffer[position]; + byte reg = (byte)((modRM & 0x38) >> 3); + + return reg == 3; // 3 = NEG + } + + /// + /// Decodes a NEG r/m32 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 = "neg"; + + int position = Decoder.GetPosition(); + + if (position >= Length) + { + return false; + } + + // Read the ModR/M byte + byte modRM = CodeBuffer[position++]; + Decoder.SetPosition(position); + + // Extract the fields from the ModR/M byte + byte mod = (byte)((modRM & 0xC0) >> 6); + byte reg = (byte)((modRM & 0x38) >> 3); // Should be 3 for NEG + byte rm = (byte)(modRM & 0x07); + + // Decode the operand + string operand = _modRMDecoder.DecodeModRM(mod, rm, false); + + // Set the operands + instruction.Operands = operand; + + return true; + } +} diff --git a/X86Disassembler/X86/Handlers/Group3/NotRm32Handler.cs b/X86Disassembler/X86/Handlers/Group3/NotRm32Handler.cs new file mode 100644 index 0000000..bb1a6ff --- /dev/null +++ b/X86Disassembler/X86/Handlers/Group3/NotRm32Handler.cs @@ -0,0 +1,75 @@ +namespace X86Disassembler.X86.Handlers.Group3; + +/// +/// Handler for NOT r/m32 instruction (0xF7 /2) +/// +public class NotRm32Handler : Group3BaseHandler +{ + /// + /// Initializes a new instance of the NotRm32Handler class + /// + /// The buffer containing the code to decode + /// The instruction decoder that owns this handler + /// The length of the buffer + public NotRm32Handler(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 != 0xF7) + return false; + + // Check if the reg field of the ModR/M byte is 2 (NOT) + int position = Decoder.GetPosition(); + if (position >= Length) + return false; + + byte modRM = CodeBuffer[position]; + byte reg = (byte)((modRM & 0x38) >> 3); + + return reg == 2; // 2 = NOT + } + + /// + /// Decodes a NOT r/m32 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 = "not"; + + int position = Decoder.GetPosition(); + + if (position >= Length) + { + return false; + } + + // Read the ModR/M byte + byte modRM = CodeBuffer[position++]; + Decoder.SetPosition(position); + + // Extract the fields from the ModR/M byte + byte mod = (byte)((modRM & 0xC0) >> 6); + byte reg = (byte)((modRM & 0x38) >> 3); // Should be 2 for NOT + byte rm = (byte)(modRM & 0x07); + + // Decode the operand + string operand = _modRMDecoder.DecodeModRM(mod, rm, false); + + // Set the operands + instruction.Operands = operand; + + return true; + } +} diff --git a/X86Disassembler/X86/Handlers/Group3/TestImmWithRm32Handler.cs b/X86Disassembler/X86/Handlers/Group3/TestImmWithRm32Handler.cs new file mode 100644 index 0000000..2c9832e --- /dev/null +++ b/X86Disassembler/X86/Handlers/Group3/TestImmWithRm32Handler.cs @@ -0,0 +1,84 @@ +namespace X86Disassembler.X86.Handlers.Group3; + +/// +/// Handler for TEST r/m32, imm32 instruction (0xF7 /0) +/// +public class TestImmWithRm32Handler : Group3BaseHandler +{ + /// + /// Initializes a new instance of the TestImmWithRm32Handler class + /// + /// The buffer containing the code to decode + /// The instruction decoder that owns this handler + /// The length of the buffer + public TestImmWithRm32Handler(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 != 0xF7) + return false; + + // Check if the reg field of the ModR/M byte is 0 (TEST) + int position = Decoder.GetPosition(); + if (position >= Length) + return false; + + byte modRM = CodeBuffer[position]; + byte reg = (byte)((modRM & 0x38) >> 3); + + return reg == 0; // 0 = TEST + } + + /// + /// Decodes a TEST r/m32, 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 = "test"; + + int position = Decoder.GetPosition(); + + if (position >= Length) + { + return false; + } + + // Read the ModR/M byte + byte modRM = CodeBuffer[position++]; + Decoder.SetPosition(position); + + // Extract the fields from the ModR/M byte + byte mod = (byte)((modRM & 0xC0) >> 6); + byte reg = (byte)((modRM & 0x38) >> 3); // Should be 0 for TEST + byte rm = (byte)(modRM & 0x07); + + // Decode the destination operand + string destOperand = _modRMDecoder.DecodeModRM(mod, rm, false); + + // Read the immediate value + if (position + 3 >= Length) + { + return false; + } + + uint imm32 = BitConverter.ToUInt32(CodeBuffer, position); + Decoder.SetPosition(position + 4); + + // Set the operands + instruction.Operands = $"{destOperand}, 0x{imm32:X8}"; + + return true; + } +} diff --git a/X86Disassembler/X86/Handlers/InstructionHandlerFactory.cs b/X86Disassembler/X86/Handlers/InstructionHandlerFactory.cs index 7608a84..3a22e8c 100644 --- a/X86Disassembler/X86/Handlers/InstructionHandlerFactory.cs +++ b/X86Disassembler/X86/Handlers/InstructionHandlerFactory.cs @@ -1,5 +1,8 @@ namespace X86Disassembler.X86.Handlers; +using X86Disassembler.X86.Handlers.Group1; +using X86Disassembler.X86.Handlers.Group3; + /// /// Factory for creating instruction handlers /// @@ -45,13 +48,84 @@ public class InstructionHandlerFactory _handlers.Add(new ConditionalJumpHandler(_codeBuffer, _decoder, _length)); _handlers.Add(new TwoByteConditionalJumpHandler(_codeBuffer, _decoder, _length)); + // Register Group1 handlers + RegisterGroup1Handlers(); + + // Register Group3 handlers + RegisterGroup3Handlers(); + // Register group handlers for instructions that share similar decoding logic - _handlers.Add(new Group1Handler(_codeBuffer, _decoder, _length)); - _handlers.Add(new Group3Handler(_codeBuffer, _decoder, _length)); _handlers.Add(new FloatingPointHandler(_codeBuffer, _decoder, _length)); _handlers.Add(new DataTransferHandler(_codeBuffer, _decoder, _length)); } + /// + /// Registers the Group1 handlers + /// + private void RegisterGroup1Handlers() + { + // ADD handlers + _handlers.Add(new AddImmToRm8Handler(_codeBuffer, _decoder, _length)); + _handlers.Add(new AddImmToRm32Handler(_codeBuffer, _decoder, _length)); + _handlers.Add(new AddImmToRm32SignExtendedHandler(_codeBuffer, _decoder, _length)); + + // OR handlers + _handlers.Add(new OrImmToRm8Handler(_codeBuffer, _decoder, _length)); + _handlers.Add(new OrImmToRm32Handler(_codeBuffer, _decoder, _length)); + _handlers.Add(new OrImmToRm32SignExtendedHandler(_codeBuffer, _decoder, _length)); + + // ADC handlers + _handlers.Add(new AdcImmToRm32Handler(_codeBuffer, _decoder, _length)); + _handlers.Add(new AdcImmToRm32SignExtendedHandler(_codeBuffer, _decoder, _length)); + + // SBB handlers + _handlers.Add(new SbbImmFromRm32Handler(_codeBuffer, _decoder, _length)); + _handlers.Add(new SbbImmFromRm32SignExtendedHandler(_codeBuffer, _decoder, _length)); + + // AND handlers + _handlers.Add(new AndImmWithRm32Handler(_codeBuffer, _decoder, _length)); + _handlers.Add(new AndImmWithRm32SignExtendedHandler(_codeBuffer, _decoder, _length)); + + // SUB handlers + _handlers.Add(new SubImmFromRm32Handler(_codeBuffer, _decoder, _length)); + _handlers.Add(new SubImmFromRm32SignExtendedHandler(_codeBuffer, _decoder, _length)); + + // XOR handlers + _handlers.Add(new XorImmWithRm32Handler(_codeBuffer, _decoder, _length)); + _handlers.Add(new XorImmWithRm32SignExtendedHandler(_codeBuffer, _decoder, _length)); + + // CMP handlers + _handlers.Add(new CmpImmWithRm32Handler(_codeBuffer, _decoder, _length)); + _handlers.Add(new CmpImmWithRm32SignExtendedHandler(_codeBuffer, _decoder, _length)); + } + + /// + /// Registers the Group3 handlers + /// + private void RegisterGroup3Handlers() + { + // TEST handler + _handlers.Add(new TestImmWithRm32Handler(_codeBuffer, _decoder, _length)); + + // NOT handler + _handlers.Add(new NotRm32Handler(_codeBuffer, _decoder, _length)); + + // NEG handler + _handlers.Add(new NegRm32Handler(_codeBuffer, _decoder, _length)); + + // MUL handler + _handlers.Add(new MulRm32Handler(_codeBuffer, _decoder, _length)); + + // IMUL handler + _handlers.Add(new ImulRm32Handler(_codeBuffer, _decoder, _length)); + + // DIV handler + _handlers.Add(new DivRm32Handler(_codeBuffer, _decoder, _length)); + + // IDIV handler + _handlers.Add(new IdivRm32Handler(_codeBuffer, _decoder, _length)); + } + /// /// Gets a handler that can decode the given opcode ///