mirror of
https://github.com/sampletext32/ParkanPlayground.git
synced 2025-06-19 16:08:02 +03:00
Unified ADC accumulator handlers into a single handler
This commit is contained in:
@ -85,13 +85,16 @@ public class Disassembler
|
||||
break;
|
||||
}
|
||||
|
||||
// If no special case applies, decode normally
|
||||
// Store the position before decoding to handle prefixes properly
|
||||
int startPosition = position;
|
||||
|
||||
// Decode the instruction
|
||||
Instruction? instruction = decoder.DecodeInstruction();
|
||||
|
||||
if (instruction != null)
|
||||
{
|
||||
// Adjust the instruction address to include the base address
|
||||
instruction.Address += _baseAddress;
|
||||
instruction.Address = _baseAddress + (uint)startPosition;
|
||||
|
||||
// Add the instruction to the list
|
||||
instructions.Add(instruction);
|
||||
@ -103,7 +106,7 @@ public class Disassembler
|
||||
|
||||
Instruction dummyInstruction = new Instruction
|
||||
{
|
||||
Address = _baseAddress + (uint) position,
|
||||
Address = _baseAddress + (uint)position,
|
||||
Type = InstructionType.Unknown,
|
||||
StructuredOperands = [OperandFactory.CreateImmediateOperand(unknownByte, 8),]
|
||||
};
|
||||
|
71
X86Disassembler/X86/Handlers/Adc/AdcAccumulatorImmHandler.cs
Normal file
71
X86Disassembler/X86/Handlers/Adc/AdcAccumulatorImmHandler.cs
Normal file
@ -0,0 +1,71 @@
|
||||
namespace X86Disassembler.X86.Handlers.Adc;
|
||||
|
||||
using Operands;
|
||||
|
||||
/// <summary>
|
||||
/// Handler for ADC AX/EAX, imm16/32 instruction (opcode 0x15)
|
||||
/// </summary>
|
||||
public class AdcAccumulatorImmHandler : InstructionHandler
|
||||
{
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the AdcAccumulatorImmHandler class
|
||||
/// </summary>
|
||||
/// <param name="decoder">The instruction decoder that owns this handler</param>
|
||||
public AdcAccumulatorImmHandler(InstructionDecoder decoder)
|
||||
: base(decoder)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Checks if this handler can decode the given opcode
|
||||
/// </summary>
|
||||
/// <param name="opcode">The opcode to check</param>
|
||||
/// <returns>True if this handler can decode the opcode</returns>
|
||||
public override bool CanHandle(byte opcode)
|
||||
{
|
||||
// ADC AX/EAX, imm16/32 is encoded as 0x15
|
||||
return opcode == 0x15;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Decodes a ADC AX/EAX, imm16/32 instruction
|
||||
/// </summary>
|
||||
/// <param name="opcode">The opcode of the instruction</param>
|
||||
/// <param name="instruction">The instruction object to populate</param>
|
||||
/// <returns>True if the instruction was successfully decoded</returns>
|
||||
public override bool Decode(byte opcode, Instruction instruction)
|
||||
{
|
||||
// Set the instruction type
|
||||
instruction.Type = InstructionType.Adc;
|
||||
|
||||
// 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;
|
||||
}
|
||||
}
|
64
X86Disassembler/X86/Handlers/Adc/AdcAlImmHandler.cs
Normal file
64
X86Disassembler/X86/Handlers/Adc/AdcAlImmHandler.cs
Normal file
@ -0,0 +1,64 @@
|
||||
using X86Disassembler.X86.Operands;
|
||||
|
||||
namespace X86Disassembler.X86.Handlers.Adc;
|
||||
|
||||
/// <summary>
|
||||
/// Handler for ADC AL, imm8 instruction (0x14)
|
||||
/// </summary>
|
||||
public class AdcAlImmHandler : InstructionHandler
|
||||
{
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the AdcAlImmHandler class
|
||||
/// </summary>
|
||||
/// <param name="decoder">The instruction decoder that owns this handler</param>
|
||||
public AdcAlImmHandler(InstructionDecoder decoder)
|
||||
: base(decoder)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Checks if this handler can decode the given opcode
|
||||
/// </summary>
|
||||
/// <param name="opcode">The opcode to check</param>
|
||||
/// <returns>True if this handler can decode the opcode</returns>
|
||||
public override bool CanHandle(byte opcode)
|
||||
{
|
||||
return opcode == 0x14;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Decodes an ADC AL, imm8 instruction
|
||||
/// </summary>
|
||||
/// <param name="opcode">The opcode of the instruction</param>
|
||||
/// <param name="instruction">The instruction object to populate</param>
|
||||
/// <returns>True if the instruction was successfully decoded</returns>
|
||||
public override bool Decode(byte opcode, Instruction instruction)
|
||||
{
|
||||
// Set the instruction type
|
||||
instruction.Type = InstructionType.Adc;
|
||||
|
||||
// Check if we have enough bytes for the immediate value
|
||||
if (!Decoder.CanReadByte())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// Read the immediate byte
|
||||
var imm8 = Decoder.ReadByte();
|
||||
|
||||
// Create the AL register operand
|
||||
var destinationOperand = OperandFactory.CreateRegisterOperand8(RegisterIndex8.AL);
|
||||
|
||||
// Create the immediate operand
|
||||
var sourceOperand = OperandFactory.CreateImmediateOperand(imm8);
|
||||
|
||||
// Set the structured operands
|
||||
instruction.StructuredOperands =
|
||||
[
|
||||
destinationOperand,
|
||||
sourceOperand
|
||||
];
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
82
X86Disassembler/X86/Handlers/Adc/AdcImmToRm16Handler.cs
Normal file
82
X86Disassembler/X86/Handlers/Adc/AdcImmToRm16Handler.cs
Normal file
@ -0,0 +1,82 @@
|
||||
namespace X86Disassembler.X86.Handlers.Adc;
|
||||
|
||||
using Operands;
|
||||
|
||||
/// <summary>
|
||||
/// Handler for ADC r/m16, imm16 instruction (0x81 /2 with 0x66 prefix)
|
||||
/// </summary>
|
||||
public class AdcImmToRm16Handler : InstructionHandler
|
||||
{
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the AdcImmToRm16Handler class
|
||||
/// </summary>
|
||||
/// <param name="decoder">The instruction decoder that owns this handler</param>
|
||||
public AdcImmToRm16Handler(InstructionDecoder decoder)
|
||||
: base(decoder)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Checks if this handler can decode the given opcode
|
||||
/// </summary>
|
||||
/// <param name="opcode">The opcode to check</param>
|
||||
/// <returns>True if this handler can decode the opcode</returns>
|
||||
public override bool CanHandle(byte opcode)
|
||||
{
|
||||
// ADC r/m16, imm16 is encoded as 0x81 /2 with 0x66 prefix
|
||||
if (opcode != 0x81)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// Check if we have enough bytes to read the ModR/M byte
|
||||
if (!Decoder.CanReadByte())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// Check if the reg field of the ModR/M byte is 2 (ADC)
|
||||
var reg = ModRMDecoder.PeakModRMReg();
|
||||
|
||||
// Only handle when the operand size prefix is present
|
||||
return reg == 2 && Decoder.HasOperandSizePrefix();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Decodes a ADC r/m16, imm16 instruction
|
||||
/// </summary>
|
||||
/// <param name="opcode">The opcode of the instruction</param>
|
||||
/// <param name="instruction">The instruction object to populate</param>
|
||||
/// <returns>True if the instruction was successfully decoded</returns>
|
||||
public override bool Decode(byte opcode, Instruction instruction)
|
||||
{
|
||||
// Set the instruction type
|
||||
instruction.Type = InstructionType.Adc;
|
||||
|
||||
// Read the ModR/M byte, specifying that we're dealing with 16-bit operands
|
||||
var (_, _, _, destinationOperand) = ModRMDecoder.ReadModRM16();
|
||||
|
||||
// Note: The operand size is already set to 16-bit by the ReadModRM16 method
|
||||
|
||||
// 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;
|
||||
}
|
||||
}
|
@ -0,0 +1,84 @@
|
||||
namespace X86Disassembler.X86.Handlers.Adc;
|
||||
|
||||
using Operands;
|
||||
|
||||
/// <summary>
|
||||
/// Handler for ADC r/m16, imm8 (sign-extended) instruction (0x83 /2 with 0x66 prefix)
|
||||
/// </summary>
|
||||
public class AdcImmToRm16SignExtendedHandler : InstructionHandler
|
||||
{
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the AdcImmToRm16SignExtendedHandler class
|
||||
/// </summary>
|
||||
/// <param name="decoder">The instruction decoder that owns this handler</param>
|
||||
public AdcImmToRm16SignExtendedHandler(InstructionDecoder decoder)
|
||||
: base(decoder)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Checks if this handler can decode the given opcode
|
||||
/// </summary>
|
||||
/// <param name="opcode">The opcode to check</param>
|
||||
/// <returns>True if this handler can decode the opcode</returns>
|
||||
public override bool CanHandle(byte opcode)
|
||||
{
|
||||
// ADC r/m16, imm8 (sign-extended) is encoded as 0x83 /2 with 0x66 prefix
|
||||
if (opcode != 0x83)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// Check if we have enough bytes to read the ModR/M byte
|
||||
if (!Decoder.CanReadByte())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// Check if the reg field of the ModR/M byte is 2 (ADC)
|
||||
var reg = ModRMDecoder.PeakModRMReg();
|
||||
|
||||
// Only handle when the operand size prefix is present
|
||||
return reg == 2 && Decoder.HasOperandSizePrefix();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Decodes a ADC r/m16, imm8 (sign-extended) instruction
|
||||
/// </summary>
|
||||
/// <param name="opcode">The opcode of the instruction</param>
|
||||
/// <param name="instruction">The instruction object to populate</param>
|
||||
/// <returns>True if the instruction was successfully decoded</returns>
|
||||
public override bool Decode(byte opcode, Instruction instruction)
|
||||
{
|
||||
// Set the instruction type
|
||||
instruction.Type = InstructionType.Adc;
|
||||
|
||||
// For ADC r/m16, imm8 (sign-extended) (0x83 /2 with 0x66 prefix):
|
||||
// - The r/m field with mod specifies the destination operand (register or memory)
|
||||
// - The immediate value is the source operand (sign-extended from 8 to 16 bits)
|
||||
var (_, _, _, destinationOperand) = ModRMDecoder.ReadModRM16();
|
||||
|
||||
// Note: The operand size is already set to 16-bit by the ReadModRM16 method
|
||||
|
||||
// Check if we have enough bytes for the immediate value
|
||||
if (!Decoder.CanReadByte())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// Read the immediate value (sign-extended from 8 to 16 bits)
|
||||
short imm16 = (sbyte)Decoder.ReadByte();
|
||||
|
||||
// Create the immediate operand
|
||||
var sourceOperand = OperandFactory.CreateImmediateOperand((ushort)imm16, 16);
|
||||
|
||||
// Set the structured operands
|
||||
instruction.StructuredOperands =
|
||||
[
|
||||
destinationOperand,
|
||||
sourceOperand
|
||||
];
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
81
X86Disassembler/X86/Handlers/Adc/AdcImmToRm8Handler.cs
Normal file
81
X86Disassembler/X86/Handlers/Adc/AdcImmToRm8Handler.cs
Normal file
@ -0,0 +1,81 @@
|
||||
namespace X86Disassembler.X86.Handlers.Adc;
|
||||
|
||||
using Operands;
|
||||
|
||||
/// <summary>
|
||||
/// Handler for ADC r/m8, imm8 instruction (0x80 /2)
|
||||
/// </summary>
|
||||
public class AdcImmToRm8Handler : InstructionHandler
|
||||
{
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the AdcImmToRm8Handler class
|
||||
/// </summary>
|
||||
/// <param name="decoder">The instruction decoder that owns this handler</param>
|
||||
public AdcImmToRm8Handler(InstructionDecoder decoder)
|
||||
: base(decoder)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Checks if this handler can decode the given opcode
|
||||
/// </summary>
|
||||
/// <param name="opcode">The opcode to check</param>
|
||||
/// <returns>True if this handler can decode the opcode</returns>
|
||||
public override bool CanHandle(byte opcode)
|
||||
{
|
||||
if (opcode != 0x80)
|
||||
return false;
|
||||
|
||||
// Check if the reg field of the ModR/M byte is 2 (ADC)
|
||||
if (!Decoder.CanReadByte())
|
||||
return false;
|
||||
|
||||
var reg = ModRMDecoder.PeakModRMReg();
|
||||
|
||||
return reg == 2; // 2 = ADC
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Decodes an ADC r/m8, imm8 instruction
|
||||
/// </summary>
|
||||
/// <param name="opcode">The opcode of the instruction</param>
|
||||
/// <param name="instruction">The instruction object to populate</param>
|
||||
/// <returns>True if the instruction was successfully decoded</returns>
|
||||
public override bool Decode(byte opcode, Instruction instruction)
|
||||
{
|
||||
// Set the instruction type
|
||||
instruction.Type = InstructionType.Adc;
|
||||
|
||||
if (!Decoder.CanReadByte())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// Read the ModR/M byte
|
||||
// For ADC r/m8, imm8 (0x80 /2):
|
||||
// - 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;
|
||||
}
|
||||
}
|
72
X86Disassembler/X86/Handlers/Adc/AdcR16Rm16Handler.cs
Normal file
72
X86Disassembler/X86/Handlers/Adc/AdcR16Rm16Handler.cs
Normal file
@ -0,0 +1,72 @@
|
||||
namespace X86Disassembler.X86.Handlers.Adc;
|
||||
|
||||
using Operands;
|
||||
|
||||
/// <summary>
|
||||
/// Handler for ADC r16, r/m16 instruction (0x13 with 0x66 prefix)
|
||||
/// </summary>
|
||||
public class AdcR16Rm16Handler : InstructionHandler
|
||||
{
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the AdcR16Rm16Handler class
|
||||
/// </summary>
|
||||
/// <param name="decoder">The instruction decoder that owns this handler</param>
|
||||
public AdcR16Rm16Handler(InstructionDecoder decoder)
|
||||
: base(decoder)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Checks if this handler can decode the given opcode
|
||||
/// </summary>
|
||||
/// <param name="opcode">The opcode to check</param>
|
||||
/// <returns>True if this handler can decode the opcode</returns>
|
||||
public override bool CanHandle(byte opcode)
|
||||
{
|
||||
// ADC r16, r/m16 is encoded as 0x13 with 0x66 prefix
|
||||
if (opcode != 0x13)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// Only handle when the operand size prefix is present
|
||||
return Decoder.HasOperandSizePrefix();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Decodes a ADC r16, r/m16 instruction
|
||||
/// </summary>
|
||||
/// <param name="opcode">The opcode of the instruction</param>
|
||||
/// <param name="instruction">The instruction object to populate</param>
|
||||
/// <returns>True if the instruction was successfully decoded</returns>
|
||||
public override bool Decode(byte opcode, Instruction instruction)
|
||||
{
|
||||
// Set the instruction type
|
||||
instruction.Type = InstructionType.Adc;
|
||||
|
||||
// Check if we have enough bytes for the ModR/M byte
|
||||
if (!Decoder.CanReadByte())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// For ADC r16, r/m16 (0x13 with 0x66 prefix):
|
||||
// - The reg field of the ModR/M byte specifies the destination register
|
||||
// - The r/m field with mod specifies the source operand (register or memory)
|
||||
var (_, reg, _, sourceOperand) = ModRMDecoder.ReadModRM16();
|
||||
|
||||
// Note: The operand size is already set to 16-bit by the ReadModRM16 method
|
||||
|
||||
// Create the destination register operand with 16-bit size
|
||||
var destinationOperand = OperandFactory.CreateRegisterOperand(reg, 16);
|
||||
|
||||
// Set the structured operands
|
||||
instruction.StructuredOperands =
|
||||
[
|
||||
destinationOperand,
|
||||
sourceOperand
|
||||
];
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
66
X86Disassembler/X86/Handlers/Adc/AdcR32Rm32Handler.cs
Normal file
66
X86Disassembler/X86/Handlers/Adc/AdcR32Rm32Handler.cs
Normal file
@ -0,0 +1,66 @@
|
||||
using X86Disassembler.X86.Operands;
|
||||
|
||||
namespace X86Disassembler.X86.Handlers.Adc;
|
||||
|
||||
/// <summary>
|
||||
/// Handler for ADC r32, r/m32 instruction (0x13)
|
||||
/// </summary>
|
||||
public class AdcR32Rm32Handler : InstructionHandler
|
||||
{
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the AdcR32Rm32Handler class
|
||||
/// </summary>
|
||||
/// <param name="decoder">The instruction decoder that owns this handler</param>
|
||||
public AdcR32Rm32Handler(InstructionDecoder decoder)
|
||||
: base(decoder)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Checks if this handler can decode the given opcode
|
||||
/// </summary>
|
||||
/// <param name="opcode">The opcode to check</param>
|
||||
/// <returns>True if this handler can decode the opcode</returns>
|
||||
public override bool CanHandle(byte opcode)
|
||||
{
|
||||
// Only handle opcode 0x13 when the operand size prefix is NOT present
|
||||
// This ensures 16-bit handlers get priority when the prefix is present
|
||||
return opcode == 0x13 && !Decoder.HasOperandSizePrefix();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Decodes an ADC r32, r/m32 instruction
|
||||
/// </summary>
|
||||
/// <param name="opcode">The opcode of the instruction</param>
|
||||
/// <param name="instruction">The instruction object to populate</param>
|
||||
/// <returns>True if the instruction was successfully decoded</returns>
|
||||
public override bool Decode(byte opcode, Instruction instruction)
|
||||
{
|
||||
// Set the instruction type
|
||||
instruction.Type = InstructionType.Adc;
|
||||
|
||||
// Check if we have enough bytes for the ModR/M byte
|
||||
if (!Decoder.CanReadByte())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// Read the ModR/M byte
|
||||
// For ADC r32, r/m32 (0x13):
|
||||
// - 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;
|
||||
}
|
||||
}
|
64
X86Disassembler/X86/Handlers/Adc/AdcR8Rm8Handler.cs
Normal file
64
X86Disassembler/X86/Handlers/Adc/AdcR8Rm8Handler.cs
Normal file
@ -0,0 +1,64 @@
|
||||
using X86Disassembler.X86.Operands;
|
||||
|
||||
namespace X86Disassembler.X86.Handlers.Adc;
|
||||
|
||||
/// <summary>
|
||||
/// Handler for ADC r8, r/m8 instruction (0x12)
|
||||
/// </summary>
|
||||
public class AdcR8Rm8Handler : InstructionHandler
|
||||
{
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the AdcR8Rm8Handler class
|
||||
/// </summary>
|
||||
/// <param name="decoder">The instruction decoder that owns this handler</param>
|
||||
public AdcR8Rm8Handler(InstructionDecoder decoder)
|
||||
: base(decoder)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Checks if this handler can decode the given opcode
|
||||
/// </summary>
|
||||
/// <param name="opcode">The opcode to check</param>
|
||||
/// <returns>True if this handler can decode the opcode</returns>
|
||||
public override bool CanHandle(byte opcode)
|
||||
{
|
||||
return opcode == 0x12;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Decodes an ADC r8, r/m8 instruction
|
||||
/// </summary>
|
||||
/// <param name="opcode">The opcode of the instruction</param>
|
||||
/// <param name="instruction">The instruction object to populate</param>
|
||||
/// <returns>True if the instruction was successfully decoded</returns>
|
||||
public override bool Decode(byte opcode, Instruction instruction)
|
||||
{
|
||||
// Set the instruction type
|
||||
instruction.Type = InstructionType.Adc;
|
||||
|
||||
// Check if we have enough bytes for the ModR/M byte
|
||||
if (!Decoder.CanReadByte())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// Read the ModR/M byte
|
||||
// For ADC r8, r/m8 (0x12):
|
||||
// - 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
|
||||
var destinationOperand = OperandFactory.CreateRegisterOperand8(reg);
|
||||
|
||||
// Set the structured operands
|
||||
instruction.StructuredOperands =
|
||||
[
|
||||
destinationOperand,
|
||||
sourceOperand
|
||||
];
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
72
X86Disassembler/X86/Handlers/Adc/AdcRm16R16Handler.cs
Normal file
72
X86Disassembler/X86/Handlers/Adc/AdcRm16R16Handler.cs
Normal file
@ -0,0 +1,72 @@
|
||||
namespace X86Disassembler.X86.Handlers.Adc;
|
||||
|
||||
using Operands;
|
||||
|
||||
/// <summary>
|
||||
/// Handler for ADC r/m16, r16 instruction (0x11 with 0x66 prefix)
|
||||
/// </summary>
|
||||
public class AdcRm16R16Handler : InstructionHandler
|
||||
{
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the AdcRm16R16Handler class
|
||||
/// </summary>
|
||||
/// <param name="decoder">The instruction decoder that owns this handler</param>
|
||||
public AdcRm16R16Handler(InstructionDecoder decoder)
|
||||
: base(decoder)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Checks if this handler can decode the given opcode
|
||||
/// </summary>
|
||||
/// <param name="opcode">The opcode to check</param>
|
||||
/// <returns>True if this handler can decode the opcode</returns>
|
||||
public override bool CanHandle(byte opcode)
|
||||
{
|
||||
// ADC r/m16, r16 is encoded as 0x11 with 0x66 prefix
|
||||
if (opcode != 0x11)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// Only handle when the operand size prefix is present
|
||||
return Decoder.HasOperandSizePrefix();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Decodes a ADC r/m16, r16 instruction
|
||||
/// </summary>
|
||||
/// <param name="opcode">The opcode of the instruction</param>
|
||||
/// <param name="instruction">The instruction object to populate</param>
|
||||
/// <returns>True if the instruction was successfully decoded</returns>
|
||||
public override bool Decode(byte opcode, Instruction instruction)
|
||||
{
|
||||
// Set the instruction type
|
||||
instruction.Type = InstructionType.Adc;
|
||||
|
||||
// Check if we have enough bytes for the ModR/M byte
|
||||
if (!Decoder.CanReadByte())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// For ADC r/m16, r16 (0x11 with 0x66 prefix):
|
||||
// - The reg field of the ModR/M byte specifies the source register
|
||||
// - The r/m field with mod specifies the destination operand (register or memory)
|
||||
var (_, reg, _, destinationOperand) = ModRMDecoder.ReadModRM16();
|
||||
|
||||
// Note: The operand size is already set to 16-bit by the ReadModRM16 method
|
||||
|
||||
// Create the source register operand with 16-bit size
|
||||
var sourceOperand = OperandFactory.CreateRegisterOperand(reg, 16);
|
||||
|
||||
// Set the structured operands
|
||||
instruction.StructuredOperands =
|
||||
[
|
||||
destinationOperand,
|
||||
sourceOperand
|
||||
];
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
66
X86Disassembler/X86/Handlers/Adc/AdcRm32R32Handler.cs
Normal file
66
X86Disassembler/X86/Handlers/Adc/AdcRm32R32Handler.cs
Normal file
@ -0,0 +1,66 @@
|
||||
using X86Disassembler.X86.Operands;
|
||||
|
||||
namespace X86Disassembler.X86.Handlers.Adc;
|
||||
|
||||
/// <summary>
|
||||
/// Handler for ADC r/m32, r32 instruction (0x11)
|
||||
/// </summary>
|
||||
public class AdcRm32R32Handler : InstructionHandler
|
||||
{
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the AdcRm32R32Handler class
|
||||
/// </summary>
|
||||
/// <param name="decoder">The instruction decoder that owns this handler</param>
|
||||
public AdcRm32R32Handler(InstructionDecoder decoder)
|
||||
: base(decoder)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Checks if this handler can decode the given opcode
|
||||
/// </summary>
|
||||
/// <param name="opcode">The opcode to check</param>
|
||||
/// <returns>True if this handler can decode the opcode</returns>
|
||||
public override bool CanHandle(byte opcode)
|
||||
{
|
||||
// Only handle opcode 0x11 when the operand size prefix is NOT present
|
||||
// This ensures 16-bit handlers get priority when the prefix is present
|
||||
return opcode == 0x11 && !Decoder.HasOperandSizePrefix();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Decodes an ADC r/m32, r32 instruction
|
||||
/// </summary>
|
||||
/// <param name="opcode">The opcode of the instruction</param>
|
||||
/// <param name="instruction">The instruction object to populate</param>
|
||||
/// <returns>True if the instruction was successfully decoded</returns>
|
||||
public override bool Decode(byte opcode, Instruction instruction)
|
||||
{
|
||||
// Set the instruction type
|
||||
instruction.Type = InstructionType.Adc;
|
||||
|
||||
// Check if we have enough bytes for the ModR/M byte
|
||||
if (!Decoder.CanReadByte())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// Read the ModR/M byte
|
||||
// For ADC r/m32, r32 (0x11):
|
||||
// - 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;
|
||||
}
|
||||
}
|
64
X86Disassembler/X86/Handlers/Adc/AdcRm8R8Handler.cs
Normal file
64
X86Disassembler/X86/Handlers/Adc/AdcRm8R8Handler.cs
Normal file
@ -0,0 +1,64 @@
|
||||
using X86Disassembler.X86.Operands;
|
||||
|
||||
namespace X86Disassembler.X86.Handlers.Adc;
|
||||
|
||||
/// <summary>
|
||||
/// Handler for ADC r/m8, r8 instruction (0x10)
|
||||
/// </summary>
|
||||
public class AdcRm8R8Handler : InstructionHandler
|
||||
{
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the AdcRm8R8Handler class
|
||||
/// </summary>
|
||||
/// <param name="decoder">The instruction decoder that owns this handler</param>
|
||||
public AdcRm8R8Handler(InstructionDecoder decoder)
|
||||
: base(decoder)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Checks if this handler can decode the given opcode
|
||||
/// </summary>
|
||||
/// <param name="opcode">The opcode to check</param>
|
||||
/// <returns>True if this handler can decode the opcode</returns>
|
||||
public override bool CanHandle(byte opcode)
|
||||
{
|
||||
return opcode == 0x10;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Decodes an ADC r/m8, r8 instruction
|
||||
/// </summary>
|
||||
/// <param name="opcode">The opcode of the instruction</param>
|
||||
/// <param name="instruction">The instruction object to populate</param>
|
||||
/// <returns>True if the instruction was successfully decoded</returns>
|
||||
public override bool Decode(byte opcode, Instruction instruction)
|
||||
{
|
||||
// Set the instruction type
|
||||
instruction.Type = InstructionType.Adc;
|
||||
|
||||
// Check if we have enough bytes for the ModR/M byte
|
||||
if (!Decoder.CanReadByte())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// Read the ModR/M byte
|
||||
// For ADC r/m8, r8 (0x10):
|
||||
// - 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
|
||||
var sourceOperand = OperandFactory.CreateRegisterOperand8(reg);
|
||||
|
||||
// Set the structured operands
|
||||
instruction.StructuredOperands =
|
||||
[
|
||||
destinationOperand,
|
||||
sourceOperand
|
||||
];
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
@ -23,7 +23,9 @@ public class AddR32Rm32Handler : InstructionHandler
|
||||
/// <returns>True if this handler can decode the opcode</returns>
|
||||
public override bool CanHandle(byte opcode)
|
||||
{
|
||||
return opcode == 0x03;
|
||||
// Only handle opcode 0x03 when the operand size prefix is NOT present
|
||||
// This ensures 16-bit handlers get priority when the prefix is present
|
||||
return opcode == 0x03 && !Decoder.HasOperandSizePrefix();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -23,7 +23,9 @@ public class AddRm32R32Handler : InstructionHandler
|
||||
/// <returns>True if this handler can decode the opcode</returns>
|
||||
public override bool CanHandle(byte opcode)
|
||||
{
|
||||
return opcode == 0x01;
|
||||
// Only handle opcode 0x01 when the operand size prefix is NOT present
|
||||
// This ensures 16-bit handlers get priority when the prefix is present
|
||||
return opcode == 0x01 && !Decoder.HasOperandSizePrefix();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -23,7 +23,9 @@ public class AndMemRegHandler : InstructionHandler
|
||||
/// <returns>True if this handler can decode the opcode</returns>
|
||||
public override bool CanHandle(byte opcode)
|
||||
{
|
||||
return opcode == 0x21;
|
||||
// Only handle opcode 0x21 when the operand size prefix is NOT present
|
||||
// This ensures 16-bit handlers get priority when the prefix is present
|
||||
return opcode == 0x21 && !Decoder.HasOperandSizePrefix();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -23,7 +23,9 @@ public class AndR32Rm32Handler : InstructionHandler
|
||||
/// <returns>True if this handler can decode the opcode</returns>
|
||||
public override bool CanHandle(byte opcode)
|
||||
{
|
||||
return opcode == 0x23;
|
||||
// Only handle opcode 0x23 when the operand size prefix is NOT present
|
||||
// This ensures 16-bit handlers get priority when the prefix is present
|
||||
return opcode == 0x23 && !Decoder.HasOperandSizePrefix();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
84
X86Disassembler/X86/Handlers/Bit/BsfR32Rm32Handler.cs
Normal file
84
X86Disassembler/X86/Handlers/Bit/BsfR32Rm32Handler.cs
Normal file
@ -0,0 +1,84 @@
|
||||
namespace X86Disassembler.X86.Handlers.Bit;
|
||||
|
||||
using Operands;
|
||||
|
||||
/// <summary>
|
||||
/// Handler for BSF r32, r/m32 instruction (0F BC)
|
||||
/// </summary>
|
||||
public class BsfR32Rm32Handler : InstructionHandler
|
||||
{
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the BsfR32Rm32Handler class
|
||||
/// </summary>
|
||||
/// <param name="decoder">The instruction decoder that owns this handler</param>
|
||||
public BsfR32Rm32Handler(InstructionDecoder decoder)
|
||||
: base(decoder)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Checks if this handler can decode the given opcode
|
||||
/// </summary>
|
||||
/// <param name="opcode">The opcode to check</param>
|
||||
/// <returns>True if this handler can decode the opcode</returns>
|
||||
public override bool CanHandle(byte opcode)
|
||||
{
|
||||
// BSF r32, r/m32 is a two-byte opcode: 0F BC
|
||||
if (opcode != 0x0F)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// Check if we have enough bytes to read the second opcode byte
|
||||
if (!Decoder.CanReadByte())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// Check if the second byte is BC
|
||||
var secondByte = Decoder.PeakByte();
|
||||
|
||||
// Only handle when the operand size prefix is NOT present
|
||||
// This ensures 16-bit handlers get priority when the prefix is present
|
||||
return secondByte == 0xBC && !Decoder.HasOperandSizePrefix();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Decodes a BSF r32, r/m32 instruction
|
||||
/// </summary>
|
||||
/// <param name="opcode">The opcode of the instruction</param>
|
||||
/// <param name="instruction">The instruction object to populate</param>
|
||||
/// <returns>True if the instruction was successfully decoded</returns>
|
||||
public override bool Decode(byte opcode, Instruction instruction)
|
||||
{
|
||||
// Set the instruction type
|
||||
instruction.Type = InstructionType.Bsf;
|
||||
|
||||
// Read the second opcode byte (BC)
|
||||
Decoder.ReadByte();
|
||||
|
||||
// Check if we have enough bytes for the ModR/M byte
|
||||
if (!Decoder.CanReadByte())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// Read the ModR/M byte
|
||||
// For BSF r32, r/m32 (0F BC):
|
||||
// - 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;
|
||||
}
|
||||
}
|
84
X86Disassembler/X86/Handlers/Bit/BsrR32Rm32Handler.cs
Normal file
84
X86Disassembler/X86/Handlers/Bit/BsrR32Rm32Handler.cs
Normal file
@ -0,0 +1,84 @@
|
||||
namespace X86Disassembler.X86.Handlers.Bit;
|
||||
|
||||
using Operands;
|
||||
|
||||
/// <summary>
|
||||
/// Handler for BSR r32, r/m32 instruction (0F BD)
|
||||
/// </summary>
|
||||
public class BsrR32Rm32Handler : InstructionHandler
|
||||
{
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the BsrR32Rm32Handler class
|
||||
/// </summary>
|
||||
/// <param name="decoder">The instruction decoder that owns this handler</param>
|
||||
public BsrR32Rm32Handler(InstructionDecoder decoder)
|
||||
: base(decoder)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Checks if this handler can decode the given opcode
|
||||
/// </summary>
|
||||
/// <param name="opcode">The opcode to check</param>
|
||||
/// <returns>True if this handler can decode the opcode</returns>
|
||||
public override bool CanHandle(byte opcode)
|
||||
{
|
||||
// BSR r32, r/m32 is a two-byte opcode: 0F BD
|
||||
if (opcode != 0x0F)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// Check if we have enough bytes to read the second opcode byte
|
||||
if (!Decoder.CanReadByte())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// Check if the second byte is BD
|
||||
var secondByte = Decoder.PeakByte();
|
||||
|
||||
// Only handle when the operand size prefix is NOT present
|
||||
// This ensures 16-bit handlers get priority when the prefix is present
|
||||
return secondByte == 0xBD && !Decoder.HasOperandSizePrefix();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Decodes a BSR r32, r/m32 instruction
|
||||
/// </summary>
|
||||
/// <param name="opcode">The opcode of the instruction</param>
|
||||
/// <param name="instruction">The instruction object to populate</param>
|
||||
/// <returns>True if the instruction was successfully decoded</returns>
|
||||
public override bool Decode(byte opcode, Instruction instruction)
|
||||
{
|
||||
// Set the instruction type
|
||||
instruction.Type = InstructionType.Bsr;
|
||||
|
||||
// Read the second opcode byte (BD)
|
||||
Decoder.ReadByte();
|
||||
|
||||
// Check if we have enough bytes for the ModR/M byte
|
||||
if (!Decoder.CanReadByte())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// Read the ModR/M byte
|
||||
// For BSR r32, r/m32 (0F BD):
|
||||
// - 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;
|
||||
}
|
||||
}
|
84
X86Disassembler/X86/Handlers/Bit/BtR32Rm32Handler.cs
Normal file
84
X86Disassembler/X86/Handlers/Bit/BtR32Rm32Handler.cs
Normal file
@ -0,0 +1,84 @@
|
||||
namespace X86Disassembler.X86.Handlers.Bit;
|
||||
|
||||
using Operands;
|
||||
|
||||
/// <summary>
|
||||
/// Handler for BT r32, r/m32 instruction (0F A3)
|
||||
/// </summary>
|
||||
public class BtR32Rm32Handler : InstructionHandler
|
||||
{
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the BtR32Rm32Handler class
|
||||
/// </summary>
|
||||
/// <param name="decoder">The instruction decoder that owns this handler</param>
|
||||
public BtR32Rm32Handler(InstructionDecoder decoder)
|
||||
: base(decoder)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Checks if this handler can decode the given opcode
|
||||
/// </summary>
|
||||
/// <param name="opcode">The opcode to check</param>
|
||||
/// <returns>True if this handler can decode the opcode</returns>
|
||||
public override bool CanHandle(byte opcode)
|
||||
{
|
||||
// BT r32, r/m32 is a two-byte opcode: 0F A3
|
||||
if (opcode != 0x0F)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// Check if we have enough bytes to read the second opcode byte
|
||||
if (!Decoder.CanReadByte())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// Check if the second byte is A3
|
||||
var secondByte = Decoder.PeakByte();
|
||||
|
||||
// Only handle when the operand size prefix is NOT present
|
||||
// This ensures 16-bit handlers get priority when the prefix is present
|
||||
return secondByte == 0xA3 && !Decoder.HasOperandSizePrefix();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Decodes a BT r32, r/m32 instruction
|
||||
/// </summary>
|
||||
/// <param name="opcode">The opcode of the instruction</param>
|
||||
/// <param name="instruction">The instruction object to populate</param>
|
||||
/// <returns>True if the instruction was successfully decoded</returns>
|
||||
public override bool Decode(byte opcode, Instruction instruction)
|
||||
{
|
||||
// Set the instruction type
|
||||
instruction.Type = InstructionType.Bt;
|
||||
|
||||
// Read the second opcode byte (A3)
|
||||
Decoder.ReadByte();
|
||||
|
||||
// Check if we have enough bytes for the ModR/M byte
|
||||
if (!Decoder.CanReadByte())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// Read the ModR/M byte
|
||||
// For BT r/m32, r32 (0F A3):
|
||||
// - The r/m field with mod specifies the destination operand (register or memory)
|
||||
// - The reg field specifies the bit index register
|
||||
var (_, reg, _, destinationOperand) = ModRMDecoder.ReadModRM();
|
||||
|
||||
// Create the register operand for the reg field
|
||||
var bitIndexOperand = OperandFactory.CreateRegisterOperand(reg);
|
||||
|
||||
// Set the structured operands
|
||||
instruction.StructuredOperands =
|
||||
[
|
||||
destinationOperand,
|
||||
bitIndexOperand
|
||||
];
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
101
X86Disassembler/X86/Handlers/Bit/BtRm32ImmHandler.cs
Normal file
101
X86Disassembler/X86/Handlers/Bit/BtRm32ImmHandler.cs
Normal file
@ -0,0 +1,101 @@
|
||||
namespace X86Disassembler.X86.Handlers.Bit;
|
||||
|
||||
using Operands;
|
||||
|
||||
/// <summary>
|
||||
/// Handler for BT r/m32, imm8 instruction (0F BA /4)
|
||||
/// </summary>
|
||||
public class BtRm32ImmHandler : InstructionHandler
|
||||
{
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the BtRm32ImmHandler class
|
||||
/// </summary>
|
||||
/// <param name="decoder">The instruction decoder that owns this handler</param>
|
||||
public BtRm32ImmHandler(InstructionDecoder decoder)
|
||||
: base(decoder)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Checks if this handler can decode the given opcode
|
||||
/// </summary>
|
||||
/// <param name="opcode">The opcode to check</param>
|
||||
/// <returns>True if this handler can decode the opcode</returns>
|
||||
public override bool CanHandle(byte opcode)
|
||||
{
|
||||
// BT r/m32, imm8 is encoded as 0F BA /4
|
||||
if (opcode != 0x0F)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// Check if we have enough bytes to read the second opcode byte
|
||||
if (!Decoder.CanRead(2))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
var (secondByte, modRm) = Decoder.PeakTwoBytes();
|
||||
|
||||
// Check if the second byte is BA
|
||||
if (secondByte != 0xBA)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// Check if the reg field of the ModR/M byte is 4 (BT)
|
||||
var reg = ModRMDecoder.GetRegFromModRM(modRm);
|
||||
|
||||
// Only handle when the operand size prefix is NOT present
|
||||
// This ensures 16-bit handlers get priority when the prefix is present
|
||||
return reg == 4 && !Decoder.HasOperandSizePrefix();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Decodes a BT r/m32, imm8 instruction
|
||||
/// </summary>
|
||||
/// <param name="opcode">The opcode of the instruction</param>
|
||||
/// <param name="instruction">The instruction object to populate</param>
|
||||
/// <returns>True if the instruction was successfully decoded</returns>
|
||||
public override bool Decode(byte opcode, Instruction instruction)
|
||||
{
|
||||
// Set the instruction type
|
||||
instruction.Type = InstructionType.Bt;
|
||||
|
||||
// Read the second opcode byte (BA)
|
||||
Decoder.ReadByte();
|
||||
|
||||
// Check if we have enough bytes for the ModR/M byte
|
||||
if (!Decoder.CanReadByte())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// Read the ModR/M byte
|
||||
// For BT r/m32, imm8 (0F BA /4):
|
||||
// - The r/m field with mod specifies the destination operand (register or memory)
|
||||
// - The immediate value specifies the bit index
|
||||
var (_, _, _, destinationOperand) = ModRMDecoder.ReadModRM();
|
||||
|
||||
// Check if we have enough bytes for the immediate value
|
||||
if (!Decoder.CanReadByte())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// Read the immediate byte for the bit position
|
||||
byte imm8 = Decoder.ReadByte();
|
||||
|
||||
// Create the immediate operand
|
||||
var bitIndexOperand = OperandFactory.CreateImmediateOperand(imm8, 8);
|
||||
|
||||
// Set the structured operands
|
||||
instruction.StructuredOperands =
|
||||
[
|
||||
destinationOperand,
|
||||
bitIndexOperand
|
||||
];
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
84
X86Disassembler/X86/Handlers/Bit/BtcR32Rm32Handler.cs
Normal file
84
X86Disassembler/X86/Handlers/Bit/BtcR32Rm32Handler.cs
Normal file
@ -0,0 +1,84 @@
|
||||
namespace X86Disassembler.X86.Handlers.Bit;
|
||||
|
||||
using Operands;
|
||||
|
||||
/// <summary>
|
||||
/// Handler for BTC r32, r/m32 instruction (0F BB)
|
||||
/// </summary>
|
||||
public class BtcR32Rm32Handler : InstructionHandler
|
||||
{
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the BtcR32Rm32Handler class
|
||||
/// </summary>
|
||||
/// <param name="decoder">The instruction decoder that owns this handler</param>
|
||||
public BtcR32Rm32Handler(InstructionDecoder decoder)
|
||||
: base(decoder)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Checks if this handler can decode the given opcode
|
||||
/// </summary>
|
||||
/// <param name="opcode">The opcode to check</param>
|
||||
/// <returns>True if this handler can decode the opcode</returns>
|
||||
public override bool CanHandle(byte opcode)
|
||||
{
|
||||
// BTC r32, r/m32 is a two-byte opcode: 0F BB
|
||||
if (opcode != 0x0F)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// Check if we have enough bytes to read the second opcode byte
|
||||
if (!Decoder.CanReadByte())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// Check if the second byte is BB
|
||||
var secondByte = Decoder.PeakByte();
|
||||
|
||||
// Only handle when the operand size prefix is NOT present
|
||||
// This ensures 16-bit handlers get priority when the prefix is present
|
||||
return secondByte == 0xBB && !Decoder.HasOperandSizePrefix();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Decodes a BTC r32, r/m32 instruction
|
||||
/// </summary>
|
||||
/// <param name="opcode">The opcode of the instruction</param>
|
||||
/// <param name="instruction">The instruction object to populate</param>
|
||||
/// <returns>True if the instruction was successfully decoded</returns>
|
||||
public override bool Decode(byte opcode, Instruction instruction)
|
||||
{
|
||||
// Set the instruction type
|
||||
instruction.Type = InstructionType.Btc;
|
||||
|
||||
// Read the second opcode byte (BB)
|
||||
Decoder.ReadByte();
|
||||
|
||||
// Check if we have enough bytes for the ModR/M byte
|
||||
if (!Decoder.CanReadByte())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// Read the ModR/M byte
|
||||
// For BTC r/m32, r32 (0F BB):
|
||||
// - The r/m field with mod specifies the destination operand (register or memory)
|
||||
// - The reg field specifies the bit index register
|
||||
var (_, reg, _, destinationOperand) = ModRMDecoder.ReadModRM();
|
||||
|
||||
// Create the register operand for the reg field
|
||||
var bitIndexOperand = OperandFactory.CreateRegisterOperand(reg);
|
||||
|
||||
// Set the structured operands
|
||||
instruction.StructuredOperands =
|
||||
[
|
||||
destinationOperand,
|
||||
bitIndexOperand
|
||||
];
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
101
X86Disassembler/X86/Handlers/Bit/BtcRm32ImmHandler.cs
Normal file
101
X86Disassembler/X86/Handlers/Bit/BtcRm32ImmHandler.cs
Normal file
@ -0,0 +1,101 @@
|
||||
namespace X86Disassembler.X86.Handlers.Bit;
|
||||
|
||||
using Operands;
|
||||
|
||||
/// <summary>
|
||||
/// Handler for BTC r/m32, imm8 instruction (0F BA /7)
|
||||
/// </summary>
|
||||
public class BtcRm32ImmHandler : InstructionHandler
|
||||
{
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the BtcRm32ImmHandler class
|
||||
/// </summary>
|
||||
/// <param name="decoder">The instruction decoder that owns this handler</param>
|
||||
public BtcRm32ImmHandler(InstructionDecoder decoder)
|
||||
: base(decoder)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Checks if this handler can decode the given opcode
|
||||
/// </summary>
|
||||
/// <param name="opcode">The opcode to check</param>
|
||||
/// <returns>True if this handler can decode the opcode</returns>
|
||||
public override bool CanHandle(byte opcode)
|
||||
{
|
||||
// BTC r/m32, imm8 is encoded as 0F BA /7
|
||||
if (opcode != 0x0F)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// Check if we have enough bytes to read the second opcode byte
|
||||
if (!Decoder.CanRead(2))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
var (secondByte, modRm) = Decoder.PeakTwoBytes();
|
||||
|
||||
// Check if the second byte is BA
|
||||
if (secondByte != 0xBA)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// Check if the reg field of the ModR/M byte is 7 (BTC)
|
||||
var reg = ModRMDecoder.GetRegFromModRM(modRm);
|
||||
|
||||
// Only handle when the operand size prefix is NOT present
|
||||
// This ensures 16-bit handlers get priority when the prefix is present
|
||||
return reg == 7 && !Decoder.HasOperandSizePrefix();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Decodes a BTC r/m32, imm8 instruction
|
||||
/// </summary>
|
||||
/// <param name="opcode">The opcode of the instruction</param>
|
||||
/// <param name="instruction">The instruction object to populate</param>
|
||||
/// <returns>True if the instruction was successfully decoded</returns>
|
||||
public override bool Decode(byte opcode, Instruction instruction)
|
||||
{
|
||||
// Set the instruction type
|
||||
instruction.Type = InstructionType.Btc;
|
||||
|
||||
// Read the second opcode byte (BA)
|
||||
Decoder.ReadByte();
|
||||
|
||||
// Check if we have enough bytes for the ModR/M byte
|
||||
if (!Decoder.CanReadByte())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// Read the ModR/M byte
|
||||
// For BTC r/m32, imm8 (0F BA /7):
|
||||
// - The r/m field with mod specifies the destination operand (register or memory)
|
||||
// - The immediate value specifies the bit index
|
||||
var (_, _, _, destinationOperand) = ModRMDecoder.ReadModRM();
|
||||
|
||||
// Check if we have enough bytes for the immediate value
|
||||
if (!Decoder.CanReadByte())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// Read the immediate byte for the bit position
|
||||
byte imm8 = Decoder.ReadByte();
|
||||
|
||||
// Create the immediate operand
|
||||
var bitIndexOperand = OperandFactory.CreateImmediateOperand(imm8, 8);
|
||||
|
||||
// Set the structured operands
|
||||
instruction.StructuredOperands =
|
||||
[
|
||||
destinationOperand,
|
||||
bitIndexOperand
|
||||
];
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
84
X86Disassembler/X86/Handlers/Bit/BtrR32Rm32Handler.cs
Normal file
84
X86Disassembler/X86/Handlers/Bit/BtrR32Rm32Handler.cs
Normal file
@ -0,0 +1,84 @@
|
||||
namespace X86Disassembler.X86.Handlers.Bit;
|
||||
|
||||
using Operands;
|
||||
|
||||
/// <summary>
|
||||
/// Handler for BTR r32, r/m32 instruction (0F B3)
|
||||
/// </summary>
|
||||
public class BtrR32Rm32Handler : InstructionHandler
|
||||
{
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the BtrR32Rm32Handler class
|
||||
/// </summary>
|
||||
/// <param name="decoder">The instruction decoder that owns this handler</param>
|
||||
public BtrR32Rm32Handler(InstructionDecoder decoder)
|
||||
: base(decoder)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Checks if this handler can decode the given opcode
|
||||
/// </summary>
|
||||
/// <param name="opcode">The opcode to check</param>
|
||||
/// <returns>True if this handler can decode the opcode</returns>
|
||||
public override bool CanHandle(byte opcode)
|
||||
{
|
||||
// BTR r32, r/m32 is a two-byte opcode: 0F B3
|
||||
if (opcode != 0x0F)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// Check if we have enough bytes to read the second opcode byte
|
||||
if (!Decoder.CanReadByte())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// Check if the second byte is B3
|
||||
var secondByte = Decoder.PeakByte();
|
||||
|
||||
// Only handle when the operand size prefix is NOT present
|
||||
// This ensures 16-bit handlers get priority when the prefix is present
|
||||
return secondByte == 0xB3 && !Decoder.HasOperandSizePrefix();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Decodes a BTR r32, r/m32 instruction
|
||||
/// </summary>
|
||||
/// <param name="opcode">The opcode of the instruction</param>
|
||||
/// <param name="instruction">The instruction object to populate</param>
|
||||
/// <returns>True if the instruction was successfully decoded</returns>
|
||||
public override bool Decode(byte opcode, Instruction instruction)
|
||||
{
|
||||
// Set the instruction type
|
||||
instruction.Type = InstructionType.Btr;
|
||||
|
||||
// Read the second opcode byte (B3)
|
||||
Decoder.ReadByte();
|
||||
|
||||
// Check if we have enough bytes for the ModR/M byte
|
||||
if (!Decoder.CanReadByte())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// Read the ModR/M byte
|
||||
// For BTR r/m32, r32 (0F B3):
|
||||
// - The r/m field with mod specifies the destination operand (register or memory)
|
||||
// - The reg field specifies the bit index register
|
||||
var (_, reg, _, destinationOperand) = ModRMDecoder.ReadModRM();
|
||||
|
||||
// Create the register operand for the reg field
|
||||
var bitIndexOperand = OperandFactory.CreateRegisterOperand(reg);
|
||||
|
||||
// Set the structured operands
|
||||
instruction.StructuredOperands =
|
||||
[
|
||||
destinationOperand,
|
||||
bitIndexOperand
|
||||
];
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
102
X86Disassembler/X86/Handlers/Bit/BtrRm32ImmHandler.cs
Normal file
102
X86Disassembler/X86/Handlers/Bit/BtrRm32ImmHandler.cs
Normal file
@ -0,0 +1,102 @@
|
||||
namespace X86Disassembler.X86.Handlers.Bit;
|
||||
|
||||
using Operands;
|
||||
|
||||
/// <summary>
|
||||
/// Handler for BTR r/m32, imm8 instruction (0F BA /6)
|
||||
/// </summary>
|
||||
public class BtrRm32ImmHandler : InstructionHandler
|
||||
{
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the BtrRm32ImmHandler class
|
||||
/// </summary>
|
||||
/// <param name="decoder">The instruction decoder that owns this handler</param>
|
||||
public BtrRm32ImmHandler(InstructionDecoder decoder)
|
||||
: base(decoder)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Checks if this handler can decode the given opcode
|
||||
/// </summary>
|
||||
/// <param name="opcode">The opcode to check</param>
|
||||
/// <returns>True if this handler can decode the opcode</returns>
|
||||
public override bool CanHandle(byte opcode)
|
||||
{
|
||||
// BTR r/m32, imm8 is encoded as 0F BA /6
|
||||
if (opcode != 0x0F)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
// Check if we have enough bytes to read the second opcode byte
|
||||
if (!Decoder.CanRead(2))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
var (secondByte, modRm) = Decoder.PeakTwoBytes();
|
||||
|
||||
// Check if the second byte is BA
|
||||
if (secondByte != 0xBA)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// Check if the reg field of the ModR/M byte is 6 (BTR)
|
||||
var reg = ModRMDecoder.GetRegFromModRM(modRm);
|
||||
|
||||
// Only handle when the operand size prefix is NOT present
|
||||
// This ensures 16-bit handlers get priority when the prefix is present
|
||||
return reg == 6 && !Decoder.HasOperandSizePrefix();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Decodes a BTR r/m32, imm8 instruction
|
||||
/// </summary>
|
||||
/// <param name="opcode">The opcode of the instruction</param>
|
||||
/// <param name="instruction">The instruction object to populate</param>
|
||||
/// <returns>True if the instruction was successfully decoded</returns>
|
||||
public override bool Decode(byte opcode, Instruction instruction)
|
||||
{
|
||||
// Set the instruction type
|
||||
instruction.Type = InstructionType.Btr;
|
||||
|
||||
// Read the second opcode byte (BA)
|
||||
Decoder.ReadByte();
|
||||
|
||||
// Check if we have enough bytes for the ModR/M byte
|
||||
if (!Decoder.CanReadByte())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// Read the ModR/M byte
|
||||
// For BTR r/m32, imm8 (0F BA /6):
|
||||
// - The r/m field with mod specifies the destination operand (register or memory)
|
||||
// - The immediate value specifies the bit index
|
||||
var (_, _, _, destinationOperand) = ModRMDecoder.ReadModRM();
|
||||
|
||||
// Check if we have enough bytes for the immediate value
|
||||
if (!Decoder.CanReadByte())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// Read the immediate byte for the bit position
|
||||
byte imm8 = Decoder.ReadByte();
|
||||
|
||||
// Create the immediate operand
|
||||
var bitIndexOperand = OperandFactory.CreateImmediateOperand(imm8, 8);
|
||||
|
||||
// Set the structured operands
|
||||
instruction.StructuredOperands =
|
||||
[
|
||||
destinationOperand,
|
||||
bitIndexOperand
|
||||
];
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
84
X86Disassembler/X86/Handlers/Bit/BtsR32Rm32Handler.cs
Normal file
84
X86Disassembler/X86/Handlers/Bit/BtsR32Rm32Handler.cs
Normal file
@ -0,0 +1,84 @@
|
||||
namespace X86Disassembler.X86.Handlers.Bit;
|
||||
|
||||
using Operands;
|
||||
|
||||
/// <summary>
|
||||
/// Handler for BTS r32, r/m32 instruction (0F AB)
|
||||
/// </summary>
|
||||
public class BtsR32Rm32Handler : InstructionHandler
|
||||
{
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the BtsR32Rm32Handler class
|
||||
/// </summary>
|
||||
/// <param name="decoder">The instruction decoder that owns this handler</param>
|
||||
public BtsR32Rm32Handler(InstructionDecoder decoder)
|
||||
: base(decoder)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Checks if this handler can decode the given opcode
|
||||
/// </summary>
|
||||
/// <param name="opcode">The opcode to check</param>
|
||||
/// <returns>True if this handler can decode the opcode</returns>
|
||||
public override bool CanHandle(byte opcode)
|
||||
{
|
||||
// BTS r32, r/m32 is a two-byte opcode: 0F AB
|
||||
if (opcode != 0x0F)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// Check if we have enough bytes to read the second opcode byte
|
||||
if (!Decoder.CanReadByte())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// Check if the second byte is AB
|
||||
var secondByte = Decoder.PeakByte();
|
||||
|
||||
// Only handle when the operand size prefix is NOT present
|
||||
// This ensures 16-bit handlers get priority when the prefix is present
|
||||
return secondByte == 0xAB && !Decoder.HasOperandSizePrefix();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Decodes a BTS r32, r/m32 instruction
|
||||
/// </summary>
|
||||
/// <param name="opcode">The opcode of the instruction</param>
|
||||
/// <param name="instruction">The instruction object to populate</param>
|
||||
/// <returns>True if the instruction was successfully decoded</returns>
|
||||
public override bool Decode(byte opcode, Instruction instruction)
|
||||
{
|
||||
// Set the instruction type
|
||||
instruction.Type = InstructionType.Bts;
|
||||
|
||||
// Read the second opcode byte (AB)
|
||||
Decoder.ReadByte();
|
||||
|
||||
// Check if we have enough bytes for the ModR/M byte
|
||||
if (!Decoder.CanReadByte())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// Read the ModR/M byte
|
||||
// For BTS r/m32, r32 (0F AB):
|
||||
// - The r/m field with mod specifies the destination operand (register or memory)
|
||||
// - The reg field specifies the bit index register
|
||||
var (_, reg, _, destinationOperand) = ModRMDecoder.ReadModRM();
|
||||
|
||||
// Create the register operand for the reg field
|
||||
var bitIndexOperand = OperandFactory.CreateRegisterOperand(reg);
|
||||
|
||||
// Set the structured operands
|
||||
instruction.StructuredOperands =
|
||||
[
|
||||
destinationOperand,
|
||||
bitIndexOperand
|
||||
];
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
101
X86Disassembler/X86/Handlers/Bit/BtsRm32ImmHandler.cs
Normal file
101
X86Disassembler/X86/Handlers/Bit/BtsRm32ImmHandler.cs
Normal file
@ -0,0 +1,101 @@
|
||||
namespace X86Disassembler.X86.Handlers.Bit;
|
||||
|
||||
using Operands;
|
||||
|
||||
/// <summary>
|
||||
/// Handler for BTS r/m32, imm8 instruction (0F BA /5)
|
||||
/// </summary>
|
||||
public class BtsRm32ImmHandler : InstructionHandler
|
||||
{
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the BtsRm32ImmHandler class
|
||||
/// </summary>
|
||||
/// <param name="decoder">The instruction decoder that owns this handler</param>
|
||||
public BtsRm32ImmHandler(InstructionDecoder decoder)
|
||||
: base(decoder)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Checks if this handler can decode the given opcode
|
||||
/// </summary>
|
||||
/// <param name="opcode">The opcode to check</param>
|
||||
/// <returns>True if this handler can decode the opcode</returns>
|
||||
public override bool CanHandle(byte opcode)
|
||||
{
|
||||
// BTS r/m32, imm8 is encoded as 0F BA /5
|
||||
if (opcode != 0x0F)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// Check if we have enough bytes to read the second opcode byte
|
||||
if (!Decoder.CanRead(2))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
var (secondByte, modRm) = Decoder.PeakTwoBytes();
|
||||
|
||||
// Check if the second byte is BA
|
||||
if (secondByte != 0xBA)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// Check if the reg field of the ModR/M byte is 5 (BTS)
|
||||
var reg = ModRMDecoder.GetRegFromModRM(modRm);
|
||||
|
||||
// Only handle when the operand size prefix is NOT present
|
||||
// This ensures 16-bit handlers get priority when the prefix is present
|
||||
return reg == 5 && !Decoder.HasOperandSizePrefix();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Decodes a BTS r/m32, imm8 instruction
|
||||
/// </summary>
|
||||
/// <param name="opcode">The opcode of the instruction</param>
|
||||
/// <param name="instruction">The instruction object to populate</param>
|
||||
/// <returns>True if the instruction was successfully decoded</returns>
|
||||
public override bool Decode(byte opcode, Instruction instruction)
|
||||
{
|
||||
// Set the instruction type
|
||||
instruction.Type = InstructionType.Bts;
|
||||
|
||||
// Read the second opcode byte (BA)
|
||||
Decoder.ReadByte();
|
||||
|
||||
// Check if we have enough bytes for the ModR/M byte
|
||||
if (!Decoder.CanReadByte())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// Read the ModR/M byte
|
||||
// For BTS r/m32, imm8 (0F BA /5):
|
||||
// - The r/m field with mod specifies the destination operand (register or memory)
|
||||
// - The immediate value specifies the bit index
|
||||
var (_, _, _, destinationOperand) = ModRMDecoder.ReadModRM();
|
||||
|
||||
// Check if we have enough bytes for the immediate value
|
||||
if (!Decoder.CanReadByte())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// Read the immediate byte for the bit position
|
||||
byte imm8 = Decoder.ReadByte();
|
||||
|
||||
// Create the immediate operand
|
||||
var bitIndexOperand = OperandFactory.CreateImmediateOperand(imm8, 8);
|
||||
|
||||
// Set the structured operands
|
||||
instruction.StructuredOperands =
|
||||
[
|
||||
destinationOperand,
|
||||
bitIndexOperand
|
||||
];
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
94
X86Disassembler/X86/Handlers/Call/CallFarPtrHandler.cs
Normal file
94
X86Disassembler/X86/Handlers/Call/CallFarPtrHandler.cs
Normal file
@ -0,0 +1,94 @@
|
||||
using X86Disassembler.X86.Operands;
|
||||
|
||||
namespace X86Disassembler.X86.Handlers.Call;
|
||||
|
||||
/// <summary>
|
||||
/// Handler for CALL m16:32 instruction (FF /3) - Far call with memory operand
|
||||
/// </summary>
|
||||
public class CallFarPtrHandler : InstructionHandler
|
||||
{
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the CallFarPtrHandler class
|
||||
/// </summary>
|
||||
/// <param name="decoder">The instruction decoder that owns this handler</param>
|
||||
public CallFarPtrHandler(InstructionDecoder decoder)
|
||||
: base(decoder)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Checks if this handler can decode the given opcode
|
||||
/// </summary>
|
||||
/// <param name="opcode">The opcode to check</param>
|
||||
/// <returns>True if this handler can decode the opcode</returns>
|
||||
public override bool CanHandle(byte opcode)
|
||||
{
|
||||
// CALL m16:32 is encoded as FF /3
|
||||
if (opcode != 0xFF)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// Check if we have enough bytes to read the ModR/M byte
|
||||
if (!Decoder.CanReadByte())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// Extract the reg field (bits 3-5)
|
||||
var reg = ModRMDecoder.PeakModRMReg();
|
||||
|
||||
// CALL m16:32 is encoded as FF /3 (reg field = 3)
|
||||
return reg == 3;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Decodes a CALL m16:32 instruction (far call)
|
||||
/// </summary>
|
||||
/// <param name="opcode">The opcode of the instruction</param>
|
||||
/// <param name="instruction">The instruction object to populate</param>
|
||||
/// <returns>True if the instruction was successfully decoded</returns>
|
||||
public override bool Decode(byte opcode, Instruction instruction)
|
||||
{
|
||||
// Set the instruction type
|
||||
instruction.Type = InstructionType.Call;
|
||||
|
||||
// Check if we have enough bytes for the ModR/M byte
|
||||
if (!Decoder.CanReadByte())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// Read the ModR/M byte
|
||||
// For CALL m16:32 (FF /3):
|
||||
// - The r/m field with mod specifies the memory operand
|
||||
// - This instruction can only reference memory, not registers
|
||||
var (mod, reg, rm, operand) = ModRMDecoder.ReadModRM();
|
||||
|
||||
// For far calls, we need to ensure this is a memory operand, not a register
|
||||
// If mod == 3, then it's a register operand, which is invalid for far calls
|
||||
if (mod == 3)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// Create a special far pointer operand by modifying the memory operand
|
||||
// to indicate it's a far pointer (fword ptr)
|
||||
// We need to ensure the operand is a memory operand before converting it
|
||||
if (!(operand is MemoryOperand memOperand))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
var farPtrOperand = OperandFactory.CreateFarPointerOperand(memOperand);
|
||||
|
||||
// Set the structured operands
|
||||
// CALL has only one operand
|
||||
instruction.StructuredOperands =
|
||||
[
|
||||
farPtrOperand
|
||||
];
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
@ -39,7 +39,9 @@ public class CallRm32Handler : InstructionHandler
|
||||
var reg = ModRMDecoder.PeakModRMReg();
|
||||
|
||||
// CALL r/m32 is encoded as FF /2 (reg field = 2)
|
||||
return reg == 2;
|
||||
// Only handle when the operand size prefix is NOT present
|
||||
// This ensures 16-bit handlers get priority when the prefix is present
|
||||
return reg == 2 && !Decoder.HasOperandSizePrefix();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -23,7 +23,9 @@ public class CmpR32Rm32Handler : InstructionHandler
|
||||
/// <returns>True if this handler can decode the opcode</returns>
|
||||
public override bool CanHandle(byte opcode)
|
||||
{
|
||||
return opcode == 0x3B;
|
||||
// Only handle opcode 0x3B when the operand size prefix is NOT present
|
||||
// This ensures 16-bit handlers get priority when the prefix is present
|
||||
return opcode == 0x3B && !Decoder.HasOperandSizePrefix();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -23,7 +23,9 @@ public class CmpRm32R32Handler : InstructionHandler
|
||||
/// <returns>True if this handler can decode the opcode</returns>
|
||||
public override bool CanHandle(byte opcode)
|
||||
{
|
||||
return opcode == 0x39;
|
||||
// Only handle opcode 0x39 when the operand size prefix is NOT present
|
||||
// This ensures 16-bit handlers get priority when the prefix is present
|
||||
return opcode == 0x39 && !Decoder.HasOperandSizePrefix();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -24,7 +24,9 @@ public class DecRegHandler : InstructionHandler
|
||||
public override bool CanHandle(byte opcode)
|
||||
{
|
||||
// DEC EAX = 0x48, DEC ECX = 0x49, ..., DEC EDI = 0x4F
|
||||
return opcode >= 0x48 && opcode <= 0x4F;
|
||||
// Only handle when the operand size prefix is NOT present
|
||||
// This ensures 16-bit handlers get priority when the prefix is present
|
||||
return opcode >= 0x48 && opcode <= 0x4F && !Decoder.HasOperandSizePrefix();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
77
X86Disassembler/X86/Handlers/Imul/ImulR32Rm32Handler.cs
Normal file
77
X86Disassembler/X86/Handlers/Imul/ImulR32Rm32Handler.cs
Normal file
@ -0,0 +1,77 @@
|
||||
using X86Disassembler.X86.Operands;
|
||||
|
||||
namespace X86Disassembler.X86.Handlers.Imul;
|
||||
|
||||
/// <summary>
|
||||
/// Handler for IMUL r32, r/m32 instruction (0x0F 0xAF /r)
|
||||
/// </summary>
|
||||
public class ImulR32Rm32Handler : InstructionHandler
|
||||
{
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the ImulR32Rm32Handler class
|
||||
/// </summary>
|
||||
/// <param name="decoder">The instruction decoder that owns this handler</param>
|
||||
public ImulR32Rm32Handler(InstructionDecoder decoder)
|
||||
: base(decoder)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Checks if this handler can decode the given opcode sequence
|
||||
/// </summary>
|
||||
/// <param name="opcode">The opcode to check</param>
|
||||
/// <returns>True if this handler can decode the opcode</returns>
|
||||
public override bool CanHandle(byte opcode)
|
||||
{
|
||||
// IMUL r32, r/m32: opcode 0F AF /r
|
||||
if (opcode != 0x0F)
|
||||
return false;
|
||||
|
||||
// Check if we can read the second byte
|
||||
if (!Decoder.CanReadByte())
|
||||
return false;
|
||||
|
||||
// Check if the second byte is 0xAF
|
||||
byte secondByte = Decoder.PeakByte();
|
||||
|
||||
// Only handle when the operand size prefix is NOT present
|
||||
// This ensures 16-bit handlers get priority when the prefix is present
|
||||
return secondByte == 0xAF && !Decoder.HasOperandSizePrefix();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Decodes an IMUL r32, r/m32 instruction
|
||||
/// </summary>
|
||||
/// <param name="opcode">The opcode of the instruction</param>
|
||||
/// <param name="instruction">The instruction object to populate</param>
|
||||
/// <returns>True if the instruction was successfully decoded</returns>
|
||||
public override bool Decode(byte opcode, Instruction instruction)
|
||||
{
|
||||
instruction.Type = InstructionType.IMul;
|
||||
|
||||
// Read the second byte of the opcode (0xAF)
|
||||
if (!Decoder.CanReadByte())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
byte secondByte = Decoder.ReadByte();
|
||||
if (secondByte != 0xAF)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// Read ModR/M: reg = destination, r/m = source
|
||||
var (_, reg, _, operand) = ModRMDecoder.ReadModRM();
|
||||
|
||||
// Create the destination register operand (32-bit)
|
||||
var destOperand = OperandFactory.CreateRegisterOperand(reg);
|
||||
|
||||
// Source operand is already an Operand
|
||||
instruction.StructuredOperands =
|
||||
[
|
||||
destOperand,
|
||||
operand
|
||||
];
|
||||
return true;
|
||||
}
|
||||
}
|
57
X86Disassembler/X86/Handlers/Imul/ImulR32Rm32Imm32Handler.cs
Normal file
57
X86Disassembler/X86/Handlers/Imul/ImulR32Rm32Imm32Handler.cs
Normal file
@ -0,0 +1,57 @@
|
||||
using X86Disassembler.X86.Operands;
|
||||
|
||||
namespace X86Disassembler.X86.Handlers.Imul;
|
||||
|
||||
/// <summary>
|
||||
/// Handler for IMUL r32, r/m32, imm32 instruction (0x69 /r id)
|
||||
/// </summary>
|
||||
public class ImulR32Rm32Imm32Handler : InstructionHandler
|
||||
{
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the ImulR32Rm32Imm32Handler class
|
||||
/// </summary>
|
||||
/// <param name="decoder">The instruction decoder that owns this handler</param>
|
||||
public ImulR32Rm32Imm32Handler(InstructionDecoder decoder)
|
||||
: base(decoder)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Checks if this handler can decode the given opcode
|
||||
/// </summary>
|
||||
/// <param name="opcode">The opcode to check</param>
|
||||
/// <returns>True if this handler can decode the opcode</returns>
|
||||
public override bool CanHandle(byte opcode)
|
||||
{
|
||||
// IMUL r32, r/m32, imm32: opcode 69 /r id
|
||||
return opcode == 0x69;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Decodes an IMUL r32, r/m32, imm32 instruction
|
||||
/// </summary>
|
||||
/// <param name="opcode">The opcode of the instruction</param>
|
||||
/// <param name="instruction">The instruction object to populate</param>
|
||||
/// <returns>True if the instruction was successfully decoded</returns>
|
||||
public override bool Decode(byte opcode, Instruction instruction)
|
||||
{
|
||||
instruction.Type = InstructionType.IMul;
|
||||
|
||||
// Read ModR/M: reg = destination, r/m = source
|
||||
var (_, reg, _, operand) = ModRMDecoder.ReadModRM();
|
||||
|
||||
var destOperand = OperandFactory.CreateRegisterOperand(reg);
|
||||
|
||||
// Read imm32 (4 bytes)
|
||||
uint imm32 = Decoder.ReadUInt32();
|
||||
var immOperand = OperandFactory.CreateImmediateOperand(imm32);
|
||||
|
||||
instruction.StructuredOperands =
|
||||
[
|
||||
destOperand,
|
||||
operand,
|
||||
immOperand
|
||||
];
|
||||
return true;
|
||||
}
|
||||
}
|
57
X86Disassembler/X86/Handlers/Imul/ImulR32Rm32Imm8Handler.cs
Normal file
57
X86Disassembler/X86/Handlers/Imul/ImulR32Rm32Imm8Handler.cs
Normal file
@ -0,0 +1,57 @@
|
||||
using X86Disassembler.X86.Operands;
|
||||
|
||||
namespace X86Disassembler.X86.Handlers.Imul;
|
||||
|
||||
/// <summary>
|
||||
/// Handler for IMUL r32, r/m32, imm8 instruction (0x6B /r ib)
|
||||
/// </summary>
|
||||
public class ImulR32Rm32Imm8Handler : InstructionHandler
|
||||
{
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the ImulR32Rm32Imm8Handler class
|
||||
/// </summary>
|
||||
/// <param name="decoder">The instruction decoder that owns this handler</param>
|
||||
public ImulR32Rm32Imm8Handler(InstructionDecoder decoder)
|
||||
: base(decoder)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Checks if this handler can decode the given opcode
|
||||
/// </summary>
|
||||
/// <param name="opcode">The opcode to check</param>
|
||||
/// <returns>True if this handler can decode the opcode</returns>
|
||||
public override bool CanHandle(byte opcode)
|
||||
{
|
||||
// IMUL r32, r/m32, imm8: opcode 6B /r ib
|
||||
return opcode == 0x6B;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Decodes an IMUL r32, r/m32, imm8 instruction
|
||||
/// </summary>
|
||||
/// <param name="opcode">The opcode of the instruction</param>
|
||||
/// <param name="instruction">The instruction object to populate</param>
|
||||
/// <returns>True if the instruction was successfully decoded</returns>
|
||||
public override bool Decode(byte opcode, Instruction instruction)
|
||||
{
|
||||
instruction.Type = InstructionType.IMul;
|
||||
|
||||
// Read ModR/M: reg = destination, r/m = source
|
||||
var (_, reg, _, operand) = ModRMDecoder.ReadModRM();
|
||||
|
||||
var destOperand = OperandFactory.CreateRegisterOperand(reg);
|
||||
|
||||
// Read imm8 and sign-extend to int32
|
||||
sbyte imm8 = (sbyte)Decoder.ReadByte();
|
||||
var immOperand = OperandFactory.CreateImmediateOperand((uint)imm8, 8); // 8-bit immediate, sign-extended
|
||||
|
||||
instruction.StructuredOperands =
|
||||
[
|
||||
destOperand,
|
||||
operand,
|
||||
immOperand
|
||||
];
|
||||
return true;
|
||||
}
|
||||
}
|
@ -24,7 +24,9 @@ public class IncRegHandler : InstructionHandler
|
||||
public override bool CanHandle(byte opcode)
|
||||
{
|
||||
// INC EAX = 0x40, INC ECX = 0x41, ..., INC EDI = 0x47
|
||||
return opcode >= 0x40 && opcode <= 0x47;
|
||||
// Only handle when the operand size prefix is NOT present
|
||||
// This ensures 16-bit handlers get priority when the prefix is present
|
||||
return opcode >= 0x40 && opcode <= 0x47 && !Decoder.HasOperandSizePrefix();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -1,6 +1,7 @@
|
||||
using X86Disassembler.X86.Handlers.Adc;
|
||||
using X86Disassembler.X86.Handlers.Add;
|
||||
using X86Disassembler.X86.Handlers.And;
|
||||
using X86Disassembler.X86.Handlers.Bit;
|
||||
using X86Disassembler.X86.Handlers.Call;
|
||||
using X86Disassembler.X86.Handlers.Cmp;
|
||||
using X86Disassembler.X86.Handlers.Dec;
|
||||
@ -63,7 +64,8 @@ public class InstructionHandlerFactory
|
||||
_handlers.Add(new Int3Handler(_decoder));
|
||||
|
||||
// Register handlers in order of priority (most specific first)
|
||||
RegisterArithmeticImmediateHandlers(); // Group 1 instructions (including 0x83)
|
||||
RegisterSbbHandlers(); // SBB instructions
|
||||
RegisterAdcHandlers(); // ADC instructions
|
||||
RegisterAddHandlers(); // ADD instructions
|
||||
RegisterAndHandlers(); // AND instructions
|
||||
RegisterOrHandlers(); // OR instructions
|
||||
@ -72,7 +74,6 @@ public class InstructionHandlerFactory
|
||||
RegisterTestHandlers(); // TEST instructions
|
||||
|
||||
// Register arithmetic unary instructions
|
||||
RegisterArithmeticUnaryHandlers(); // Empty, kept for consistency
|
||||
RegisterNotHandlers(); // NOT instructions
|
||||
RegisterNegHandlers(); // NEG instructions
|
||||
RegisterMulHandlers(); // MUL instructions
|
||||
@ -93,32 +94,44 @@ public class InstructionHandlerFactory
|
||||
RegisterMovHandlers();
|
||||
RegisterSubHandlers(); // Register SUB handlers
|
||||
RegisterNopHandlers(); // Register NOP handlers
|
||||
RegisterBitHandlers(); // Register bit manipulation handlers
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Registers all ArithmeticUnary instruction handlers
|
||||
/// Registers all SBB instruction handlers
|
||||
/// </summary>
|
||||
private void RegisterArithmeticUnaryHandlers()
|
||||
private void RegisterSbbHandlers()
|
||||
{
|
||||
// This method is kept for consistency, but all handlers have been moved to their own namespaces
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Registers all ArithmeticImmediate instruction handlers
|
||||
/// </summary>
|
||||
private void RegisterArithmeticImmediateHandlers()
|
||||
{
|
||||
// ADC handlers
|
||||
_handlers.Add(new AdcImmToRm32Handler(_decoder)); // ADC r/m32, imm32 (opcode 81 /2)
|
||||
_handlers.Add(new AdcImmToRm32SignExtendedHandler(_decoder)); // ADC r/m32, imm8 (opcode 83 /2)
|
||||
|
||||
// SBB handlers
|
||||
// SBB immediate handlers
|
||||
_handlers.Add(new SbbImmFromRm32Handler(_decoder)); // SBB r/m32, imm32 (opcode 81 /3)
|
||||
_handlers.Add(new SbbImmFromRm32SignExtendedHandler(_decoder)); // SBB r/m32, imm8 (opcode 83 /3)
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Registers all ADC instruction handlers
|
||||
/// </summary>
|
||||
private void RegisterAdcHandlers()
|
||||
{
|
||||
// ADC immediate handlers
|
||||
_handlers.Add(new AdcImmToRm8Handler(_decoder)); // ADC r/m8, imm8 (opcode 80 /2)
|
||||
_handlers.Add(new AdcImmToRm16Handler(_decoder)); // ADC r/m16, imm16 (opcode 81 /2 with 0x66 prefix)
|
||||
_handlers.Add(new AdcImmToRm16SignExtendedHandler(_decoder)); // ADC r/m16, imm8 (opcode 83 /2 with 0x66 prefix)
|
||||
_handlers.Add(new AdcImmToRm32Handler(_decoder)); // ADC r/m32, imm32 (opcode 81 /2)
|
||||
_handlers.Add(new AdcImmToRm32SignExtendedHandler(_decoder)); // ADC r/m32, imm8 (opcode 83 /2)
|
||||
_handlers.Add(new AdcAlImmHandler(_decoder)); // ADC AL, imm8 (opcode 14)
|
||||
_handlers.Add(new AdcAccumulatorImmHandler(_decoder)); // ADC AX/EAX, imm16/32 (opcode 15)
|
||||
|
||||
// SUB handlers
|
||||
_handlers.Add(new SubImmFromRm32Handler(_decoder)); // SUB r/m32, imm32 (opcode 81 /5)
|
||||
_handlers.Add(new SubImmFromRm32SignExtendedHandler(_decoder)); // SUB r/m32, imm8 (opcode 83 /5)
|
||||
// Register-to-register ADC handlers (8-bit)
|
||||
_handlers.Add(new AdcR8Rm8Handler(_decoder)); // ADC r8, r/m8 (opcode 12)
|
||||
_handlers.Add(new AdcRm8R8Handler(_decoder)); // ADC r/m8, r8 (opcode 10)
|
||||
|
||||
// Register-to-register ADC handlers (16-bit)
|
||||
_handlers.Add(new AdcR16Rm16Handler(_decoder)); // ADC r16, r/m16 (opcode 13 with 0x66 prefix)
|
||||
_handlers.Add(new AdcRm16R16Handler(_decoder)); // ADC r/m16, r16 (opcode 11 with 0x66 prefix)
|
||||
|
||||
// Register-to-register ADC handlers (32-bit)
|
||||
_handlers.Add(new AdcR32Rm32Handler(_decoder)); // ADC r32, r/m32 (opcode 13)
|
||||
_handlers.Add(new AdcRm32R32Handler(_decoder)); // ADC r/m32, r32 (opcode 11)
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@ -310,14 +323,6 @@ public class InstructionHandlerFactory
|
||||
_handlers.Add(new MovRm32Imm32Handler(_decoder));
|
||||
_handlers.Add(new MovRm8Imm8Handler(_decoder));
|
||||
|
||||
// Add PUSH handlers
|
||||
_handlers.Add(new PushRegHandler(_decoder));
|
||||
_handlers.Add(new PushImm32Handler(_decoder));
|
||||
_handlers.Add(new PushImm8Handler(_decoder));
|
||||
|
||||
// Add POP handlers
|
||||
_handlers.Add(new PopRegHandler(_decoder));
|
||||
|
||||
// Add XCHG handlers
|
||||
_handlers.Add(new XchgEaxRegHandler(_decoder));
|
||||
}
|
||||
@ -392,6 +397,7 @@ public class InstructionHandlerFactory
|
||||
{
|
||||
// Add POP register handlers
|
||||
_handlers.Add(new PopRegHandler(_decoder)); // POP r32 (opcode 58+r)
|
||||
_handlers.Add(new PopRm32Handler(_decoder)); // POP r/m32 (opcode 8F /0)
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@ -421,20 +427,20 @@ public class InstructionHandlerFactory
|
||||
private void RegisterSubHandlers()
|
||||
{
|
||||
// Register SUB handlers
|
||||
|
||||
|
||||
// 16-bit handlers with operand size prefix (must come first)
|
||||
_handlers.Add(new SubAxImm16Handler(_decoder));
|
||||
_handlers.Add(new SubImmFromRm16Handler(_decoder));
|
||||
_handlers.Add(new SubImmFromRm16SignExtendedHandler(_decoder));
|
||||
_handlers.Add(new SubRm16R16Handler(_decoder));
|
||||
_handlers.Add(new SubR16Rm16Handler(_decoder));
|
||||
|
||||
// 32-bit handlers
|
||||
_handlers.Add(new SubRm32R32Handler(_decoder));
|
||||
_handlers.Add(new SubR32Rm32Handler(_decoder));
|
||||
_handlers.Add(new SubImmFromRm32Handler(_decoder));
|
||||
_handlers.Add(new SubImmFromRm32SignExtendedHandler(_decoder));
|
||||
|
||||
// 16-bit handlers
|
||||
_handlers.Add(new SubRm16R16Handler(_decoder));
|
||||
_handlers.Add(new SubR16Rm16Handler(_decoder));
|
||||
_handlers.Add(new SubAxImm16Handler(_decoder));
|
||||
_handlers.Add(new SubImmFromRm16Handler(_decoder));
|
||||
_handlers.Add(new SubImmFromRm16SignExtendedHandler(_decoder));
|
||||
|
||||
// 8-bit handlers
|
||||
_handlers.Add(new SubRm8R8Handler(_decoder));
|
||||
_handlers.Add(new SubR8Rm8Handler(_decoder));
|
||||
@ -453,6 +459,32 @@ public class InstructionHandlerFactory
|
||||
_handlers.Add(new MultiByteNopHandler(_decoder));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Registers all bit manipulation instruction handlers
|
||||
/// </summary>
|
||||
private void RegisterBitHandlers()
|
||||
{
|
||||
// BT (Bit Test) handlers
|
||||
_handlers.Add(new BtR32Rm32Handler(_decoder)); // BT r32, r/m32 (0F A3)
|
||||
_handlers.Add(new BtRm32ImmHandler(_decoder)); // BT r/m32, imm8 (0F BA /4)
|
||||
|
||||
// BTS (Bit Test and Set) handlers
|
||||
_handlers.Add(new BtsR32Rm32Handler(_decoder)); // BTS r32, r/m32 (0F AB)
|
||||
_handlers.Add(new BtsRm32ImmHandler(_decoder)); // BTS r/m32, imm8 (0F BA /5)
|
||||
|
||||
// BTR (Bit Test and Reset) handlers
|
||||
_handlers.Add(new BtrR32Rm32Handler(_decoder)); // BTR r32, r/m32 (0F B3)
|
||||
_handlers.Add(new BtrRm32ImmHandler(_decoder)); // BTR r/m32, imm8 (0F BA /6)
|
||||
|
||||
// BTC (Bit Test and Complement) handlers
|
||||
_handlers.Add(new BtcR32Rm32Handler(_decoder)); // BTC r32, r/m32 (0F BB)
|
||||
_handlers.Add(new BtcRm32ImmHandler(_decoder)); // BTC r/m32, imm8 (0F BA /7)
|
||||
|
||||
// BSF and BSR (Bit Scan) handlers
|
||||
_handlers.Add(new BsfR32Rm32Handler(_decoder)); // BSF r32, r/m32 (0F BC)
|
||||
_handlers.Add(new BsrR32Rm32Handler(_decoder)); // BSR r32, r/m32 (0F BD)
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Registers all NEG instruction handlers
|
||||
/// </summary>
|
||||
|
@ -23,7 +23,9 @@ public class JmpRel32Handler : InstructionHandler
|
||||
/// <returns>True if this handler can decode the opcode</returns>
|
||||
public override bool CanHandle(byte opcode)
|
||||
{
|
||||
return opcode == 0xE9;
|
||||
// Only handle opcode 0xE9 when the operand size prefix is NOT present
|
||||
// This ensures 16-bit handlers get priority when the prefix is present
|
||||
return opcode == 0xE9 && !Decoder.HasOperandSizePrefix();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -39,7 +39,9 @@ public class JmpRm32Handler : InstructionHandler
|
||||
var reg = ModRMDecoder.PeakModRMReg();
|
||||
|
||||
// JMP r/m32 is encoded as FF /4 (reg field = 4)
|
||||
return reg == 4;
|
||||
// Only handle when the operand size prefix is NOT present
|
||||
// This ensures 16-bit handlers get priority when the prefix is present
|
||||
return reg == 4 && !Decoder.HasOperandSizePrefix();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -23,7 +23,9 @@ public class LeaR32MHandler : InstructionHandler
|
||||
/// <returns>True if this handler can decode the opcode</returns>
|
||||
public override bool CanHandle(byte opcode)
|
||||
{
|
||||
return opcode == 0x8D;
|
||||
// Only handle opcode 0x8D when the operand size prefix is NOT present
|
||||
// This ensures 16-bit handlers get priority when the prefix is present
|
||||
return opcode == 0x8D && !Decoder.HasOperandSizePrefix();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -23,7 +23,13 @@ public class MovMemRegHandler : InstructionHandler
|
||||
/// <returns>True if this handler can decode the opcode</returns>
|
||||
public override bool CanHandle(byte opcode)
|
||||
{
|
||||
return opcode == 0x88 || opcode == 0x89;
|
||||
// For 8-bit operations (0x88), no prefix check needed
|
||||
if (opcode == 0x88)
|
||||
return true;
|
||||
|
||||
// For 32-bit operations (0x89), only handle when operand size prefix is NOT present
|
||||
// This ensures 16-bit handlers get priority when the prefix is present
|
||||
return opcode == 0x89 && !Decoder.HasOperandSizePrefix();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -23,7 +23,13 @@ public class MovRegMemHandler : InstructionHandler
|
||||
/// <returns>True if this handler can decode the opcode</returns>
|
||||
public override bool CanHandle(byte opcode)
|
||||
{
|
||||
return opcode == 0x8A || opcode == 0x8B;
|
||||
// For 8-bit operations (0x8A), no prefix check needed
|
||||
if (opcode == 0x8A)
|
||||
return true;
|
||||
|
||||
// For 32-bit operations (0x8B), only handle when operand size prefix is NOT present
|
||||
// This ensures 16-bit handlers get priority when the prefix is present
|
||||
return opcode == 0x8B && !Decoder.HasOperandSizePrefix();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -34,7 +34,7 @@ public class MovRm32Imm32Handler : InstructionHandler
|
||||
return false;
|
||||
}
|
||||
|
||||
// Peek at the ModR/M byte without advancing the position
|
||||
// Peak at the ModR/M byte without advancing the position
|
||||
var reg = ModRMDecoder.PeakModRMReg();
|
||||
|
||||
// MOV r/m8, imm8 only uses reg=0
|
||||
|
@ -35,7 +35,7 @@ public class MovRm8Imm8Handler : InstructionHandler
|
||||
return false;
|
||||
}
|
||||
|
||||
// Peek at the ModR/M byte without advancing the position
|
||||
// Peak at the ModR/M byte without advancing the position
|
||||
var reg = ModRMDecoder.PeakModRMReg();
|
||||
|
||||
// MOV r/m8, imm8 only uses reg=0
|
||||
|
@ -32,7 +32,9 @@ public class NegRm32Handler : InstructionHandler
|
||||
|
||||
var reg = ModRMDecoder.PeakModRMReg();
|
||||
|
||||
return reg == 3; // 3 = NEG
|
||||
// Only handle when the operand size prefix is NOT present
|
||||
// This ensures 16-bit handlers get priority when the prefix is present
|
||||
return reg == 3 && !Decoder.HasOperandSizePrefix(); // 3 = NEG
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -33,7 +33,9 @@ public class NotRm32Handler : InstructionHandler
|
||||
|
||||
var reg = ModRMDecoder.PeakModRMReg();
|
||||
|
||||
return reg == 2; // 2 = NOT
|
||||
// Only handle when the operand size prefix is NOT present
|
||||
// This ensures 16-bit handlers get priority when the prefix is present
|
||||
return reg == 2 && !Decoder.HasOperandSizePrefix(); // 2 = NOT
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@ -55,7 +57,7 @@ public class NotRm32Handler : InstructionHandler
|
||||
// Read the ModR/M byte
|
||||
// For NOT r/m32 (0xF7 /2):
|
||||
// - The r/m field with mod specifies the operand (register or memory)
|
||||
var (_, reg, _, operand) = ModRMDecoder.ReadModRM();
|
||||
var (_, _, _, operand) = ModRMDecoder.ReadModRM();
|
||||
|
||||
// Set the structured operands
|
||||
// NOT has only one operand
|
||||
|
@ -55,7 +55,7 @@ public class NotRm8Handler : InstructionHandler
|
||||
// Read the ModR/M byte
|
||||
// For NOT r/m8 (0xF6 /2):
|
||||
// - The r/m field with mod specifies the operand (register or memory)
|
||||
var (_, reg, _, operand) = ModRMDecoder.ReadModRM8();
|
||||
var (_, _, _, operand) = ModRMDecoder.ReadModRM8();
|
||||
|
||||
// Set the structured operands
|
||||
// NOT has only one operand
|
||||
|
@ -23,7 +23,9 @@ public class OrR32Rm32Handler : InstructionHandler
|
||||
/// <returns>True if this handler can decode the opcode</returns>
|
||||
public override bool CanHandle(byte opcode)
|
||||
{
|
||||
return opcode == 0x0B;
|
||||
// Only handle opcode 0x0B when the operand size prefix is NOT present
|
||||
// This ensures 16-bit handlers get priority when the prefix is present
|
||||
return opcode == 0x0B && !Decoder.HasOperandSizePrefix();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -23,7 +23,9 @@ public class OrRm32R32Handler : InstructionHandler
|
||||
/// <returns>True if this handler can decode the opcode</returns>
|
||||
public override bool CanHandle(byte opcode)
|
||||
{
|
||||
return opcode == 0x09;
|
||||
// Only handle opcode 0x09 when the operand size prefix is NOT present
|
||||
// This ensures 16-bit handlers get priority when the prefix is present
|
||||
return opcode == 0x09 && !Decoder.HasOperandSizePrefix();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -23,7 +23,9 @@ public class PopRegHandler : InstructionHandler
|
||||
/// <returns>True if this handler can decode the opcode</returns>
|
||||
public override bool CanHandle(byte opcode)
|
||||
{
|
||||
return opcode >= 0x58 && opcode <= 0x5F;
|
||||
// Only handle opcodes 0x58-0x5F when the operand size prefix is NOT present
|
||||
// This ensures 16-bit handlers get priority when the prefix is present
|
||||
return opcode >= 0x58 && opcode <= 0x5F && !Decoder.HasOperandSizePrefix();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
77
X86Disassembler/X86/Handlers/Pop/PopRm32Handler.cs
Normal file
77
X86Disassembler/X86/Handlers/Pop/PopRm32Handler.cs
Normal file
@ -0,0 +1,77 @@
|
||||
using X86Disassembler.X86.Operands;
|
||||
|
||||
namespace X86Disassembler.X86.Handlers.Pop;
|
||||
|
||||
/// <summary>
|
||||
/// Handler for POP r/m32 instruction (0x8F /0)
|
||||
/// </summary>
|
||||
public class PopRm32Handler : InstructionHandler
|
||||
{
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the PopRm32Handler class
|
||||
/// </summary>
|
||||
/// <param name="decoder">The instruction decoder that owns this handler</param>
|
||||
public PopRm32Handler(InstructionDecoder decoder)
|
||||
: base(decoder)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Checks if this handler can decode the given opcode
|
||||
/// </summary>
|
||||
/// <param name="opcode">The opcode to check</param>
|
||||
/// <returns>True if this handler can decode the opcode</returns>
|
||||
public override bool CanHandle(byte opcode)
|
||||
{
|
||||
// POP r/m32 is encoded as 8F /0
|
||||
if (opcode != 0x8F)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// Check if we have enough bytes to read the ModR/M byte
|
||||
if (!Decoder.CanReadByte())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
var reg = ModRMDecoder.PeakModRMReg();
|
||||
|
||||
// POP r/m32 is encoded as 8F /0 (reg field = 0)
|
||||
// Only handle when the operand size prefix is NOT present
|
||||
// This ensures 16-bit handlers get priority when the prefix is present
|
||||
return reg == 0 && !Decoder.HasOperandSizePrefix();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Decodes a POP r/m32 instruction
|
||||
/// </summary>
|
||||
/// <param name="opcode">The opcode of the instruction</param>
|
||||
/// <param name="instruction">The instruction object to populate</param>
|
||||
/// <returns>True if the instruction was successfully decoded</returns>
|
||||
public override bool Decode(byte opcode, Instruction instruction)
|
||||
{
|
||||
// Set the instruction type
|
||||
instruction.Type = InstructionType.Pop;
|
||||
|
||||
// Check if we have enough bytes for the ModR/M byte
|
||||
if (!Decoder.CanReadByte())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// Read the ModR/M byte
|
||||
// For POP r/m32 (8F /0):
|
||||
// - The r/m field with mod specifies the operand (register or memory)
|
||||
var (_, _, _, operand) = ModRMDecoder.ReadModRM();
|
||||
|
||||
// Set the structured operands
|
||||
// POP has only one operand
|
||||
instruction.StructuredOperands =
|
||||
[
|
||||
operand
|
||||
];
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
@ -38,7 +38,9 @@ public class PushRm32Handler : InstructionHandler
|
||||
var reg = ModRMDecoder.PeakModRMReg();
|
||||
|
||||
// PUSH r/m32 is encoded as FF /6 (reg field = 6)
|
||||
return reg == 6;
|
||||
// Only handle when the operand size prefix is NOT present
|
||||
// This ensures 16-bit handlers get priority when the prefix is present
|
||||
return reg == 6 && !Decoder.HasOperandSizePrefix();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -23,7 +23,9 @@ public class RetHandler : InstructionHandler
|
||||
/// <returns>True if this handler can decode the opcode</returns>
|
||||
public override bool CanHandle(byte opcode)
|
||||
{
|
||||
return opcode == 0xC3;
|
||||
// Only handle opcode 0xC3 when the operand size prefix is NOT present
|
||||
// This ensures 16-bit handlers get priority when the prefix is present
|
||||
return opcode == 0xC3 && !Decoder.HasOperandSizePrefix();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -23,7 +23,9 @@ public class RetImmHandler : InstructionHandler
|
||||
/// <returns>True if this handler can decode the opcode</returns>
|
||||
public override bool CanHandle(byte opcode)
|
||||
{
|
||||
return opcode == 0xC2;
|
||||
// Only handle opcode 0xC2 when the operand size prefix is NOT present
|
||||
// This ensures 16-bit handlers get priority when the prefix is present
|
||||
return opcode == 0xC2 && !Decoder.HasOperandSizePrefix();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -46,7 +46,7 @@ public class SubAlImm8Handler : InstructionHandler
|
||||
instruction.Type = InstructionType.Sub;
|
||||
|
||||
// Create the destination register operand (AL)
|
||||
var destinationOperand = OperandFactory.CreateRegisterOperand(RegisterIndex.A, 8);
|
||||
var destinationOperand = OperandFactory.CreateRegisterOperand8(RegisterIndex8.AL);
|
||||
|
||||
// Create the source immediate operand
|
||||
var sourceOperand = OperandFactory.CreateImmediateOperand(imm8, 8);
|
||||
|
@ -23,7 +23,9 @@ public class SubR32Rm32Handler : InstructionHandler
|
||||
/// <returns>True if this handler can decode the opcode</returns>
|
||||
public override bool CanHandle(byte opcode)
|
||||
{
|
||||
return opcode == 0x2B;
|
||||
// Only handle opcode 0x2B when the operand size prefix is NOT present
|
||||
// This ensures 16-bit handlers get priority when the prefix is present
|
||||
return opcode == 0x2B && !Decoder.HasOperandSizePrefix();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -23,7 +23,9 @@ public class SubRm32R32Handler : InstructionHandler
|
||||
/// <returns>True if this handler can decode the opcode</returns>
|
||||
public override bool CanHandle(byte opcode)
|
||||
{
|
||||
return opcode == 0x29;
|
||||
// Only handle opcode 0x29 when the operand size prefix is NOT present
|
||||
// This ensures 16-bit handlers get priority when the prefix is present
|
||||
return opcode == 0x29 && !Decoder.HasOperandSizePrefix();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -23,7 +23,9 @@ public class TestRegMemHandler : InstructionHandler
|
||||
/// <returns>True if this handler can decode the opcode</returns>
|
||||
public override bool CanHandle(byte opcode)
|
||||
{
|
||||
return opcode == 0x85;
|
||||
// Only handle opcode 0x85 when the operand size prefix is NOT present
|
||||
// This ensures 16-bit handlers get priority when the prefix is present
|
||||
return opcode == 0x85 && !Decoder.HasOperandSizePrefix();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -23,40 +23,9 @@ public class XchgEaxRegHandler : InstructionHandler
|
||||
/// <returns>True if this handler can decode the opcode</returns>
|
||||
public override bool CanHandle(byte opcode)
|
||||
{
|
||||
return opcode >= 0x91 && opcode <= 0x97;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Maps the register index from the opcode to the RegisterIndex enum value expected by tests
|
||||
/// </summary>
|
||||
/// <param name="opcodeRegIndex">The register index from the opcode (0-7)</param>
|
||||
/// <returns>The corresponding RegisterIndex enum value</returns>
|
||||
private RegisterIndex MapOpcodeToRegisterIndex(int opcodeRegIndex)
|
||||
{
|
||||
// The mapping from opcode register index to RegisterIndex enum is:
|
||||
// 0 -> A (EAX)
|
||||
// 1 -> C (ECX)
|
||||
// 2 -> D (EDX)
|
||||
// 3 -> B (EBX)
|
||||
// 4 -> Sp (ESP)
|
||||
// 5 -> Bp (EBP)
|
||||
// 6 -> Si (ESI)
|
||||
// 7 -> Di (EDI)
|
||||
|
||||
// This mapping is based on the x86 instruction encoding
|
||||
// but we need to map to the RegisterIndex enum values that the tests expect
|
||||
return opcodeRegIndex switch
|
||||
{
|
||||
0 => RegisterIndex.A, // EAX
|
||||
1 => RegisterIndex.C, // ECX
|
||||
2 => RegisterIndex.D, // EDX
|
||||
3 => RegisterIndex.B, // EBX
|
||||
4 => RegisterIndex.Sp, // ESP
|
||||
5 => RegisterIndex.Bp, // EBP
|
||||
6 => RegisterIndex.Si, // ESI
|
||||
7 => RegisterIndex.Di, // EDI
|
||||
_ => RegisterIndex.A // Default case, should never happen
|
||||
};
|
||||
// Only handle opcodes 0x91-0x97 when the operand size prefix is NOT present
|
||||
// This ensures 16-bit handlers get priority when the prefix is present
|
||||
return opcode >= 0x91 && opcode <= 0x97 && !Decoder.HasOperandSizePrefix();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@ -71,10 +40,7 @@ public class XchgEaxRegHandler : InstructionHandler
|
||||
instruction.Type = InstructionType.Xchg;
|
||||
|
||||
// Register is encoded in the low 3 bits of the opcode
|
||||
int opcodeRegIndex = opcode & 0x07;
|
||||
|
||||
// Map the opcode register index to the RegisterIndex enum value
|
||||
RegisterIndex reg = MapOpcodeToRegisterIndex(opcodeRegIndex);
|
||||
RegisterIndex reg = (RegisterIndex)(opcode & 0x07);
|
||||
|
||||
// Create the register operands
|
||||
var eaxOperand = OperandFactory.CreateRegisterOperand(RegisterIndex.A);
|
||||
|
@ -46,7 +46,7 @@ public class XorAlImmHandler : InstructionHandler
|
||||
byte imm8 = Decoder.ReadByte();
|
||||
|
||||
// Create the register operand for AL
|
||||
var alOperand = OperandFactory.CreateRegisterOperand(RegisterIndex.A, 8);
|
||||
var alOperand = OperandFactory.CreateRegisterOperand8(RegisterIndex8.AL);
|
||||
|
||||
// Create the immediate operand
|
||||
var immOperand = OperandFactory.CreateImmediateOperand(imm8, 8);
|
||||
|
@ -23,7 +23,9 @@ public class XorMemRegHandler : InstructionHandler
|
||||
/// <returns>True if this handler can decode the opcode</returns>
|
||||
public override bool CanHandle(byte opcode)
|
||||
{
|
||||
return opcode == 0x31;
|
||||
// Only handle opcode 0x31 when the operand size prefix is NOT present
|
||||
// This ensures 16-bit handlers get priority when the prefix is present
|
||||
return opcode == 0x31 && !Decoder.HasOperandSizePrefix();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -25,7 +25,9 @@ public class XorRegMemHandler : InstructionHandler
|
||||
/// <returns>True if this handler can decode the opcode</returns>
|
||||
public override bool CanHandle(byte opcode)
|
||||
{
|
||||
return opcode == 0x33;
|
||||
// Only handle opcode 0x33 when the operand size prefix is NOT present
|
||||
// This ensures 16-bit handlers get priority when the prefix is present
|
||||
return opcode == 0x33 && !Decoder.HasOperandSizePrefix();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -1,4 +1,3 @@
|
||||
using System.Diagnostics;
|
||||
using System.Diagnostics.Contracts;
|
||||
|
||||
namespace X86Disassembler.X86;
|
||||
@ -6,6 +5,11 @@ namespace X86Disassembler.X86;
|
||||
using Handlers;
|
||||
using Operands;
|
||||
|
||||
public static class Printer
|
||||
{
|
||||
public static Action<string>? WriteLine;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Decodes x86 instructions from a byte buffer
|
||||
/// </summary>
|
||||
@ -83,44 +87,19 @@ public class InstructionDecoder
|
||||
}
|
||||
}
|
||||
|
||||
// If only prefixes were found, return a prefix-only instruction
|
||||
// If only prefixes were found and we're at the end of the buffer, return null
|
||||
if (_position > startPosition && !CanReadByte())
|
||||
{
|
||||
// Check for segment override prefix
|
||||
if (_prefixDecoder.HasSegmentOverridePrefix())
|
||||
{
|
||||
// Set the instruction type to Rep for segment override prefixes when they appear alone
|
||||
// This matches the expected behavior in the tests
|
||||
instruction.Type = InstructionType.Rep;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Set the instruction type to Unknown for other prefixes
|
||||
instruction.Type = InstructionType.Unknown;
|
||||
}
|
||||
|
||||
// Add segment override prefix as an operand if present
|
||||
string segmentOverride = _prefixDecoder.GetSegmentOverride();
|
||||
if (!string.IsNullOrEmpty(segmentOverride))
|
||||
{
|
||||
// Could create a special operand for segment overrides if needed
|
||||
}
|
||||
|
||||
return instruction;
|
||||
}
|
||||
|
||||
if (!CanReadByte())
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
// Read the opcode
|
||||
byte opcode = ReadByte();
|
||||
|
||||
// Get a handler for the opcode
|
||||
var handler = _handlerFactory.GetHandler(opcode);
|
||||
|
||||
Debug.WriteLine($"Resolved handler {handler?.GetType().Name}");
|
||||
Printer.WriteLine?.Invoke($"Resolved handler {handler?.GetType().Name}");
|
||||
|
||||
bool handlerSuccess = false;
|
||||
|
||||
@ -326,6 +305,20 @@ public class InstructionDecoder
|
||||
return _codeBuffer[_position];
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Peaks a byte from the buffer without adjusting position
|
||||
/// </summary>
|
||||
/// <returns>The byte peaked</returns>
|
||||
public (byte b1, byte b2) PeakTwoBytes()
|
||||
{
|
||||
if (_position + 1 >= _length)
|
||||
{
|
||||
return (0,0);
|
||||
}
|
||||
|
||||
return (_codeBuffer[_position], _codeBuffer[_position + 1]);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Peaks a byte from the buffer at the specified offset from current position without adjusting position
|
||||
/// </summary>
|
||||
|
@ -185,6 +185,18 @@ public class ModRMDecoder
|
||||
return regIndex;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Extracts modRM reg field
|
||||
/// </summary>
|
||||
/// <returns>A reg from the ModR/M byte</returns>
|
||||
public static byte GetRegFromModRM(byte modRm)
|
||||
{
|
||||
// Extract fields from ModR/M byte
|
||||
byte regIndex = (byte)((modRm & Constants.REG_MASK) >> 3); // Middle 3 bits (bits 3-5)
|
||||
|
||||
return regIndex;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Reads and decodes a ModR/M byte for standard 32-bit operands
|
||||
/// </summary>
|
||||
|
@ -39,26 +39,28 @@ public class DisplacementMemoryOperand : MemoryOperand
|
||||
var registerName = RegisterMapper.GetRegisterName(BaseRegister, 32);
|
||||
|
||||
// Format the displacement value
|
||||
string formattedDisplacement;
|
||||
string sign;
|
||||
|
||||
// Handle positive and negative displacements
|
||||
if (Displacement >= 0)
|
||||
long absDisplacement = Math.Abs(Displacement);
|
||||
string sign = Displacement >= 0 ? "+" : "-";
|
||||
string format;
|
||||
|
||||
if (absDisplacement == 0)
|
||||
{
|
||||
sign = "+";
|
||||
formattedDisplacement = Displacement < 256
|
||||
? $"0x{Displacement:X2}"
|
||||
: $"0x{Displacement:X8}";
|
||||
format = "X2";
|
||||
}
|
||||
else if (absDisplacement <= 0xFF)
|
||||
{
|
||||
format = "X2";
|
||||
}
|
||||
else if (absDisplacement <= 0xFFFF)
|
||||
{
|
||||
format = "X4";
|
||||
}
|
||||
else
|
||||
{
|
||||
sign = "-";
|
||||
// For negative values, take the absolute value for display
|
||||
var absDisplacement = Math.Abs(Displacement);
|
||||
formattedDisplacement = absDisplacement < 256
|
||||
? $"0x{absDisplacement:X2}"
|
||||
: $"0x{absDisplacement:X8}";
|
||||
format = "X8";
|
||||
}
|
||||
|
||||
string formattedDisplacement = $"0x{absDisplacement.ToString(format)}";
|
||||
|
||||
return $"{GetSizePrefix()}[{registerName}{sign}{formattedDisplacement}]";
|
||||
}
|
||||
|
@ -46,42 +46,25 @@ public class ImmediateOperand : Operand
|
||||
_ => Value
|
||||
};
|
||||
|
||||
// For 8-bit immediate values, always use at least 2 digits
|
||||
if (Size == 8)
|
||||
string format;
|
||||
|
||||
if (maskedValue == 0)
|
||||
{
|
||||
return $"0x{maskedValue:X2}";
|
||||
format = "X2";
|
||||
}
|
||||
|
||||
// For 16-bit immediate values, format depends on the value
|
||||
if (Size == 16)
|
||||
else if (maskedValue <= 0xFF)
|
||||
{
|
||||
// For small values (< 256), show without leading zeros
|
||||
if (maskedValue < 256)
|
||||
{
|
||||
return $"0x{maskedValue:X}";
|
||||
}
|
||||
|
||||
// For larger values, use at least 4 digits
|
||||
return $"0x{maskedValue:X4}";
|
||||
format = "X2";
|
||||
}
|
||||
|
||||
// For 32-bit immediate values, format depends on the instruction context
|
||||
if (Size == 32)
|
||||
else if (maskedValue <= 0xFFFF)
|
||||
{
|
||||
// For small values (0), always show as 0x00
|
||||
if (maskedValue == 0)
|
||||
{
|
||||
return "0x00";
|
||||
}
|
||||
|
||||
// For other small values (< 256), show as 0xNN
|
||||
if (maskedValue < 256)
|
||||
{
|
||||
return $"0x{maskedValue:X2}";
|
||||
}
|
||||
format = "X4";
|
||||
}
|
||||
|
||||
// For larger 32-bit values, show the full 32-bit representation
|
||||
return $"0x{maskedValue:X8}";
|
||||
else
|
||||
{
|
||||
format = "X8";
|
||||
}
|
||||
|
||||
return $"0x{maskedValue.ToString(format)}";
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user