diff --git a/X86Disassembler/X86/Handlers/InstructionHandlerFactory.cs b/X86Disassembler/X86/Handlers/InstructionHandlerFactory.cs index b5105d1..ec54493 100644 --- a/X86Disassembler/X86/Handlers/InstructionHandlerFactory.cs +++ b/X86Disassembler/X86/Handlers/InstructionHandlerFactory.cs @@ -100,9 +100,20 @@ public class InstructionHandlerFactory /// private void RegisterSbbHandlers() { - // SBB immediate handlers + // SBB immediate handlers for 8-bit operands + _handlers.Add(new SbbImmFromRm8Handler(_decoder)); // SBB r/m8, imm8 (opcode 80 /3) + _handlers.Add(new SbbAlImmHandler(_decoder)); // SBB AL, imm8 (opcode 1C) + + // SBB immediate handlers for 16-bit operands (with 0x66 prefix) + _handlers.Add(new SbbImmFromRm16Handler(_decoder)); // SBB r/m16, imm16 (opcode 81 /3 with 0x66 prefix) + _handlers.Add(new SbbImmFromRm16SignExtendedHandler(_decoder)); // SBB r/m16, imm8 (opcode 83 /3 with 0x66 prefix) + + // SBB immediate handlers for 32-bit operands _handlers.Add(new SbbImmFromRm32Handler(_decoder)); // SBB r/m32, imm32 (opcode 81 /3) _handlers.Add(new SbbImmFromRm32SignExtendedHandler(_decoder)); // SBB r/m32, imm8 (opcode 83 /3) + + // SBB accumulator handlers + _handlers.Add(new SbbAccumulatorImmHandler(_decoder)); // SBB AX/EAX, imm16/32 (opcode 1D) } /// @@ -140,6 +151,15 @@ public class InstructionHandlerFactory // Add Return handlers _handlers.Add(new RetHandler(_decoder)); _handlers.Add(new RetImmHandler(_decoder)); + + // Add Far Return handlers + // 16-bit handlers with operand size prefix (must come first) + _handlers.Add(new Retf16Handler(_decoder)); // RETF (16-bit) (opcode 0xCB with 0x66 prefix) + _handlers.Add(new RetfImm16Handler(_decoder)); // RETF imm16 (16-bit) (opcode 0xCA with 0x66 prefix) + + // 32-bit handlers (default) + _handlers.Add(new RetfHandler(_decoder)); // RETF (32-bit) (opcode 0xCB) + _handlers.Add(new RetfImmHandler(_decoder)); // RETF imm16 (32-bit) (opcode 0xCA) } /// diff --git a/X86Disassembler/X86/Handlers/Sbb/SbbAccumulatorImmHandler.cs b/X86Disassembler/X86/Handlers/Sbb/SbbAccumulatorImmHandler.cs new file mode 100644 index 0000000..473cc05 --- /dev/null +++ b/X86Disassembler/X86/Handlers/Sbb/SbbAccumulatorImmHandler.cs @@ -0,0 +1,70 @@ +namespace X86Disassembler.X86.Handlers.Sbb; + +using Operands; + +/// +/// Handler for SBB AX/EAX, imm16/32 instruction (0x1D) +/// +public class SbbAccumulatorImmHandler : InstructionHandler +{ + /// + /// Initializes a new instance of the SbbAccumulatorImmHandler class + /// + /// The instruction decoder that owns this handler + public SbbAccumulatorImmHandler(InstructionDecoder decoder) + : base(decoder) + { + } + + /// + /// 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 == 0x1D; + } + + /// + /// Decodes a SBB AX/EAX, imm16/32 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 instruction type + instruction.Type = InstructionType.Sbb; + + // Determine operand size based on prefix + int operandSize = Decoder.HasOperandSizePrefix() ? 16 : 32; + + // Check if we have enough bytes for the immediate value + if (operandSize == 16 && !Decoder.CanReadUShort()) + { + return false; + } + else if (operandSize == 32 && !Decoder.CanReadUInt()) + { + return false; + } + + // Create the accumulator register operand (AX or EAX) + var accumulatorOperand = OperandFactory.CreateRegisterOperand(RegisterIndex.A, operandSize); + + // Read and create the immediate operand based on operand size + var immOperand = operandSize == 16 + ? OperandFactory.CreateImmediateOperand(Decoder.ReadUInt16(), operandSize) + : OperandFactory.CreateImmediateOperand(Decoder.ReadUInt32(), operandSize); + + // Set the structured operands + instruction.StructuredOperands = + [ + accumulatorOperand, + immOperand + ]; + + return true; + } +} diff --git a/X86Disassembler/X86/Handlers/Sbb/SbbAlImmHandler.cs b/X86Disassembler/X86/Handlers/Sbb/SbbAlImmHandler.cs new file mode 100644 index 0000000..cc0a572 --- /dev/null +++ b/X86Disassembler/X86/Handlers/Sbb/SbbAlImmHandler.cs @@ -0,0 +1,64 @@ +namespace X86Disassembler.X86.Handlers.Sbb; + +using Operands; + +/// +/// Handler for SBB AL, imm8 instruction (0x1C) +/// +public class SbbAlImmHandler : InstructionHandler +{ + /// + /// Initializes a new instance of the SbbAlImmHandler class + /// + /// The instruction decoder that owns this handler + public SbbAlImmHandler(InstructionDecoder decoder) + : base(decoder) + { + } + + /// + /// 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 == 0x1C; + } + + /// + /// Decodes a SBB AL, 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 instruction type + instruction.Type = InstructionType.Sbb; + + // Create the AL register operand + var alOperand = OperandFactory.CreateRegisterOperand(RegisterIndex.A, 8); + + // Check if we have enough bytes for the immediate value + if (!Decoder.CanReadByte()) + { + return false; + } + + // Read the immediate value + byte imm8 = Decoder.ReadByte(); + + // Create the immediate operand + var immOperand = OperandFactory.CreateImmediateOperand(imm8, 8); + + // Set the structured operands + instruction.StructuredOperands = + [ + alOperand, + immOperand + ]; + + return true; + } +} diff --git a/X86Disassembler/X86/Handlers/Sbb/SbbImmFromRm16Handler.cs b/X86Disassembler/X86/Handlers/Sbb/SbbImmFromRm16Handler.cs new file mode 100644 index 0000000..830fd10 --- /dev/null +++ b/X86Disassembler/X86/Handlers/Sbb/SbbImmFromRm16Handler.cs @@ -0,0 +1,85 @@ +using X86Disassembler.X86.Operands; + +namespace X86Disassembler.X86.Handlers.Sbb; + +/// +/// Handler for SBB r/m16, imm16 instruction (0x81 /3 with 0x66 prefix) +/// +public class SbbImmFromRm16Handler : InstructionHandler +{ + /// + /// Initializes a new instance of the SbbImmFromRm16Handler class + /// + /// The instruction decoder that owns this handler + public SbbImmFromRm16Handler(InstructionDecoder decoder) + : base(decoder) + { + } + + /// + /// 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; + + // Must have operand size prefix for 16-bit operation + if (!Decoder.HasOperandSizePrefix()) + return false; + + // Check if the reg field of the ModR/M byte is 3 (SBB) + if (!Decoder.CanReadByte()) + return false; + + var reg = ModRMDecoder.PeakModRMReg(); + + return reg == 3; // 3 = SBB + } + + /// + /// Decodes a SBB r/m16, imm16 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 instruction type + instruction.Type = InstructionType.Sbb; + + if (!Decoder.CanReadByte()) + { + return false; + } + + // Read the ModR/M byte + // For SBB r/m16, imm16 (0x81 /3 with 0x66 prefix): + // - The r/m field with mod specifies the destination operand (register or memory) + // - The immediate value is the source operand + var (_, _, _, destinationOperand) = ModRMDecoder.ReadModRM16(); + + // Check if we have enough bytes for the immediate value + if (!Decoder.CanReadUShort()) + { + return false; + } + + // Read the immediate value + ushort imm16 = Decoder.ReadUInt16(); + + // Create the immediate operand + var sourceOperand = OperandFactory.CreateImmediateOperand(imm16, 16); + + // Set the structured operands + instruction.StructuredOperands = + [ + destinationOperand, + sourceOperand + ]; + + return true; + } +} diff --git a/X86Disassembler/X86/Handlers/Sbb/SbbImmFromRm16SignExtendedHandler.cs b/X86Disassembler/X86/Handlers/Sbb/SbbImmFromRm16SignExtendedHandler.cs new file mode 100644 index 0000000..6d6d24d --- /dev/null +++ b/X86Disassembler/X86/Handlers/Sbb/SbbImmFromRm16SignExtendedHandler.cs @@ -0,0 +1,85 @@ +using X86Disassembler.X86.Operands; + +namespace X86Disassembler.X86.Handlers.Sbb; + +/// +/// Handler for SBB r/m16, imm8 (sign-extended) instruction (0x83 /3 with 0x66 prefix) +/// +public class SbbImmFromRm16SignExtendedHandler : InstructionHandler +{ + /// + /// Initializes a new instance of the SbbImmFromRm16SignExtendedHandler class + /// + /// The instruction decoder that owns this handler + public SbbImmFromRm16SignExtendedHandler(InstructionDecoder decoder) + : base(decoder) + { + } + + /// + /// 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; + + // Must have operand size prefix for 16-bit operation + if (!Decoder.HasOperandSizePrefix()) + return false; + + // Check if the reg field of the ModR/M byte is 3 (SBB) + if (!Decoder.CanReadByte()) + return false; + + var reg = ModRMDecoder.PeakModRMReg(); + + return reg == 3; // 3 = SBB + } + + /// + /// Decodes a SBB r/m16, 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 instruction type + instruction.Type = InstructionType.Sbb; + + if (!Decoder.CanReadByte()) + { + return false; + } + + // Read the ModR/M byte + // For SBB r/m16, imm8 (sign-extended) (0x83 /3 with 0x66 prefix): + // - The r/m field with mod specifies the destination operand (register or memory) + // - The immediate value is the source operand + var (_, _, _, destinationOperand) = ModRMDecoder.ReadModRM16(); + + // Check if we have enough bytes for the immediate value + if (!Decoder.CanReadByte()) + { + return false; + } + + // Sign-extend to 16 bits + sbyte imm8 = (sbyte)Decoder.ReadByte(); + + // Create the immediate operand with sign extension + var sourceOperand = OperandFactory.CreateImmediateOperand((ushort)imm8, 16); + + // Set the structured operands + instruction.StructuredOperands = + [ + destinationOperand, + sourceOperand + ]; + + return true; + } +} diff --git a/X86Disassembler/X86/Handlers/Sbb/SbbImmFromRm8Handler.cs b/X86Disassembler/X86/Handlers/Sbb/SbbImmFromRm8Handler.cs new file mode 100644 index 0000000..c9cb2ee --- /dev/null +++ b/X86Disassembler/X86/Handlers/Sbb/SbbImmFromRm8Handler.cs @@ -0,0 +1,81 @@ +using X86Disassembler.X86.Operands; + +namespace X86Disassembler.X86.Handlers.Sbb; + +/// +/// Handler for SBB r/m8, imm8 instruction (0x80 /3) +/// +public class SbbImmFromRm8Handler : InstructionHandler +{ + /// + /// Initializes a new instance of the SbbImmFromRm8Handler class + /// + /// The instruction decoder that owns this handler + public SbbImmFromRm8Handler(InstructionDecoder decoder) + : base(decoder) + { + } + + /// + /// 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 3 (SBB) + if (!Decoder.CanReadByte()) + return false; + + var reg = ModRMDecoder.PeakModRMReg(); + + return reg == 3; // 3 = SBB + } + + /// + /// Decodes a SBB 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 instruction type + instruction.Type = InstructionType.Sbb; + + if (!Decoder.CanReadByte()) + { + return false; + } + + // Read the ModR/M byte + // For SBB r/m8, imm8 (0x80 /3): + // - The r/m field with mod specifies the destination operand (register or memory) + // - The immediate value is the source operand + var (_, _, _, destinationOperand) = ModRMDecoder.ReadModRM8(); + + // Check if we have enough bytes for the immediate value + if (!Decoder.CanReadByte()) + { + return false; + } + + // Read the immediate value + byte imm8 = Decoder.ReadByte(); + + // Create the immediate operand + var sourceOperand = OperandFactory.CreateImmediateOperand(imm8, 8); + + // Set the structured operands + instruction.StructuredOperands = + [ + destinationOperand, + sourceOperand + ]; + + return true; + } +}