diff --git a/X86Disassembler/X86/Handlers/InstructionHandlerFactory.cs b/X86Disassembler/X86/Handlers/InstructionHandlerFactory.cs
index ec54493..8a727a1 100644
--- a/X86Disassembler/X86/Handlers/InstructionHandlerFactory.cs
+++ b/X86Disassembler/X86/Handlers/InstructionHandlerFactory.cs
@@ -100,6 +100,18 @@ public class InstructionHandlerFactory
///
private void RegisterSbbHandlers()
{
+ // SBB register-register and register-memory handlers for 8-bit operands
+ _handlers.Add(new SbbRm8R8Handler(_decoder)); // SBB r/m8, r8 (opcode 18)
+ _handlers.Add(new SbbR8Rm8Handler(_decoder)); // SBB r8, r/m8 (opcode 1A)
+
+ // SBB register-register and register-memory handlers for 16-bit operands (with 0x66 prefix)
+ _handlers.Add(new SbbRm16R16Handler(_decoder)); // SBB r/m16, r16 (opcode 19 with 0x66 prefix)
+ _handlers.Add(new SbbR16Rm16Handler(_decoder)); // SBB r16, r/m16 (opcode 1B with 0x66 prefix)
+
+ // SBB register-register and register-memory handlers for 32-bit operands
+ _handlers.Add(new SbbRm32R32Handler(_decoder)); // SBB r/m32, r32 (opcode 19)
+ _handlers.Add(new SbbR32Rm32Handler(_decoder)); // SBB r32, r/m32 (opcode 1B)
+
// 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)
diff --git a/X86Disassembler/X86/Handlers/Sbb/SbbR16Rm16Handler.cs b/X86Disassembler/X86/Handlers/Sbb/SbbR16Rm16Handler.cs
new file mode 100644
index 0000000..46ff47b
--- /dev/null
+++ b/X86Disassembler/X86/Handlers/Sbb/SbbR16Rm16Handler.cs
@@ -0,0 +1,65 @@
+using X86Disassembler.X86.Operands;
+
+namespace X86Disassembler.X86.Handlers.Sbb;
+
+///
+/// Handler for SBB r16, r/m16 instruction (0x1B with 0x66 prefix)
+///
+public class SbbR16Rm16Handler : InstructionHandler
+{
+ ///
+ /// Initializes a new instance of the SbbR16Rm16Handler class
+ ///
+ /// The instruction decoder that owns this handler
+ public SbbR16Rm16Handler(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)
+ {
+ // Only handle opcode 0x1B when the operand size prefix IS present
+ return opcode == 0x1B && Decoder.HasOperandSizePrefix();
+ }
+
+ ///
+ /// Decodes a SBB r16, r/m16 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;
+
+ // Check if we have enough bytes for the ModR/M byte
+ if (!Decoder.CanReadByte())
+ {
+ return false;
+ }
+
+ // Read the ModR/M byte
+ // For SBB r16, r/m16 (0x1B with 0x66 prefix):
+ // - The reg field specifies the destination register
+ // - The r/m field with mod specifies the source operand (register or memory)
+ var (_, reg, _, sourceOperand) = ModRMDecoder.ReadModRM16();
+
+ // Create the register operand for the reg field (16-bit)
+ var destinationOperand = OperandFactory.CreateRegisterOperand(reg, 16);
+
+ // Set the structured operands
+ instruction.StructuredOperands =
+ [
+ destinationOperand,
+ sourceOperand
+ ];
+
+ return true;
+ }
+}
diff --git a/X86Disassembler/X86/Handlers/Sbb/SbbR32Rm32Handler.cs b/X86Disassembler/X86/Handlers/Sbb/SbbR32Rm32Handler.cs
new file mode 100644
index 0000000..dd2c2b0
--- /dev/null
+++ b/X86Disassembler/X86/Handlers/Sbb/SbbR32Rm32Handler.cs
@@ -0,0 +1,66 @@
+using X86Disassembler.X86.Operands;
+
+namespace X86Disassembler.X86.Handlers.Sbb;
+
+///
+/// Handler for SBB r32, r/m32 instruction (0x1B)
+///
+public class SbbR32Rm32Handler : InstructionHandler
+{
+ ///
+ /// Initializes a new instance of the SbbR32Rm32Handler class
+ ///
+ /// The instruction decoder that owns this handler
+ public SbbR32Rm32Handler(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)
+ {
+ // Only handle opcode 0x1B when the operand size prefix is NOT present
+ // This ensures 16-bit handlers get priority when the prefix is present
+ return opcode == 0x1B && !Decoder.HasOperandSizePrefix();
+ }
+
+ ///
+ /// Decodes a SBB r32, 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 instruction type
+ instruction.Type = InstructionType.Sbb;
+
+ // Check if we have enough bytes for the ModR/M byte
+ if (!Decoder.CanReadByte())
+ {
+ return false;
+ }
+
+ // Read the ModR/M byte
+ // For SBB r32, r/m32 (0x1B):
+ // - The reg field specifies the destination register
+ // - The r/m field with mod specifies the source operand (register or memory)
+ var (_, reg, _, sourceOperand) = ModRMDecoder.ReadModRM();
+
+ // Create the register operand for the reg field
+ var destinationOperand = OperandFactory.CreateRegisterOperand(reg);
+
+ // Set the structured operands
+ instruction.StructuredOperands =
+ [
+ destinationOperand,
+ sourceOperand
+ ];
+
+ return true;
+ }
+}
diff --git a/X86Disassembler/X86/Handlers/Sbb/SbbR8Rm8Handler.cs b/X86Disassembler/X86/Handlers/Sbb/SbbR8Rm8Handler.cs
new file mode 100644
index 0000000..b731462
--- /dev/null
+++ b/X86Disassembler/X86/Handlers/Sbb/SbbR8Rm8Handler.cs
@@ -0,0 +1,64 @@
+using X86Disassembler.X86.Operands;
+
+namespace X86Disassembler.X86.Handlers.Sbb;
+
+///
+/// Handler for SBB r8, r/m8 instruction (0x1A)
+///
+public class SbbR8Rm8Handler : InstructionHandler
+{
+ ///
+ /// Initializes a new instance of the SbbR8Rm8Handler class
+ ///
+ /// The instruction decoder that owns this handler
+ public SbbR8Rm8Handler(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 == 0x1A;
+ }
+
+ ///
+ /// Decodes a SBB r8, r/m8 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;
+
+ // Check if we have enough bytes for the ModR/M byte
+ if (!Decoder.CanReadByte())
+ {
+ return false;
+ }
+
+ // Read the ModR/M byte
+ // For SBB r8, r/m8 (0x1A):
+ // - The reg field specifies the destination register
+ // - The r/m field with mod specifies the source operand (register or memory)
+ var (_, reg, _, sourceOperand) = ModRMDecoder.ReadModRM8();
+
+ // Create the register operand for the reg field (8-bit)
+ var destinationOperand = OperandFactory.CreateRegisterOperand8(reg);
+
+ // Set the structured operands
+ instruction.StructuredOperands =
+ [
+ destinationOperand,
+ sourceOperand
+ ];
+
+ return true;
+ }
+}
diff --git a/X86Disassembler/X86/Handlers/Sbb/SbbRm16R16Handler.cs b/X86Disassembler/X86/Handlers/Sbb/SbbRm16R16Handler.cs
new file mode 100644
index 0000000..987e727
--- /dev/null
+++ b/X86Disassembler/X86/Handlers/Sbb/SbbRm16R16Handler.cs
@@ -0,0 +1,65 @@
+using X86Disassembler.X86.Operands;
+
+namespace X86Disassembler.X86.Handlers.Sbb;
+
+///
+/// Handler for SBB r/m16, r16 instruction (0x19 with 0x66 prefix)
+///
+public class SbbRm16R16Handler : InstructionHandler
+{
+ ///
+ /// Initializes a new instance of the SbbRm16R16Handler class
+ ///
+ /// The instruction decoder that owns this handler
+ public SbbRm16R16Handler(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)
+ {
+ // Only handle opcode 0x19 when the operand size prefix IS present
+ return opcode == 0x19 && Decoder.HasOperandSizePrefix();
+ }
+
+ ///
+ /// Decodes a SBB r/m16, r16 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;
+
+ // Check if we have enough bytes for the ModR/M byte
+ if (!Decoder.CanReadByte())
+ {
+ return false;
+ }
+
+ // Read the ModR/M byte
+ // For SBB r/m16, r16 (0x19 with 0x66 prefix):
+ // - The r/m field with mod specifies the destination operand (register or memory)
+ // - The reg field specifies the source register
+ var (_, reg, _, destinationOperand) = ModRMDecoder.ReadModRM16();
+
+ // Create the register operand for the reg field (16-bit)
+ var sourceOperand = OperandFactory.CreateRegisterOperand(reg, 16);
+
+ // Set the structured operands
+ instruction.StructuredOperands =
+ [
+ destinationOperand,
+ sourceOperand
+ ];
+
+ return true;
+ }
+}
diff --git a/X86Disassembler/X86/Handlers/Sbb/SbbRm32R32Handler.cs b/X86Disassembler/X86/Handlers/Sbb/SbbRm32R32Handler.cs
new file mode 100644
index 0000000..59c74b7
--- /dev/null
+++ b/X86Disassembler/X86/Handlers/Sbb/SbbRm32R32Handler.cs
@@ -0,0 +1,66 @@
+using X86Disassembler.X86.Operands;
+
+namespace X86Disassembler.X86.Handlers.Sbb;
+
+///
+/// Handler for SBB r/m32, r32 instruction (0x19)
+///
+public class SbbRm32R32Handler : InstructionHandler
+{
+ ///
+ /// Initializes a new instance of the SbbRm32R32Handler class
+ ///
+ /// The instruction decoder that owns this handler
+ public SbbRm32R32Handler(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)
+ {
+ // Only handle opcode 0x19 when the operand size prefix is NOT present
+ // This ensures 16-bit handlers get priority when the prefix is present
+ return opcode == 0x19 && !Decoder.HasOperandSizePrefix();
+ }
+
+ ///
+ /// Decodes a SBB r/m32, r32 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;
+
+ // Check if we have enough bytes for the ModR/M byte
+ if (!Decoder.CanReadByte())
+ {
+ return false;
+ }
+
+ // Read the ModR/M byte
+ // For SBB r/m32, r32 (0x19):
+ // - The r/m field with mod specifies the destination operand (register or memory)
+ // - The reg field specifies the source register
+ var (_, reg, _, destinationOperand) = ModRMDecoder.ReadModRM();
+
+ // Create the register operand for the reg field
+ var sourceOperand = OperandFactory.CreateRegisterOperand(reg);
+
+ // Set the structured operands
+ instruction.StructuredOperands =
+ [
+ destinationOperand,
+ sourceOperand
+ ];
+
+ return true;
+ }
+}
diff --git a/X86Disassembler/X86/Handlers/Sbb/SbbRm8R8Handler.cs b/X86Disassembler/X86/Handlers/Sbb/SbbRm8R8Handler.cs
new file mode 100644
index 0000000..c7cb195
--- /dev/null
+++ b/X86Disassembler/X86/Handlers/Sbb/SbbRm8R8Handler.cs
@@ -0,0 +1,64 @@
+using X86Disassembler.X86.Operands;
+
+namespace X86Disassembler.X86.Handlers.Sbb;
+
+///
+/// Handler for SBB r/m8, r8 instruction (0x18)
+///
+public class SbbRm8R8Handler : InstructionHandler
+{
+ ///
+ /// Initializes a new instance of the SbbRm8R8Handler class
+ ///
+ /// The instruction decoder that owns this handler
+ public SbbRm8R8Handler(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 == 0x18;
+ }
+
+ ///
+ /// Decodes a SBB r/m8, r8 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;
+
+ // Check if we have enough bytes for the ModR/M byte
+ if (!Decoder.CanReadByte())
+ {
+ return false;
+ }
+
+ // Read the ModR/M byte
+ // For SBB r/m8, r8 (0x18):
+ // - The r/m field with mod specifies the destination operand (register or memory)
+ // - The reg field specifies the source register
+ var (_, reg, _, destinationOperand) = ModRMDecoder.ReadModRM8();
+
+ // Create the register operand for the reg field (8-bit)
+ var sourceOperand = OperandFactory.CreateRegisterOperand8(reg);
+
+ // Set the structured operands
+ instruction.StructuredOperands =
+ [
+ destinationOperand,
+ sourceOperand
+ ];
+
+ return true;
+ }
+}