From 4d2db05a07b9a203adfcc788435caa0416da9043 Mon Sep 17 00:00:00 2001 From: bird_egop Date: Thu, 17 Apr 2025 22:04:12 +0300 Subject: [PATCH] Implemented additional SBB instruction handlers for register-register and register-memory operations --- .../X86/Handlers/InstructionHandlerFactory.cs | 12 ++++ .../X86/Handlers/Sbb/SbbR16Rm16Handler.cs | 65 ++++++++++++++++++ .../X86/Handlers/Sbb/SbbR32Rm32Handler.cs | 66 +++++++++++++++++++ .../X86/Handlers/Sbb/SbbR8Rm8Handler.cs | 64 ++++++++++++++++++ .../X86/Handlers/Sbb/SbbRm16R16Handler.cs | 65 ++++++++++++++++++ .../X86/Handlers/Sbb/SbbRm32R32Handler.cs | 66 +++++++++++++++++++ .../X86/Handlers/Sbb/SbbRm8R8Handler.cs | 64 ++++++++++++++++++ 7 files changed, 402 insertions(+) create mode 100644 X86Disassembler/X86/Handlers/Sbb/SbbR16Rm16Handler.cs create mode 100644 X86Disassembler/X86/Handlers/Sbb/SbbR32Rm32Handler.cs create mode 100644 X86Disassembler/X86/Handlers/Sbb/SbbR8Rm8Handler.cs create mode 100644 X86Disassembler/X86/Handlers/Sbb/SbbRm16R16Handler.cs create mode 100644 X86Disassembler/X86/Handlers/Sbb/SbbRm32R32Handler.cs create mode 100644 X86Disassembler/X86/Handlers/Sbb/SbbRm8R8Handler.cs 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; + } +}