0
mirror of https://github.com/sampletext32/ParkanPlayground.git synced 2025-05-19 11:51:17 +03:00

Unified ADC accumulator handlers into a single handler

This commit is contained in:
bird_egop 2025-04-17 01:33:58 +03:00
parent 8c9b34ef09
commit 3fc0ebf1d5
79 changed files with 2564 additions and 473 deletions

View File

@ -85,13 +85,16 @@ public class Disassembler
break; 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(); Instruction? instruction = decoder.DecodeInstruction();
if (instruction != null) if (instruction != null)
{ {
// Adjust the instruction address to include the base address // Adjust the instruction address to include the base address
instruction.Address += _baseAddress; instruction.Address = _baseAddress + (uint)startPosition;
// Add the instruction to the list // Add the instruction to the list
instructions.Add(instruction); instructions.Add(instruction);
@ -103,7 +106,7 @@ public class Disassembler
Instruction dummyInstruction = new Instruction Instruction dummyInstruction = new Instruction
{ {
Address = _baseAddress + (uint) position, Address = _baseAddress + (uint)position,
Type = InstructionType.Unknown, Type = InstructionType.Unknown,
StructuredOperands = [OperandFactory.CreateImmediateOperand(unknownByte, 8),] StructuredOperands = [OperandFactory.CreateImmediateOperand(unknownByte, 8),]
}; };

View 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;
}
}

View 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;
}
}

View 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;
}
}

View File

@ -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;
}
}

View 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;
}
}

View 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;
}
}

View 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;
}
}

View 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;
}
}

View 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;
}
}

View 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;
}
}

View 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;
}
}

View File

@ -23,7 +23,9 @@ public class AddR32Rm32Handler : InstructionHandler
/// <returns>True if this handler can decode the opcode</returns> /// <returns>True if this handler can decode the opcode</returns>
public override bool CanHandle(byte opcode) 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> /// <summary>

View File

@ -23,7 +23,9 @@ public class AddRm32R32Handler : InstructionHandler
/// <returns>True if this handler can decode the opcode</returns> /// <returns>True if this handler can decode the opcode</returns>
public override bool CanHandle(byte opcode) 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> /// <summary>

View File

@ -23,7 +23,9 @@ public class AndMemRegHandler : InstructionHandler
/// <returns>True if this handler can decode the opcode</returns> /// <returns>True if this handler can decode the opcode</returns>
public override bool CanHandle(byte opcode) 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> /// <summary>

View File

@ -23,7 +23,9 @@ public class AndR32Rm32Handler : InstructionHandler
/// <returns>True if this handler can decode the opcode</returns> /// <returns>True if this handler can decode the opcode</returns>
public override bool CanHandle(byte opcode) 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> /// <summary>

View 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;
}
}

View 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;
}
}

View 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;
}
}

View 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;
}
}

View 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;
}
}

View 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;
}
}

View 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;
}
}

View 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;
}
}

View 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;
}
}

View 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;
}
}

View 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;
}
}

View File

@ -39,7 +39,9 @@ public class CallRm32Handler : InstructionHandler
var reg = ModRMDecoder.PeakModRMReg(); var reg = ModRMDecoder.PeakModRMReg();
// CALL r/m32 is encoded as FF /2 (reg field = 2) // 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> /// <summary>

View File

@ -23,7 +23,9 @@ public class CmpR32Rm32Handler : InstructionHandler
/// <returns>True if this handler can decode the opcode</returns> /// <returns>True if this handler can decode the opcode</returns>
public override bool CanHandle(byte opcode) 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> /// <summary>

View File

@ -23,7 +23,9 @@ public class CmpRm32R32Handler : InstructionHandler
/// <returns>True if this handler can decode the opcode</returns> /// <returns>True if this handler can decode the opcode</returns>
public override bool CanHandle(byte opcode) 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> /// <summary>

View File

@ -24,7 +24,9 @@ public class DecRegHandler : InstructionHandler
public override bool CanHandle(byte opcode) public override bool CanHandle(byte opcode)
{ {
// DEC EAX = 0x48, DEC ECX = 0x49, ..., DEC EDI = 0x4F // 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> /// <summary>

View 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;
}
}

View 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;
}
}

View 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;
}
}

View File

@ -24,7 +24,9 @@ public class IncRegHandler : InstructionHandler
public override bool CanHandle(byte opcode) public override bool CanHandle(byte opcode)
{ {
// INC EAX = 0x40, INC ECX = 0x41, ..., INC EDI = 0x47 // 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> /// <summary>

View File

@ -1,6 +1,7 @@
using X86Disassembler.X86.Handlers.Adc; using X86Disassembler.X86.Handlers.Adc;
using X86Disassembler.X86.Handlers.Add; using X86Disassembler.X86.Handlers.Add;
using X86Disassembler.X86.Handlers.And; using X86Disassembler.X86.Handlers.And;
using X86Disassembler.X86.Handlers.Bit;
using X86Disassembler.X86.Handlers.Call; using X86Disassembler.X86.Handlers.Call;
using X86Disassembler.X86.Handlers.Cmp; using X86Disassembler.X86.Handlers.Cmp;
using X86Disassembler.X86.Handlers.Dec; using X86Disassembler.X86.Handlers.Dec;
@ -63,7 +64,8 @@ public class InstructionHandlerFactory
_handlers.Add(new Int3Handler(_decoder)); _handlers.Add(new Int3Handler(_decoder));
// Register handlers in order of priority (most specific first) // Register handlers in order of priority (most specific first)
RegisterArithmeticImmediateHandlers(); // Group 1 instructions (including 0x83) RegisterSbbHandlers(); // SBB instructions
RegisterAdcHandlers(); // ADC instructions
RegisterAddHandlers(); // ADD instructions RegisterAddHandlers(); // ADD instructions
RegisterAndHandlers(); // AND instructions RegisterAndHandlers(); // AND instructions
RegisterOrHandlers(); // OR instructions RegisterOrHandlers(); // OR instructions
@ -72,7 +74,6 @@ public class InstructionHandlerFactory
RegisterTestHandlers(); // TEST instructions RegisterTestHandlers(); // TEST instructions
// Register arithmetic unary instructions // Register arithmetic unary instructions
RegisterArithmeticUnaryHandlers(); // Empty, kept for consistency
RegisterNotHandlers(); // NOT instructions RegisterNotHandlers(); // NOT instructions
RegisterNegHandlers(); // NEG instructions RegisterNegHandlers(); // NEG instructions
RegisterMulHandlers(); // MUL instructions RegisterMulHandlers(); // MUL instructions
@ -93,32 +94,44 @@ public class InstructionHandlerFactory
RegisterMovHandlers(); RegisterMovHandlers();
RegisterSubHandlers(); // Register SUB handlers RegisterSubHandlers(); // Register SUB handlers
RegisterNopHandlers(); // Register NOP handlers RegisterNopHandlers(); // Register NOP handlers
RegisterBitHandlers(); // Register bit manipulation handlers
} }
/// <summary> /// <summary>
/// Registers all ArithmeticUnary instruction handlers /// Registers all SBB instruction handlers
/// </summary> /// </summary>
private void RegisterArithmeticUnaryHandlers() private void RegisterSbbHandlers()
{ {
// This method is kept for consistency, but all handlers have been moved to their own namespaces // SBB immediate handlers
}
/// <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
_handlers.Add(new SbbImmFromRm32Handler(_decoder)); // SBB r/m32, imm32 (opcode 81 /3) _handlers.Add(new SbbImmFromRm32Handler(_decoder)); // SBB r/m32, imm32 (opcode 81 /3)
_handlers.Add(new SbbImmFromRm32SignExtendedHandler(_decoder)); // SBB r/m32, imm8 (opcode 83 /3) _handlers.Add(new SbbImmFromRm32SignExtendedHandler(_decoder)); // SBB r/m32, imm8 (opcode 83 /3)
}
// SUB handlers /// <summary>
_handlers.Add(new SubImmFromRm32Handler(_decoder)); // SUB r/m32, imm32 (opcode 81 /5) /// Registers all ADC instruction handlers
_handlers.Add(new SubImmFromRm32SignExtendedHandler(_decoder)); // SUB r/m32, imm8 (opcode 83 /5) /// </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)
// 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> /// <summary>
@ -310,14 +323,6 @@ public class InstructionHandlerFactory
_handlers.Add(new MovRm32Imm32Handler(_decoder)); _handlers.Add(new MovRm32Imm32Handler(_decoder));
_handlers.Add(new MovRm8Imm8Handler(_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 // Add XCHG handlers
_handlers.Add(new XchgEaxRegHandler(_decoder)); _handlers.Add(new XchgEaxRegHandler(_decoder));
} }
@ -392,6 +397,7 @@ public class InstructionHandlerFactory
{ {
// Add POP register handlers // Add POP register handlers
_handlers.Add(new PopRegHandler(_decoder)); // POP r32 (opcode 58+r) _handlers.Add(new PopRegHandler(_decoder)); // POP r32 (opcode 58+r)
_handlers.Add(new PopRm32Handler(_decoder)); // POP r/m32 (opcode 8F /0)
} }
/// <summary> /// <summary>
@ -422,19 +428,19 @@ public class InstructionHandlerFactory
{ {
// Register SUB handlers // 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 // 32-bit handlers
_handlers.Add(new SubRm32R32Handler(_decoder)); _handlers.Add(new SubRm32R32Handler(_decoder));
_handlers.Add(new SubR32Rm32Handler(_decoder)); _handlers.Add(new SubR32Rm32Handler(_decoder));
_handlers.Add(new SubImmFromRm32Handler(_decoder)); _handlers.Add(new SubImmFromRm32Handler(_decoder));
_handlers.Add(new SubImmFromRm32SignExtendedHandler(_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 // 8-bit handlers
_handlers.Add(new SubRm8R8Handler(_decoder)); _handlers.Add(new SubRm8R8Handler(_decoder));
_handlers.Add(new SubR8Rm8Handler(_decoder)); _handlers.Add(new SubR8Rm8Handler(_decoder));
@ -453,6 +459,32 @@ public class InstructionHandlerFactory
_handlers.Add(new MultiByteNopHandler(_decoder)); _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> /// <summary>
/// Registers all NEG instruction handlers /// Registers all NEG instruction handlers
/// </summary> /// </summary>

View File

@ -23,7 +23,9 @@ public class JmpRel32Handler : InstructionHandler
/// <returns>True if this handler can decode the opcode</returns> /// <returns>True if this handler can decode the opcode</returns>
public override bool CanHandle(byte opcode) 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> /// <summary>

View File

@ -39,7 +39,9 @@ public class JmpRm32Handler : InstructionHandler
var reg = ModRMDecoder.PeakModRMReg(); var reg = ModRMDecoder.PeakModRMReg();
// JMP r/m32 is encoded as FF /4 (reg field = 4) // 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> /// <summary>

View File

@ -23,7 +23,9 @@ public class LeaR32MHandler : InstructionHandler
/// <returns>True if this handler can decode the opcode</returns> /// <returns>True if this handler can decode the opcode</returns>
public override bool CanHandle(byte opcode) 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> /// <summary>

View File

@ -23,7 +23,13 @@ public class MovMemRegHandler : InstructionHandler
/// <returns>True if this handler can decode the opcode</returns> /// <returns>True if this handler can decode the opcode</returns>
public override bool CanHandle(byte opcode) 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> /// <summary>

View File

@ -23,7 +23,13 @@ public class MovRegMemHandler : InstructionHandler
/// <returns>True if this handler can decode the opcode</returns> /// <returns>True if this handler can decode the opcode</returns>
public override bool CanHandle(byte opcode) 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> /// <summary>

View File

@ -34,7 +34,7 @@ public class MovRm32Imm32Handler : InstructionHandler
return false; 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(); var reg = ModRMDecoder.PeakModRMReg();
// MOV r/m8, imm8 only uses reg=0 // MOV r/m8, imm8 only uses reg=0

View File

@ -35,7 +35,7 @@ public class MovRm8Imm8Handler : InstructionHandler
return false; 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(); var reg = ModRMDecoder.PeakModRMReg();
// MOV r/m8, imm8 only uses reg=0 // MOV r/m8, imm8 only uses reg=0

View File

@ -32,7 +32,9 @@ public class NegRm32Handler : InstructionHandler
var reg = ModRMDecoder.PeakModRMReg(); 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> /// <summary>

View File

@ -33,7 +33,9 @@ public class NotRm32Handler : InstructionHandler
var reg = ModRMDecoder.PeakModRMReg(); 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> /// <summary>
@ -55,7 +57,7 @@ public class NotRm32Handler : InstructionHandler
// Read the ModR/M byte // Read the ModR/M byte
// For NOT r/m32 (0xF7 /2): // For NOT r/m32 (0xF7 /2):
// - The r/m field with mod specifies the operand (register or memory) // - 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 // Set the structured operands
// NOT has only one operand // NOT has only one operand

View File

@ -55,7 +55,7 @@ public class NotRm8Handler : InstructionHandler
// Read the ModR/M byte // Read the ModR/M byte
// For NOT r/m8 (0xF6 /2): // For NOT r/m8 (0xF6 /2):
// - The r/m field with mod specifies the operand (register or memory) // - 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 // Set the structured operands
// NOT has only one operand // NOT has only one operand

View File

@ -23,7 +23,9 @@ public class OrR32Rm32Handler : InstructionHandler
/// <returns>True if this handler can decode the opcode</returns> /// <returns>True if this handler can decode the opcode</returns>
public override bool CanHandle(byte opcode) 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> /// <summary>

View File

@ -23,7 +23,9 @@ public class OrRm32R32Handler : InstructionHandler
/// <returns>True if this handler can decode the opcode</returns> /// <returns>True if this handler can decode the opcode</returns>
public override bool CanHandle(byte opcode) 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> /// <summary>

View File

@ -23,7 +23,9 @@ public class PopRegHandler : InstructionHandler
/// <returns>True if this handler can decode the opcode</returns> /// <returns>True if this handler can decode the opcode</returns>
public override bool CanHandle(byte opcode) 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> /// <summary>

View 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;
}
}

View File

@ -38,7 +38,9 @@ public class PushRm32Handler : InstructionHandler
var reg = ModRMDecoder.PeakModRMReg(); var reg = ModRMDecoder.PeakModRMReg();
// PUSH r/m32 is encoded as FF /6 (reg field = 6) // 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> /// <summary>

View File

@ -23,7 +23,9 @@ public class RetHandler : InstructionHandler
/// <returns>True if this handler can decode the opcode</returns> /// <returns>True if this handler can decode the opcode</returns>
public override bool CanHandle(byte opcode) 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> /// <summary>

View File

@ -23,7 +23,9 @@ public class RetImmHandler : InstructionHandler
/// <returns>True if this handler can decode the opcode</returns> /// <returns>True if this handler can decode the opcode</returns>
public override bool CanHandle(byte opcode) 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> /// <summary>

View File

@ -46,7 +46,7 @@ public class SubAlImm8Handler : InstructionHandler
instruction.Type = InstructionType.Sub; instruction.Type = InstructionType.Sub;
// Create the destination register operand (AL) // Create the destination register operand (AL)
var destinationOperand = OperandFactory.CreateRegisterOperand(RegisterIndex.A, 8); var destinationOperand = OperandFactory.CreateRegisterOperand8(RegisterIndex8.AL);
// Create the source immediate operand // Create the source immediate operand
var sourceOperand = OperandFactory.CreateImmediateOperand(imm8, 8); var sourceOperand = OperandFactory.CreateImmediateOperand(imm8, 8);

View File

@ -23,7 +23,9 @@ public class SubR32Rm32Handler : InstructionHandler
/// <returns>True if this handler can decode the opcode</returns> /// <returns>True if this handler can decode the opcode</returns>
public override bool CanHandle(byte opcode) 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> /// <summary>

View File

@ -23,7 +23,9 @@ public class SubRm32R32Handler : InstructionHandler
/// <returns>True if this handler can decode the opcode</returns> /// <returns>True if this handler can decode the opcode</returns>
public override bool CanHandle(byte opcode) 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> /// <summary>

View File

@ -23,7 +23,9 @@ public class TestRegMemHandler : InstructionHandler
/// <returns>True if this handler can decode the opcode</returns> /// <returns>True if this handler can decode the opcode</returns>
public override bool CanHandle(byte opcode) 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> /// <summary>

View File

@ -23,40 +23,9 @@ public class XchgEaxRegHandler : InstructionHandler
/// <returns>True if this handler can decode the opcode</returns> /// <returns>True if this handler can decode the opcode</returns>
public override bool CanHandle(byte opcode) public override bool CanHandle(byte opcode)
{ {
return opcode >= 0x91 && opcode <= 0x97; // 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>
/// 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
};
} }
/// <summary> /// <summary>
@ -71,10 +40,7 @@ public class XchgEaxRegHandler : InstructionHandler
instruction.Type = InstructionType.Xchg; instruction.Type = InstructionType.Xchg;
// Register is encoded in the low 3 bits of the opcode // Register is encoded in the low 3 bits of the opcode
int opcodeRegIndex = opcode & 0x07; RegisterIndex reg = (RegisterIndex)(opcode & 0x07);
// Map the opcode register index to the RegisterIndex enum value
RegisterIndex reg = MapOpcodeToRegisterIndex(opcodeRegIndex);
// Create the register operands // Create the register operands
var eaxOperand = OperandFactory.CreateRegisterOperand(RegisterIndex.A); var eaxOperand = OperandFactory.CreateRegisterOperand(RegisterIndex.A);

View File

@ -46,7 +46,7 @@ public class XorAlImmHandler : InstructionHandler
byte imm8 = Decoder.ReadByte(); byte imm8 = Decoder.ReadByte();
// Create the register operand for AL // Create the register operand for AL
var alOperand = OperandFactory.CreateRegisterOperand(RegisterIndex.A, 8); var alOperand = OperandFactory.CreateRegisterOperand8(RegisterIndex8.AL);
// Create the immediate operand // Create the immediate operand
var immOperand = OperandFactory.CreateImmediateOperand(imm8, 8); var immOperand = OperandFactory.CreateImmediateOperand(imm8, 8);

View File

@ -23,7 +23,9 @@ public class XorMemRegHandler : InstructionHandler
/// <returns>True if this handler can decode the opcode</returns> /// <returns>True if this handler can decode the opcode</returns>
public override bool CanHandle(byte opcode) 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> /// <summary>

View File

@ -25,7 +25,9 @@ public class XorRegMemHandler : InstructionHandler
/// <returns>True if this handler can decode the opcode</returns> /// <returns>True if this handler can decode the opcode</returns>
public override bool CanHandle(byte opcode) 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> /// <summary>

View File

@ -1,4 +1,3 @@
using System.Diagnostics;
using System.Diagnostics.Contracts; using System.Diagnostics.Contracts;
namespace X86Disassembler.X86; namespace X86Disassembler.X86;
@ -6,6 +5,11 @@ namespace X86Disassembler.X86;
using Handlers; using Handlers;
using Operands; using Operands;
public static class Printer
{
public static Action<string>? WriteLine;
}
/// <summary> /// <summary>
/// Decodes x86 instructions from a byte buffer /// Decodes x86 instructions from a byte buffer
/// </summary> /// </summary>
@ -83,33 +87,8 @@ 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()) 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; return null;
} }
@ -120,7 +99,7 @@ public class InstructionDecoder
// Get a handler for the opcode // Get a handler for the opcode
var handler = _handlerFactory.GetHandler(opcode); var handler = _handlerFactory.GetHandler(opcode);
Debug.WriteLine($"Resolved handler {handler?.GetType().Name}"); Printer.WriteLine?.Invoke($"Resolved handler {handler?.GetType().Name}");
bool handlerSuccess = false; bool handlerSuccess = false;
@ -326,6 +305,20 @@ public class InstructionDecoder
return _codeBuffer[_position]; 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> /// <summary>
/// Peaks a byte from the buffer at the specified offset from current position without adjusting position /// Peaks a byte from the buffer at the specified offset from current position without adjusting position
/// </summary> /// </summary>

View File

@ -185,6 +185,18 @@ public class ModRMDecoder
return regIndex; 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> /// <summary>
/// Reads and decodes a ModR/M byte for standard 32-bit operands /// Reads and decodes a ModR/M byte for standard 32-bit operands
/// </summary> /// </summary>

View File

@ -39,27 +39,29 @@ public class DisplacementMemoryOperand : MemoryOperand
var registerName = RegisterMapper.GetRegisterName(BaseRegister, 32); var registerName = RegisterMapper.GetRegisterName(BaseRegister, 32);
// Format the displacement value // Format the displacement value
string formattedDisplacement; long absDisplacement = Math.Abs(Displacement);
string sign; string sign = Displacement >= 0 ? "+" : "-";
string format;
// Handle positive and negative displacements if (absDisplacement == 0)
if (Displacement >= 0)
{ {
sign = "+"; format = "X2";
formattedDisplacement = Displacement < 256 }
? $"0x{Displacement:X2}" else if (absDisplacement <= 0xFF)
: $"0x{Displacement:X8}"; {
format = "X2";
}
else if (absDisplacement <= 0xFFFF)
{
format = "X4";
} }
else else
{ {
sign = "-"; format = "X8";
// For negative values, take the absolute value for display
var absDisplacement = Math.Abs(Displacement);
formattedDisplacement = absDisplacement < 256
? $"0x{absDisplacement:X2}"
: $"0x{absDisplacement:X8}";
} }
string formattedDisplacement = $"0x{absDisplacement.ToString(format)}";
return $"{GetSizePrefix()}[{registerName}{sign}{formattedDisplacement}]"; return $"{GetSizePrefix()}[{registerName}{sign}{formattedDisplacement}]";
} }
} }

View File

@ -46,42 +46,25 @@ public class ImmediateOperand : Operand
_ => Value _ => Value
}; };
// For 8-bit immediate values, always use at least 2 digits string format;
if (Size == 8)
if (maskedValue == 0)
{ {
return $"0x{maskedValue:X2}"; format = "X2";
}
else if (maskedValue <= 0xFF)
{
format = "X2";
}
else if (maskedValue <= 0xFFFF)
{
format = "X4";
}
else
{
format = "X8";
} }
// For 16-bit immediate values, format depends on the value return $"0x{maskedValue.ToString(format)}";
if (Size == 16)
{
// 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}";
}
// For 32-bit immediate values, format depends on the instruction context
if (Size == 32)
{
// 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}";
}
}
// For larger 32-bit values, show the full 32-bit representation
return $"0x{maskedValue:X8}";
} }
} }

View File

@ -148,9 +148,9 @@ public class DataTransferInstructionTests
// Check the first operand (AL) // Check the first operand (AL)
var alOperand = instruction.StructuredOperands[0]; var alOperand = instruction.StructuredOperands[0];
Assert.IsType<RegisterOperand>(alOperand); Assert.IsType<Register8Operand>(alOperand);
var alRegisterOperand = (RegisterOperand)alOperand; var alRegisterOperand = (Register8Operand)alOperand;
Assert.Equal(RegisterIndex.A, alRegisterOperand.Register); Assert.Equal(RegisterIndex8.AL, alRegisterOperand.Register);
Assert.Equal(8, alRegisterOperand.Size); // Validate that it's an 8-bit register (AL) Assert.Equal(8, alRegisterOperand.Size); // Validate that it's an 8-bit register (AL)
// Check the second operand (Immediate) // Check the second operand (Immediate)

View File

@ -0,0 +1,97 @@
using X86Disassembler.X86;
using X86Disassembler.X86.Operands;
namespace X86DisassemblerTests.InstructionTests;
/// <summary>
/// Tests for PUSH instruction handlers
/// </summary>
public class PushInstructionTests
{
/// <summary>
/// Tests the PUSH imm32 instruction (0x68)
/// </summary>
[Fact]
public void TestPushImm32()
{
// Arrange
byte[] code = { 0x68, 0x78, 0x56, 0x34, 0x12 }; // PUSH 0x12345678
// Act
Disassembler disassembler = new Disassembler(code, 0x1000);
var instructions = disassembler.Disassemble();
// Assert
Assert.Single(instructions);
var instruction = instructions[0];
Assert.Equal(InstructionType.Push, instruction.Type);
// Check that we have one operand
Assert.Single(instruction.StructuredOperands);
// Check the operand (immediate value)
var operand = instruction.StructuredOperands[0];
Assert.IsType<ImmediateOperand>(operand);
var immOperand = (ImmediateOperand)operand;
Assert.Equal(0x12345678u, immOperand.Value);
Assert.Equal(32, immOperand.Size);
}
/// <summary>
/// Tests the PUSH imm16 instruction with operand size prefix (0x66 0x68)
/// </summary>
[Fact]
public void TestPushImm16WithOperandSizePrefix()
{
// Arrange
byte[] code = { 0x66, 0x68, 0x78, 0x56 }; // PUSH 0x5678 (with operand size prefix)
// Act
Disassembler disassembler = new Disassembler(code, 0x1000);
var instructions = disassembler.Disassemble();
// Assert
Assert.Single(instructions);
var instruction = instructions[0];
Assert.Equal(InstructionType.Push, instruction.Type);
// Check that we have one operand
Assert.Single(instruction.StructuredOperands);
// Check the operand (immediate value)
var operand = instruction.StructuredOperands[0];
Assert.IsType<ImmediateOperand>(operand);
var immOperand = (ImmediateOperand)operand;
Assert.Equal(0x5678u, immOperand.Value);
Assert.Equal(16, immOperand.Size);
}
/// <summary>
/// Tests the PUSH imm8 instruction (0x6A)
/// </summary>
[Fact]
public void TestPushImm8()
{
// Arrange
byte[] code = { 0x6A, 0x42 }; // PUSH 0x42
// Act
Disassembler disassembler = new Disassembler(code, 0x1000);
var instructions = disassembler.Disassemble();
// Assert
Assert.Single(instructions);
var instruction = instructions[0];
Assert.Equal(InstructionType.Push, instruction.Type);
// Check that we have one operand
Assert.Single(instruction.StructuredOperands);
// Check the operand (immediate value)
var operand = instruction.StructuredOperands[0];
Assert.IsType<ImmediateOperand>(operand);
var immOperand = (ImmediateOperand)operand;
Assert.Equal(0x42u, immOperand.Value);
Assert.Equal(8, immOperand.Size);
}
}

View File

@ -245,27 +245,6 @@ public class SegmentOverrideTests
Assert.Equal(-4, memoryOperand.Displacement); Assert.Equal(-4, memoryOperand.Displacement);
} }
/// <summary>
/// Tests that the FS segment override prefix (0x64) is correctly recognized when it's the only byte
/// </summary>
[Fact]
public void FsSegmentOverride_Alone_IsRecognized()
{
// Arrange
// Just the FS segment override prefix (0x64)
byte[] codeBuffer = new byte[] { 0x64 };
var disassembler = new Disassembler(codeBuffer, 0);
// Act
var instructions = disassembler.Disassemble();
// Assert
Assert.Single(instructions);
var instruction = instructions[0];
Assert.NotNull(instruction);
Assert.Equal(InstructionType.Rep, instruction.Type);
}
/// <summary> /// <summary>
/// Tests segment override with a complex addressing mode /// Tests segment override with a complex addressing mode
/// </summary> /// </summary>

View File

@ -12,6 +12,8 @@ public class RawFromFileDisassemblyTests(ITestOutputHelper output)
[ClassData(typeof(TestDataProvider))] [ClassData(typeof(TestDataProvider))]
public void RunTests(string f, int idx, TestFromFileEntry test) public void RunTests(string f, int idx, TestFromFileEntry test)
{ {
Printer.WriteLine = output.WriteLine;
// Convert hex string to byte array // Convert hex string to byte array
byte[] code = HexStringToByteArray(test.RawBytes); byte[] code = HexStringToByteArray(test.RawBytes);

View File

@ -2,57 +2,26 @@
# Format: RawBytes;Instructions # Format: RawBytes;Instructions
RawBytes;Instructions RawBytes;Instructions
# ADC r/m8, imm8 (opcode 80 /2) 14AA;[{ "Type": "Adc", "Operands": ["al", "0xAA"] }]
80D042;[{ "Type": "Adc", "Operands": ["al", "0x42"] }] 80D1AA;[{ "Type": "Adc", "Operands": ["cl", "0xAA"] }]
80D342;[{ "Type": "Adc", "Operands": ["bl", "0x42"] }] 8010AA;[{ "Type": "Adc", "Operands": ["byte ptr [eax]", "0xAA"] }]
80D142;[{ "Type": "Adc", "Operands": ["cl", "0x42"] }] 805310AA;[{ "Type": "Adc", "Operands": ["byte ptr [ebx+0x10]", "0xAA"] }]
80D242;[{ "Type": "Adc", "Operands": ["dl", "0x42"] }] 10D8;[{ "Type": "Adc", "Operands": ["al", "bl"] }]
1018;[{ "Type": "Adc", "Operands": ["byte ptr [eax]", "bl"] }]
# ADC AL, imm8 (opcode 14) 1218;[{ "Type": "Adc", "Operands": ["bl", "byte ptr [eax]"] }]
1442;[{ "Type": "Adc", "Operands": ["al", "0x42"] }] 801488AA;[{ "Type": "Adc", "Operands": ["byte ptr [eax+ecx*4]", "0xAA"] }]
6681D1AA00;[{ "Type": "Adc", "Operands": ["cx", "0xAA"] }]
# ADC r/m32, imm32 (opcode 81 /2) 668110AA00;[{ "Type": "Adc", "Operands": ["word ptr [eax]", "0xAA"] }]
81D078563412;[{ "Type": "Adc", "Operands": ["eax", "0x12345678"] }] 66815310AA00;[{ "Type": "Adc", "Operands": ["word ptr [ebx+0x10]", "0xAA"] }]
81D378563412;[{ "Type": "Adc", "Operands": ["ebx", "0x12345678"] }] 6611D8;[{ "Type": "Adc", "Operands": ["ax", "bx"] }]
81D178563412;[{ "Type": "Adc", "Operands": ["ecx", "0x12345678"] }] 661118;[{ "Type": "Adc", "Operands": ["word ptr [eax]", "bx"] }]
81D278563412;[{ "Type": "Adc", "Operands": ["edx", "0x12345678"] }] 661318;[{ "Type": "Adc", "Operands": ["bx", "word ptr [eax]"] }]
66811488AA00;[{ "Type": "Adc", "Operands": ["word ptr [eax+ecx*4]", "0xAA"] }]
# ADC EAX, imm32 (opcode 15) 15AAAA0000;[{ "Type": "Adc", "Operands": ["eax", "0xAAAA"] }]
1578563412;[{ "Type": "Adc", "Operands": ["eax", "0x12345678"] }] 81D1AAAA0000;[{ "Type": "Adc", "Operands": ["ecx", "0xAAAA"] }]
8110AAAA0000;[{ "Type": "Adc", "Operands": ["dword ptr [eax]", "0xAAAA"] }]
# ADC r/m32, imm8 (opcode 83 /2) 815310AAAA0000;[{ "Type": "Adc", "Operands": ["dword ptr [ebx+0x10]", "0xAAAA"] }]
83D042;[{ "Type": "Adc", "Operands": ["eax", "0x42"] }]
83D342;[{ "Type": "Adc", "Operands": ["ebx", "0x42"] }]
83D142;[{ "Type": "Adc", "Operands": ["ecx", "0x42"] }]
83D242;[{ "Type": "Adc", "Operands": ["edx", "0x42"] }]
# ADC r/m8, r8 (opcode 10)
10C3;[{ "Type": "Adc", "Operands": ["bl", "al"] }]
10D9;[{ "Type": "Adc", "Operands": ["cl", "bl"] }]
10E2;[{ "Type": "Adc", "Operands": ["dl", "ah"] }]
# ADC r8, r/m8 (opcode 12)
12C3;[{ "Type": "Adc", "Operands": ["al", "bl"] }]
12D9;[{ "Type": "Adc", "Operands": ["bl", "cl"] }]
12E2;[{ "Type": "Adc", "Operands": ["ah", "dl"] }]
# ADC r/m32, r32 (opcode 11)
11D8;[{ "Type": "Adc", "Operands": ["eax", "ebx"] }] 11D8;[{ "Type": "Adc", "Operands": ["eax", "ebx"] }]
11CA;[{ "Type": "Adc", "Operands": ["edx", "ecx"] }] 1118;[{ "Type": "Adc", "Operands": ["dword ptr [eax]", "ebx"] }]
11E5;[{ "Type": "Adc", "Operands": ["ebp", "esp"] }] 1318;[{ "Type": "Adc", "Operands": ["ebx", "dword ptr [eax]"] }]
114B10;[{ "Type": "Adc", "Operands": ["dword ptr [ebx+0x10]", "ecx"] }] 811488AAAA0000;[{ "Type": "Adc", "Operands": ["dword ptr [eax+ecx*4]", "0xAAAA"] }]
# ADC r32, r/m32 (opcode 13)
13D8;[{ "Type": "Adc", "Operands": ["ebx", "eax"] }]
13CA;[{ "Type": "Adc", "Operands": ["ecx", "edx"] }]
13E5;[{ "Type": "Adc", "Operands": ["esp", "ebp"] }]
134B10;[{ "Type": "Adc", "Operands": ["ecx", "dword ptr [ebx+0x10]"] }]
# ADC with memory operands
8014251000000042;[{ "Type": "Adc", "Operands": ["byte ptr [0x10]", "0x42"] }]
8114251000000078563412;[{ "Type": "Adc", "Operands": ["dword ptr [0x10]", "0x12345678"] }]
8314251000000042;[{ "Type": "Adc", "Operands": ["dword ptr [0x10]", "0x42"] }]
1004251000000000;[{ "Type": "Adc", "Operands": ["byte ptr [0x10]", "al"] }]
1204251000000000;[{ "Type": "Adc", "Operands": ["al", "byte ptr [0x10]"] }]
1104251000000000;[{ "Type": "Adc", "Operands": ["dword ptr [0x10]", "eax"] }]
1304251000000000;[{ "Type": "Adc", "Operands": ["eax", "dword ptr [0x10]"] }]
Can't render this file because it contains an unexpected character in line 6 and column 11.

View File

@ -1,60 +1,36 @@
# ADD instruction tests
# Format: RawBytes;Instructions # Format: RawBytes;Instructions
RawBytes;Instructions RawBytes;Instructions
# 8-bit ADD
04AA;[{ "Type": "Add", "Operands": ["al", "0xAA"] }]
80C1AA;[{ "Type": "Add", "Operands": ["cl", "0xAA"] }]
8000AA;[{ "Type": "Add", "Operands": ["byte ptr [eax]", "0xAA"] }]
805310AA;[{ "Type": "Add", "Operands": ["byte ptr [ebx+0x10]", "0xAA"] }]
00D8;[{ "Type": "Add", "Operands": ["al", "bl"] }]
0018;[{ "Type": "Add", "Operands": ["byte ptr [eax]", "bl"] }]
0218;[{ "Type": "Add", "Operands": ["bl", "byte ptr [eax]"] }]
800488AA;[{ "Type": "Add", "Operands": ["byte ptr [eax+ecx*4]", "0xAA"] }]
# ADD r/m8, imm8 (opcode 80 /0) # 16-bit ADD (with 66 prefix)
80C042;[{ "Type": "Add", "Operands": ["al", "0x42"] }] 6605AA00;[{ "Type": "Add", "Operands": ["ax", "0xAA"] }]
80C342;[{ "Type": "Add", "Operands": ["bl", "0x42"] }] 6681C1AA00;[{ "Type": "Add", "Operands": ["cx", "0xAA"] }]
80C142;[{ "Type": "Add", "Operands": ["cl", "0x42"] }] 668100AA00;[{ "Type": "Add", "Operands": ["word ptr [eax]", "0xAA"] }]
80C242;[{ "Type": "Add", "Operands": ["dl", "0x42"] }] 66814310AA00;[{ "Type": "Add", "Operands": ["word ptr [ebx+0x10]", "0xAA"] }]
6601D8;[{ "Type": "Add", "Operands": ["ax", "bx"] }]
660118;[{ "Type": "Add", "Operands": ["word ptr [eax]", "bx"] }]
660318;[{ "Type": "Add", "Operands": ["bx", "word ptr [eax]"] }]
66810488AA00;[{ "Type": "Add", "Operands": ["word ptr [eax+ecx*4]", "0xAA"] }]
# ADD AL, imm8 (opcode 04) # 32-bit ADD
0442;[{ "Type": "Add", "Operands": ["al", "0x42"] }] 05AA000000;[{ "Type": "Add", "Operands": ["eax", "0xAA"] }]
81C1AA000000;[{ "Type": "Add", "Operands": ["ecx", "0xAA"] }]
# ADD r/m32, imm32 (opcode 81 /0) 8100AA000000;[{ "Type": "Add", "Operands": ["dword ptr [eax]", "0xAA"] }]
81C078563412;[{ "Type": "Add", "Operands": ["eax", "0x12345678"] }] 814310AA000000;[{ "Type": "Add", "Operands": ["dword ptr [ebx+0x10]", "0xAA"] }]
81C378563412;[{ "Type": "Add", "Operands": ["ebx", "0x12345678"] }]
81C178563412;[{ "Type": "Add", "Operands": ["ecx", "0x12345678"] }]
81C278563412;[{ "Type": "Add", "Operands": ["edx", "0x12345678"] }]
# ADD EAX, imm32 (opcode 05)
0578563412;[{ "Type": "Add", "Operands": ["eax", "0x12345678"] }]
# ADD r/m32, imm8 (opcode 83 /0) with sign extension
83C042;[{ "Type": "Add", "Operands": ["eax", "0x42"] }]
83C342;[{ "Type": "Add", "Operands": ["ebx", "0x42"] }]
83C142;[{ "Type": "Add", "Operands": ["ecx", "0x42"] }]
83C242;[{ "Type": "Add", "Operands": ["edx", "0x42"] }]
83C0FF;[{ "Type": "Add", "Operands": ["eax", "0xFFFFFFFF"] }]
83C3FF;[{ "Type": "Add", "Operands": ["ebx", "0xFFFFFFFF"] }]
# ADD r/m8, r8 (opcode 00)
00C3;[{ "Type": "Add", "Operands": ["bl", "al"] }]
00D9;[{ "Type": "Add", "Operands": ["cl", "bl"] }]
00E2;[{ "Type": "Add", "Operands": ["dl", "ah"] }]
# ADD r8, r/m8 (opcode 02)
02C3;[{ "Type": "Add", "Operands": ["al", "bl"] }]
02D9;[{ "Type": "Add", "Operands": ["bl", "cl"] }]
02E2;[{ "Type": "Add", "Operands": ["ah", "dl"] }]
# ADD r/m32, r32 (opcode 01)
01D8;[{ "Type": "Add", "Operands": ["eax", "ebx"] }] 01D8;[{ "Type": "Add", "Operands": ["eax", "ebx"] }]
01CA;[{ "Type": "Add", "Operands": ["edx", "ecx"] }] 0118;[{ "Type": "Add", "Operands": ["dword ptr [eax]", "ebx"] }]
01E5;[{ "Type": "Add", "Operands": ["ebp", "esp"] }] 0318;[{ "Type": "Add", "Operands": ["ebx", "dword ptr [eax]"] }]
014B10;[{ "Type": "Add", "Operands": ["dword ptr [ebx+0x10]", "ecx"] }] 810488AA000000;[{ "Type": "Add", "Operands": ["dword ptr [eax+ecx*4]", "0xAA"] }]
# ADD r32, r/m32 (opcode 03) # Mixed addressing modes
03D8;[{ "Type": "Add", "Operands": ["ebx", "eax"] }] 00A314285600;[{ "Type": "Add", "Operands": ["byte ptr [ebx+0x562814]", "ah"] }]
03CA;[{ "Type": "Add", "Operands": ["ecx", "edx"] }] 6601B310203040;[{ "Type": "Add", "Operands": ["si", "word ptr [ebx+0x40302010]"] }]
03E5;[{ "Type": "Add", "Operands": ["esp", "ebp"] }] 030C8D10203040;[{ "Type": "Add", "Operands": ["ecx", "dword ptr [ebp*4+0x40302010]"] }]
034B10;[{ "Type": "Add", "Operands": ["ecx", "dword ptr [ebx+0x10]"] }]
# ADD with memory operands
8004251000000042;[{ "Type": "Add", "Operands": ["byte ptr [0x10]", "0x42"] }]
8104251000000078563412;[{ "Type": "Add", "Operands": ["dword ptr [0x10]", "0x12345678"] }]
8304251000000042;[{ "Type": "Add", "Operands": ["dword ptr [0x10]", "0x42"] }]
00042510000000;[{ "Type": "Add", "Operands": ["byte ptr [0x10]", "al"] }]
02042510000000;[{ "Type": "Add", "Operands": ["al", "byte ptr [0x10]"] }]
01042510000000;[{ "Type": "Add", "Operands": ["dword ptr [0x10]", "eax"] }]
03042510000000;[{ "Type": "Add", "Operands": ["eax", "dword ptr [0x10]"] }]
Can't render this file because it contains an unexpected character in line 6 and column 11.

View File

@ -1,58 +1,42 @@
# AND instruction tests
# Format: RawBytes;Instructions # Format: RawBytes;Instructions
RawBytes;Instructions RawBytes;Instructions
# 8-bit AND
24AA;[{ "Type": "And", "Operands": ["al", "0xAA"] }]
# Alternate encoding
80E0AA;[{ "Type": "And", "Operands": ["al", "0xAA"] }]
80E1AA;[{ "Type": "And", "Operands": ["cl", "0xAA"] }]
8020AA;[{ "Type": "And", "Operands": ["byte ptr [eax]", "0xAA"] }]
806310AA;[{ "Type": "And", "Operands": ["byte ptr [ebx+0x10]", "0xAA"] }]
20D8;[{ "Type": "And", "Operands": ["al", "bl"] }]
2018;[{ "Type": "And", "Operands": ["byte ptr [eax]", "bl"] }]
2218;[{ "Type": "And", "Operands": ["bl", "byte ptr [eax]"] }]
800488AA;[{ "Type": "And", "Operands": ["byte ptr [eax+ecx*4]", "0xAA"] }]
# AND r/m8, imm8 (opcode 80 /4) # 16-bit AND (with 66 prefix)
80E042;[{ "Type": "And", "Operands": ["al", "0x42"] }] 6625AA00;[{ "Type": "And", "Operands": ["ax", "0xAA"] }]
80E342;[{ "Type": "And", "Operands": ["bl", "0x42"] }] # Alternate encoding
80E142;[{ "Type": "And", "Operands": ["cl", "0x42"] }] 6681E0AA00;[{ "Type": "And", "Operands": ["ax", "0xAA"] }]
80E242;[{ "Type": "And", "Operands": ["dl", "0x42"] }] 6681E1AA00;[{ "Type": "And", "Operands": ["cx", "0xAA"] }]
668120AA00;[{ "Type": "And", "Operands": ["word ptr [eax]", "0xAA"] }]
66816310AA00;[{ "Type": "And", "Operands": ["word ptr [ebx+0x10]", "0xAA"] }]
6621D8;[{ "Type": "And", "Operands": ["ax", "bx"] }]
662118;[{ "Type": "And", "Operands": ["word ptr [eax]", "bx"] }]
662318;[{ "Type": "And", "Operands": ["bx", "word ptr [eax]"] }]
66810488AA00;[{ "Type": "And", "Operands": ["word ptr [eax+ecx*4]", "0xAA"] }]
# AND AL, imm8 (opcode 24) # 32-bit AND
2442;[{ "Type": "And", "Operands": ["al", "0x42"] }] 25AA000000;[{ "Type": "And", "Operands": ["eax", "0xAA"] }]
# Alternate encoding
# AND r/m32, imm32 (opcode 81 /4) 81E0AA000000;[{ "Type": "And", "Operands": ["eax", "0xAA"] }]
81E078563412;[{ "Type": "And", "Operands": ["eax", "0x12345678"] }] 81E1AA000000;[{ "Type": "And", "Operands": ["ecx", "0xAA"] }]
81E378563412;[{ "Type": "And", "Operands": ["ebx", "0x12345678"] }] 8120AA000000;[{ "Type": "And", "Operands": ["dword ptr [eax]", "0xAA"] }]
81E178563412;[{ "Type": "And", "Operands": ["ecx", "0x12345678"] }] 816310AA000000;[{ "Type": "And", "Operands": ["dword ptr [ebx+0x10]", "0xAA"] }]
81E278563412;[{ "Type": "And", "Operands": ["edx", "0x12345678"] }]
# AND EAX, imm32 (opcode 25)
2578563412;[{ "Type": "And", "Operands": ["eax", "0x12345678"] }]
# AND r/m32, imm8 (opcode 83 /4)
83E042;[{ "Type": "And", "Operands": ["eax", "0x42"] }]
83E342;[{ "Type": "And", "Operands": ["ebx", "0x42"] }]
83E142;[{ "Type": "And", "Operands": ["ecx", "0x42"] }]
83E242;[{ "Type": "And", "Operands": ["edx", "0x42"] }]
# AND r/m8, r8 (opcode 20)
20C3;[{ "Type": "And", "Operands": ["bl", "al"] }]
20D9;[{ "Type": "And", "Operands": ["cl", "bl"] }]
20E2;[{ "Type": "And", "Operands": ["dl", "ah"] }]
# AND r8, r/m8 (opcode 22)
22C3;[{ "Type": "And", "Operands": ["al", "bl"] }]
22D9;[{ "Type": "And", "Operands": ["bl", "cl"] }]
22E2;[{ "Type": "And", "Operands": ["ah", "dl"] }]
# AND r/m32, r32 (opcode 21)
21D8;[{ "Type": "And", "Operands": ["eax", "ebx"] }] 21D8;[{ "Type": "And", "Operands": ["eax", "ebx"] }]
21CA;[{ "Type": "And", "Operands": ["edx", "ecx"] }] 2118;[{ "Type": "And", "Operands": ["dword ptr [eax]", "ebx"] }]
21E5;[{ "Type": "And", "Operands": ["ebp", "esp"] }] 2318;[{ "Type": "And", "Operands": ["ebx", "dword ptr [eax]"] }]
214B10;[{ "Type": "And", "Operands": ["dword ptr [ebx+0x10]", "ecx"] }] 810488AA000000;[{ "Type": "And", "Operands": ["dword ptr [eax+ecx*4]", "0xAA"] }]
# AND r32, r/m32 (opcode 23) # Complex addressing modes
23D8;[{ "Type": "And", "Operands": ["ebx", "eax"] }] 20A314285600;[{ "Type": "And", "Operands": ["byte ptr [ebx+0x562814]", "ah"] }]
23CA;[{ "Type": "And", "Operands": ["ecx", "edx"] }] 6621B310203040;[{ "Type": "And", "Operands": ["word ptr [ebx+0x40302010]", "si"] }]
23E5;[{ "Type": "And", "Operands": ["esp", "ebp"] }] 230C8D10203040;[{ "Type": "And", "Operands": ["ecx", "dword ptr [ebp*4+0x40302010]"] }]
234B10;[{ "Type": "And", "Operands": ["ecx", "dword ptr [ebx+0x10]"] }]
# AND with memory operands
8024251000000042;[{ "Type": "And", "Operands": ["byte ptr [0x10]", "0x42"] }]
8124251000000078563412;[{ "Type": "And", "Operands": ["dword ptr [0x10]", "0x12345678"] }]
8324251000000042;[{ "Type": "And", "Operands": ["dword ptr [0x10]", "0x42"] }]
20042510000000;[{ "Type": "And", "Operands": ["byte ptr [0x10]", "al"] }]
22042510000000;[{ "Type": "And", "Operands": ["al", "byte ptr [0x10]"] }]
21042510000000;[{ "Type": "And", "Operands": ["dword ptr [0x10]", "eax"] }]
23042510000000;[{ "Type": "And", "Operands": ["eax", "dword ptr [0x10]"] }]
Can't render this file because it contains an unexpected character in line 6 and column 11.

View File

@ -2,20 +2,40 @@
# Format: RawBytes;Instructions # Format: RawBytes;Instructions
RawBytes;Instructions RawBytes;Instructions
# BT - Bit Test (Immediate)
0FBA2005;[{ "Type": "Bt", "Operands": ["dword ptr [eax]", "0x05"] }]
0FBA650005;[{ "Type": "Bt", "Operands": ["dword ptr [ebp+0x00]", "0x05"] }]
0FBA2305;[{ "Type": "Bt", "Operands": ["dword ptr [ebx]", "0x05"] }]
0FBA2105;[{ "Type": "Bt", "Operands": ["dword ptr [ecx]", "0x05"] }]
0FBA2205;[{ "Type": "Bt", "Operands": ["dword ptr [edx]", "0x05"] }]
# BTS - Bit Test and Set (Immediate)
0FBAA805;[{ "Type": "Bts", "Operands": ["dword ptr [eax]", "0x05"] }]
0FBA6D0005;[{ "Type": "Bts", "Operands": ["dword ptr [ebp+0x00]", "0x05"] }]
0FBAAB05;[{ "Type": "Bts", "Operands": ["dword ptr [ebx]", "0x05"] }]
0FBAA905;[{ "Type": "Bts", "Operands": ["dword ptr [ecx]", "0x05"] }]
0FBAAA05;[{ "Type": "Bts", "Operands": ["dword ptr [edx]", "0x05"] }]
# BTR - Bit Test and Reset (Immediate)
0FBAB005;[{ "Type": "Btr", "Operands": ["dword ptr [eax]", "0x05"] }]
0FBA750005;[{ "Type": "Btr", "Operands": ["dword ptr [ebp+0x00]", "0x05"] }]
0FBAB305;[{ "Type": "Btr", "Operands": ["dword ptr [ebx]", "0x05"] }]
0FBAB105;[{ "Type": "Btr", "Operands": ["dword ptr [ecx]", "0x05"] }]
0FBAB205;[{ "Type": "Btr", "Operands": ["dword ptr [edx]", "0x05"] }]
# BTC - Bit Test and Complement (Immediate)
0FBAB805;[{ "Type": "Btc", "Operands": ["dword ptr [eax]", "0x05"] }]
0FBA7D0005;[{ "Type": "Btc", "Operands": ["dword ptr [ebp+0x00]", "0x05"] }]
0FBABB05;[{ "Type": "Btc", "Operands": ["dword ptr [ebx]", "0x05"] }]
0FBAB905;[{ "Type": "Btc", "Operands": ["dword ptr [ecx]", "0x05"] }]
0FBABA05;[{ "Type": "Btc", "Operands": ["dword ptr [edx]", "0x05"] }]
# BT - Bit Test # BT - Bit Test
0FA3C1;[{ "Type": "Bt", "Operands": ["ecx", "eax"] }] 0FA3C1;[{ "Type": "Bt", "Operands": ["ecx", "eax"] }]
0FA3D9;[{ "Type": "Bt", "Operands": ["ecx", "ebx"] }] 0FA3D9;[{ "Type": "Bt", "Operands": ["ecx", "ebx"] }]
0FA3CA;[{ "Type": "Bt", "Operands": ["edx", "ecx"] }] 0FA3CA;[{ "Type": "Bt", "Operands": ["edx", "ecx"] }]
0FA3E2;[{ "Type": "Bt", "Operands": ["edx", "esp"] }] 0FA3E2;[{ "Type": "Bt", "Operands": ["edx", "esp"] }]
0FA3F6;[{ "Type": "Bt", "Operands": ["esi", "esi"] }] 0FA3F6;[{ "Type": "Bt", "Operands": ["esi", "esi"] }]
0FA30425;[{ "Type": "Bt", "Operands": ["dword ptr [eax]", "eax"] }]
0FA30C25;[{ "Type": "Bt", "Operands": ["dword ptr [eax]", "ecx"] }]
0FA31425;[{ "Type": "Bt", "Operands": ["dword ptr [eax]", "edx"] }]
0FBA2005;[{ "Type": "Bt", "Operands": ["dword ptr [eax]", "0x05"] }]
0FBA2505;[{ "Type": "Bt", "Operands": ["dword ptr [ebp]", "0x05"] }]
0FBA2305;[{ "Type": "Bt", "Operands": ["dword ptr [ebx]", "0x05"] }]
0FBA2105;[{ "Type": "Bt", "Operands": ["dword ptr [ecx]", "0x05"] }]
0FBA2205;[{ "Type": "Bt", "Operands": ["dword ptr [edx]", "0x05"] }]
# BTS - Bit Test and Set # BTS - Bit Test and Set
0FABC1;[{ "Type": "Bts", "Operands": ["ecx", "eax"] }] 0FABC1;[{ "Type": "Bts", "Operands": ["ecx", "eax"] }]
@ -23,14 +43,6 @@ RawBytes;Instructions
0FABCA;[{ "Type": "Bts", "Operands": ["edx", "ecx"] }] 0FABCA;[{ "Type": "Bts", "Operands": ["edx", "ecx"] }]
0FABE2;[{ "Type": "Bts", "Operands": ["edx", "esp"] }] 0FABE2;[{ "Type": "Bts", "Operands": ["edx", "esp"] }]
0FABF6;[{ "Type": "Bts", "Operands": ["esi", "esi"] }] 0FABF6;[{ "Type": "Bts", "Operands": ["esi", "esi"] }]
0FAB0425;[{ "Type": "Bts", "Operands": ["dword ptr [eax]", "eax"] }]
0FAB0C25;[{ "Type": "Bts", "Operands": ["dword ptr [eax]", "ecx"] }]
0FAB1425;[{ "Type": "Bts", "Operands": ["dword ptr [eax]", "edx"] }]
0FBA2805;[{ "Type": "Bts", "Operands": ["dword ptr [eax]", "0x05"] }]
0FBA2D05;[{ "Type": "Bts", "Operands": ["dword ptr [ebp]", "0x05"] }]
0FBA2B05;[{ "Type": "Bts", "Operands": ["dword ptr [ebx]", "0x05"] }]
0FBA2905;[{ "Type": "Bts", "Operands": ["dword ptr [ecx]", "0x05"] }]
0FBA2A05;[{ "Type": "Bts", "Operands": ["dword ptr [edx]", "0x05"] }]
# BTR - Bit Test and Reset # BTR - Bit Test and Reset
0FB3C1;[{ "Type": "Btr", "Operands": ["ecx", "eax"] }] 0FB3C1;[{ "Type": "Btr", "Operands": ["ecx", "eax"] }]
@ -38,29 +50,6 @@ RawBytes;Instructions
0FB3CA;[{ "Type": "Btr", "Operands": ["edx", "ecx"] }] 0FB3CA;[{ "Type": "Btr", "Operands": ["edx", "ecx"] }]
0FB3E2;[{ "Type": "Btr", "Operands": ["edx", "esp"] }] 0FB3E2;[{ "Type": "Btr", "Operands": ["edx", "esp"] }]
0FB3F6;[{ "Type": "Btr", "Operands": ["esi", "esi"] }] 0FB3F6;[{ "Type": "Btr", "Operands": ["esi", "esi"] }]
0FB30425;[{ "Type": "Btr", "Operands": ["dword ptr [eax]", "eax"] }]
0FB30C25;[{ "Type": "Btr", "Operands": ["dword ptr [eax]", "ecx"] }]
0FB31425;[{ "Type": "Btr", "Operands": ["dword ptr [eax]", "edx"] }]
0FBA3005;[{ "Type": "Btr", "Operands": ["dword ptr [eax]", "0x05"] }]
0FBA3505;[{ "Type": "Btr", "Operands": ["dword ptr [ebp]", "0x05"] }]
0FBA3305;[{ "Type": "Btr", "Operands": ["dword ptr [ebx]", "0x05"] }]
0FBA3105;[{ "Type": "Btr", "Operands": ["dword ptr [ecx]", "0x05"] }]
0FBA3205;[{ "Type": "Btr", "Operands": ["dword ptr [edx]", "0x05"] }]
# BTC - Bit Test and Complement
0FBBC1;[{ "Type": "Btc", "Operands": ["ecx", "eax"] }]
0FBBD9;[{ "Type": "Btc", "Operands": ["ecx", "ebx"] }]
0FBBCA;[{ "Type": "Btc", "Operands": ["edx", "ecx"] }]
0FBBE2;[{ "Type": "Btc", "Operands": ["edx", "esp"] }]
0FBBF6;[{ "Type": "Btc", "Operands": ["esi", "esi"] }]
0FBB0425;[{ "Type": "Btc", "Operands": ["dword ptr [eax]", "eax"] }]
0FBB0C25;[{ "Type": "Btc", "Operands": ["dword ptr [eax]", "ecx"] }]
0FBB1425;[{ "Type": "Btc", "Operands": ["dword ptr [eax]", "edx"] }]
0FBA3805;[{ "Type": "Btc", "Operands": ["dword ptr [eax]", "0x05"] }]
0FBA3D05;[{ "Type": "Btc", "Operands": ["dword ptr [ebp]", "0x05"] }]
0FBA3B05;[{ "Type": "Btc", "Operands": ["dword ptr [ebx]", "0x05"] }]
0FBA3905;[{ "Type": "Btc", "Operands": ["dword ptr [ecx]", "0x05"] }]
0FBA3A05;[{ "Type": "Btc", "Operands": ["dword ptr [edx]", "0x05"] }]
# BSF - Bit Scan Forward # BSF - Bit Scan Forward
0FBCC1;[{ "Type": "Bsf", "Operands": ["eax", "ecx"] }] 0FBCC1;[{ "Type": "Bsf", "Operands": ["eax", "ecx"] }]
@ -68,11 +57,20 @@ RawBytes;Instructions
0FBCCA;[{ "Type": "Bsf", "Operands": ["ecx", "edx"] }] 0FBCCA;[{ "Type": "Bsf", "Operands": ["ecx", "edx"] }]
0FBCE2;[{ "Type": "Bsf", "Operands": ["esp", "edx"] }] 0FBCE2;[{ "Type": "Bsf", "Operands": ["esp", "edx"] }]
0FBCF6;[{ "Type": "Bsf", "Operands": ["esi", "esi"] }] 0FBCF6;[{ "Type": "Bsf", "Operands": ["esi", "esi"] }]
0FBC0425;[{ "Type": "Bsf", "Operands": ["eax", "dword ptr [eax]"] }]
0FBC0C25;[{ "Type": "Bsf", "Operands": ["ecx", "dword ptr [eax]"] }] # BTC - Bit Test and Complement
0FBC1425;[{ "Type": "Bsf", "Operands": ["edx", "dword ptr [eax]"] }] 0FBBC1;[{ "Type": "Btc", "Operands": ["ecx", "eax"] }]
0FBC1C25;[{ "Type": "Bsf", "Operands": ["ebx", "dword ptr [eax]"] }] 0FBBD9;[{ "Type": "Btc", "Operands": ["ecx", "ebx"] }]
0FBC2425;[{ "Type": "Bsf", "Operands": ["esp", "dword ptr [eax]"] }] 0FBBCA;[{ "Type": "Btc", "Operands": ["edx", "ecx"] }]
0FBBE2;[{ "Type": "Btc", "Operands": ["edx", "esp"] }]
0FBBF6;[{ "Type": "Btc", "Operands": ["esi", "esi"] }]
# BSF - Bit Scan Forward
0FBC00;[{ "Type": "Bsf", "Operands": ["eax", "dword ptr [eax]"] }]
0FBC08;[{ "Type": "Bsf", "Operands": ["ecx", "dword ptr [eax]"] }]
0FBC10;[{ "Type": "Bsf", "Operands": ["edx", "dword ptr [eax]"] }]
0FBC18;[{ "Type": "Bsf", "Operands": ["ebx", "dword ptr [eax]"] }]
0FBC20;[{ "Type": "Bsf", "Operands": ["esp", "dword ptr [eax]"] }]
# BSR - Bit Scan Reverse # BSR - Bit Scan Reverse
0FBDC1;[{ "Type": "Bsr", "Operands": ["eax", "ecx"] }] 0FBDC1;[{ "Type": "Bsr", "Operands": ["eax", "ecx"] }]
@ -80,8 +78,8 @@ RawBytes;Instructions
0FBDCA;[{ "Type": "Bsr", "Operands": ["ecx", "edx"] }] 0FBDCA;[{ "Type": "Bsr", "Operands": ["ecx", "edx"] }]
0FBDE2;[{ "Type": "Bsr", "Operands": ["esp", "edx"] }] 0FBDE2;[{ "Type": "Bsr", "Operands": ["esp", "edx"] }]
0FBDF6;[{ "Type": "Bsr", "Operands": ["esi", "esi"] }] 0FBDF6;[{ "Type": "Bsr", "Operands": ["esi", "esi"] }]
0FBD0425;[{ "Type": "Bsr", "Operands": ["eax", "dword ptr [eax]"] }] 0FBD00;[{ "Type": "Bsr", "Operands": ["eax", "dword ptr [eax]"] }]
0FBD0C25;[{ "Type": "Bsr", "Operands": ["ecx", "dword ptr [eax]"] }] 0FBD08;[{ "Type": "Bsr", "Operands": ["ecx", "dword ptr [eax]"] }]
0FBD1425;[{ "Type": "Bsr", "Operands": ["edx", "dword ptr [eax]"] }] 0FBD10;[{ "Type": "Bsr", "Operands": ["edx", "dword ptr [eax]"] }]
0FBD1C25;[{ "Type": "Bsr", "Operands": ["ebx", "dword ptr [eax]"] }] 0FBD18;[{ "Type": "Bsr", "Operands": ["ebx", "dword ptr [eax]"] }]
0FBD2425;[{ "Type": "Bsr", "Operands": ["esp", "dword ptr [eax]"] }] 0FBD20;[{ "Type": "Bsr", "Operands": ["esp", "dword ptr [eax]"] }]

Can't render this file because it contains an unexpected character in line 6 and column 11.

View File

@ -22,46 +22,23 @@ F7F5;[{ "Type": "Div", "Operands": ["ebp"] }]
F7F6;[{ "Type": "Div", "Operands": ["esi"] }] F7F6;[{ "Type": "Div", "Operands": ["esi"] }]
F7F7;[{ "Type": "Div", "Operands": ["edi"] }] F7F7;[{ "Type": "Div", "Operands": ["edi"] }]
# DIV with memory operands
# Basic memory addressing # Basic memory addressing
# SPECIAL CASE: When using SIB byte with Base=101 (EBP) and Mod=00, it requires a 32-bit displacement
# The correct encoding for "DIV byte ptr [eax]" would be F630 (with Mod=00, R/M=0 for EAX)
# F63425;[{ "Type": "Div", "Operands": ["byte ptr [eax]"] }]
F630;[{ "Type": "Div", "Operands": ["byte ptr [eax]"] }] F630;[{ "Type": "Div", "Operands": ["byte ptr [eax]"] }]
# For "DIV byte ptr [ebp]", we need to use Mod=01 with a zero displacement since [ebp] can't be encoded with Mod=00
# F63C25;[{ "Type": "Div", "Operands": ["byte ptr [ebp]"] }]
F66500;[{ "Type": "Div", "Operands": ["byte ptr [ebp]"] }]
# The correct encoding for "DIV byte ptr [eax]" would be F630 (with Mod=00, R/M=0 for EAX)
# F63825;[{ "Type": "Div", "Operands": ["byte ptr [eax]"] }]
F630;[{ "Type": "Div", "Operands": ["byte ptr [eax]"] }] F630;[{ "Type": "Div", "Operands": ["byte ptr [eax]"] }]
# The correct encoding for "DIV dword ptr [eax]" would be F730 (with Mod=00, R/M=0 for EAX)
# F73425;[{ "Type": "Div", "Operands": ["dword ptr [eax]"] }]
F730;[{ "Type": "Div", "Operands": ["dword ptr [eax]"] }] F730;[{ "Type": "Div", "Operands": ["dword ptr [eax]"] }]
# For "DIV dword ptr [ebp]", we need to use Mod=01 with a zero displacement since [ebp] can't be encoded with Mod=00 F77500;[{ "Type": "Div", "Operands": ["dword ptr [ebp+0x00]"] }]
# F73C25;[{ "Type": "Div", "Operands": ["dword ptr [ebp]"] }]
F76500;[{ "Type": "Div", "Operands": ["dword ptr [ebp]"] }]
# The correct encoding for "DIV dword ptr [eax]" would be F730 (with Mod=00, R/M=0 for EAX)
# F73825;[{ "Type": "Div", "Operands": ["dword ptr [eax]"] }]
F730;[{ "Type": "Div", "Operands": ["dword ptr [eax]"] }] F730;[{ "Type": "Div", "Operands": ["dword ptr [eax]"] }]
# With displacement F77010;[{ "Type": "Div", "Operands": ["dword ptr [eax+0x10]"] }]
# The correct encoding for "DIV dword ptr [eax+0x10]" would be F74010 (with Mod=01, R/M=0 for EAX, disp8=0x10)
# F7742510000000;[{ "Type": "Div", "Operands": ["dword ptr [eax+0x10]"] }]
F74010;[{ "Type": "Div", "Operands": ["dword ptr [eax+0x10]"] }]
# The correct encoding for "DIV dword ptr [eax+0x20]" would be F74020 (with Mod=01, R/M=0 for EAX, disp8=0x20) F77020;[{ "Type": "Div", "Operands": ["dword ptr [eax+0x20]"] }]
# F7742520000000;[{ "Type": "Div", "Operands": ["dword ptr [eax+0x20]"] }]
F74020;[{ "Type": "Div", "Operands": ["dword ptr [eax+0x20]"] }]
# The correct encoding for "DIV dword ptr [eax+0x30]" would be F74030 (with Mod=01, R/M=0 for EAX, disp8=0x30) F77030;[{ "Type": "Div", "Operands": ["dword ptr [eax+0x30]"] }]
# F7742530000000;[{ "Type": "Div", "Operands": ["dword ptr [eax+0x30]"] }]
F74030;[{ "Type": "Div", "Operands": ["dword ptr [eax+0x30]"] }]
# With SIB addressing # With SIB addressing
F7341C;[{ "Type": "Div", "Operands": ["dword ptr [esp+ebx*1]"] }] F7341C;[{ "Type": "Div", "Operands": ["dword ptr [esp+ebx*1]"] }]
@ -70,10 +47,9 @@ F7349C;[{ "Type": "Div", "Operands": ["dword ptr [esp+ebx*4]"] }]
F734DC;[{ "Type": "Div", "Operands": ["dword ptr [esp+ebx*8]"] }] F734DC;[{ "Type": "Div", "Operands": ["dword ptr [esp+ebx*8]"] }]
# With segment override prefixes # With segment override prefixes
# not recognized by ghidra or online disasms 26F730;[{ "Type": "Div", "Operands": ["dword ptr es:[eax]"] }]
# 26F73425;[{ "Type": "Div", "Operands": ["dword ptr es:[eax]"] }] 2EF730;[{ "Type": "Div", "Operands": ["dword ptr cs:[eax]"] }]
# 2EF73425;[{ "Type": "Div", "Operands": ["dword ptr cs:[eax]"] }] 36F730;[{ "Type": "Div", "Operands": ["dword ptr ss:[eax]"] }]
# 36F73425;[{ "Type": "Div", "Operands": ["dword ptr ss:[eax]"] }] 3EF730;[{ "Type": "Div", "Operands": ["dword ptr ds:[eax]"] }]
# 3EF73425;[{ "Type": "Div", "Operands": ["dword ptr ds:[eax]"] }] 64F730;[{ "Type": "Div", "Operands": ["dword ptr fs:[eax]"] }]
# 64F73425;[{ "Type": "Div", "Operands": ["dword ptr fs:[eax]"] }] 65F730;[{ "Type": "Div", "Operands": ["dword ptr gs:[eax]"] }]
# 65F73425;[{ "Type": "Div", "Operands": ["dword ptr gs:[eax]"] }]

Can't render this file because it contains an unexpected character in line 6 and column 9.

View File

@ -7,8 +7,8 @@ RawBytes;Instructions
8F01;[{ "Type": "Pop", "Operands": ["dword ptr [ecx]"] }] 8F01;[{ "Type": "Pop", "Operands": ["dword ptr [ecx]"] }]
8F02;[{ "Type": "Pop", "Operands": ["dword ptr [edx]"] }] 8F02;[{ "Type": "Pop", "Operands": ["dword ptr [edx]"] }]
8F03;[{ "Type": "Pop", "Operands": ["dword ptr [ebx]"] }] 8F03;[{ "Type": "Pop", "Operands": ["dword ptr [ebx]"] }]
8F04;[{ "Type": "Pop", "Operands": ["dword ptr [esp]"] }] 8F0424;[{ "Type": "Pop", "Operands": ["dword ptr [esp]"] }]
8F05;[{ "Type": "Pop", "Operands": ["dword ptr [ebp]"] }] 88F4500;[{ "Type": "Pop", "Operands": ["dword ptr [ebp]"] }]
8F06;[{ "Type": "Pop", "Operands": ["dword ptr [esi]"] }] 8F06;[{ "Type": "Pop", "Operands": ["dword ptr [esi]"] }]
8F07;[{ "Type": "Pop", "Operands": ["dword ptr [edi]"] }] 8F07;[{ "Type": "Pop", "Operands": ["dword ptr [edi]"] }]
@ -17,7 +17,7 @@ RawBytes;Instructions
8F4110;[{ "Type": "Pop", "Operands": ["dword ptr [ecx+0x10]"] }] 8F4110;[{ "Type": "Pop", "Operands": ["dword ptr [ecx+0x10]"] }]
8F4210;[{ "Type": "Pop", "Operands": ["dword ptr [edx+0x10]"] }] 8F4210;[{ "Type": "Pop", "Operands": ["dword ptr [edx+0x10]"] }]
8F4310;[{ "Type": "Pop", "Operands": ["dword ptr [ebx+0x10]"] }] 8F4310;[{ "Type": "Pop", "Operands": ["dword ptr [ebx+0x10]"] }]
8F4410;[{ "Type": "Pop", "Operands": ["dword ptr [esp+0x10]"] }] 8F442410;[{ "Type": "Pop", "Operands": ["dword ptr [esp+0x10]"] }]
8F4510;[{ "Type": "Pop", "Operands": ["dword ptr [ebp+0x10]"] }] 8F4510;[{ "Type": "Pop", "Operands": ["dword ptr [ebp+0x10]"] }]
8F4610;[{ "Type": "Pop", "Operands": ["dword ptr [esi+0x10]"] }] 8F4610;[{ "Type": "Pop", "Operands": ["dword ptr [esi+0x10]"] }]
8F4710;[{ "Type": "Pop", "Operands": ["dword ptr [edi+0x10]"] }] 8F4710;[{ "Type": "Pop", "Operands": ["dword ptr [edi+0x10]"] }]

Can't render this file because it contains an unexpected character in line 6 and column 9.

View File

@ -11,9 +11,9 @@ RawBytes;Instructions
6AFF;[{ "Type": "Push", "Operands": ["0xFF"] }] 6AFF;[{ "Type": "Push", "Operands": ["0xFF"] }]
# PUSH imm32 with various values # PUSH imm32 with various values
6800000000;[{ "Type": "Push", "Operands": ["0x00000000"] }] 6800000000;[{ "Type": "Push", "Operands": ["0x00"] }]
68FFFFFFFF;[{ "Type": "Push", "Operands": ["0xFFFFFFFF"] }] 68FFFFFFFF;[{ "Type": "Push", "Operands": ["0xFFFFFFFF"] }]
6801000000;[{ "Type": "Push", "Operands": ["0x00000001"] }] 6801000000;[{ "Type": "Push", "Operands": ["0x01"] }]
# PUSH imm16 with operand size prefix # PUSH imm16 with operand size prefix
66687856;[{ "Type": "Push", "Operands": ["0x5678"] }] 66687856;[{ "Type": "Push", "Operands": ["0x5678"] }]

Can't render this file because it contains an unexpected character in line 6 and column 15.

View File

@ -7,8 +7,8 @@ FF30;[{ "Type": "Push", "Operands": ["dword ptr [eax]"] }]
FF31;[{ "Type": "Push", "Operands": ["dword ptr [ecx]"] }] FF31;[{ "Type": "Push", "Operands": ["dword ptr [ecx]"] }]
FF32;[{ "Type": "Push", "Operands": ["dword ptr [edx]"] }] FF32;[{ "Type": "Push", "Operands": ["dword ptr [edx]"] }]
FF33;[{ "Type": "Push", "Operands": ["dword ptr [ebx]"] }] FF33;[{ "Type": "Push", "Operands": ["dword ptr [ebx]"] }]
FF34;[{ "Type": "Push", "Operands": ["dword ptr [esp]"] }] FF3424;[{ "Type": "Push", "Operands": ["dword ptr [esp]"] }]
FF35;[{ "Type": "Push", "Operands": ["dword ptr [ebp]"] }] FF7500;[{ "Type": "Push", "Operands": ["dword ptr [ebp]"] }]
FF36;[{ "Type": "Push", "Operands": ["dword ptr [esi]"] }] FF36;[{ "Type": "Push", "Operands": ["dword ptr [esi]"] }]
FF37;[{ "Type": "Push", "Operands": ["dword ptr [edi]"] }] FF37;[{ "Type": "Push", "Operands": ["dword ptr [edi]"] }]
@ -17,16 +17,16 @@ FF7010;[{ "Type": "Push", "Operands": ["dword ptr [eax+0x10]"] }]
FF7110;[{ "Type": "Push", "Operands": ["dword ptr [ecx+0x10]"] }] FF7110;[{ "Type": "Push", "Operands": ["dword ptr [ecx+0x10]"] }]
FF7210;[{ "Type": "Push", "Operands": ["dword ptr [edx+0x10]"] }] FF7210;[{ "Type": "Push", "Operands": ["dword ptr [edx+0x10]"] }]
FF7310;[{ "Type": "Push", "Operands": ["dword ptr [ebx+0x10]"] }] FF7310;[{ "Type": "Push", "Operands": ["dword ptr [ebx+0x10]"] }]
FF7410;[{ "Type": "Push", "Operands": ["dword ptr [esp+0x10]"] }] FF742410;[{ "Type": "Push", "Operands": ["dword ptr [esp+0x10]"] }]
FF7510;[{ "Type": "Push", "Operands": ["dword ptr [ebp+0x10]"] }] FF7510;[{ "Type": "Push", "Operands": ["dword ptr [ebp+0x10]"] }]
FF7610;[{ "Type": "Push", "Operands": ["dword ptr [esi+0x10]"] }] FF7610;[{ "Type": "Push", "Operands": ["dword ptr [esi+0x10]"] }]
FF7710;[{ "Type": "Push", "Operands": ["dword ptr [edi+0x10]"] }] FF7710;[{ "Type": "Push", "Operands": ["dword ptr [edi+0x10]"] }]
# PUSH r/m32 (opcode FF /6) with SIB byte # PUSH r/m32 (opcode FF /6) with SIB byte
FF34C5;[{ "Type": "Push", "Operands": ["dword ptr [ebp+eax*8]"] }] FF74C500;[{ "Type": "Push", "Operands": ["dword ptr [ebp+eax*8]"] }]
FF34CD;[{ "Type": "Push", "Operands": ["dword ptr [ebp+ecx*8]"] }] FF74CD00;[{ "Type": "Push", "Operands": ["dword ptr [ebp+ecx*8]"] }]
FF34D5;[{ "Type": "Push", "Operands": ["dword ptr [ebp+edx*8]"] }] FF74D500;[{ "Type": "Push", "Operands": ["dword ptr [ebp+edx*8]"] }]
FF34DD;[{ "Type": "Push", "Operands": ["dword ptr [ebp+ebx*8]"] }] FF74DD00;[{ "Type": "Push", "Operands": ["dword ptr [ebp+ebx*8]"] }]
# PUSH r/m32 (opcode FF /6) with direct memory operand # PUSH r/m32 (opcode FF /6) with direct memory operand
FF3578563412;[{ "Type": "Push", "Operands": ["dword ptr [0x12345678]"] }] FF3578563412;[{ "Type": "Push", "Operands": ["dword ptr [0x12345678]"] }]

Can't render this file because it contains an unexpected character in line 6 and column 9.

View File

@ -39,19 +39,19 @@ RawBytes;Instructions
# 16-bit register operations with operand size prefix (0x66) # 16-bit register operations with operand size prefix (0x66)
# SUB r/m16, r16 (opcode 29 with 0x66 prefix) # SUB r/m16, r16 (opcode 29 with 0x66 prefix)
6629D8;[{ "Type": "Sub", "Operands": ["eax", "ebx"] }] 6629D8;[{ "Type": "Sub", "Operands": ["ax", "bx"] }]
# SUB r16, r/m16 (opcode 2B with 0x66 prefix) # SUB r16, r/m16 (opcode 2B with 0x66 prefix)
662BD8;[{ "Type": "Sub", "Operands": ["ebx", "eax"] }] 662BD8;[{ "Type": "Sub", "Operands": ["bx", "ax"] }]
# SUB AX, imm16 (opcode 2D with 0x66 prefix) # SUB AX, imm16 (opcode 2D with 0x66 prefix)
662D3412;[{ "Type": "Sub", "Operands": ["eax", "0x1234"] }] 662D3412;[{ "Type": "Sub", "Operands": ["ax", "0x1234"] }]
# SUB r/m16, imm8 (opcode 83 /5 with 0x66 prefix and sign extension) # SUB r/m16, imm8 (opcode 83 /5 with 0x66 prefix and sign extension)
6683EB42;[{ "Type": "Sub", "Operands": ["ebx", "0x42"] }] 6683EB42;[{ "Type": "Sub", "Operands": ["bx", "0x42"] }]
# SUB r/m16, imm16 (opcode 81 /5 with 0x66 prefix) # SUB r/m16, imm16 (opcode 81 /5 with 0x66 prefix)
6681EB3412;[{ "Type": "Sub", "Operands": ["ebx", "0x1234"] }] 6681EB3412;[{ "Type": "Sub", "Operands": ["bx", "0x1234"] }]
# Additional test cases for more complex addressing modes # Additional test cases for more complex addressing modes
@ -101,7 +101,7 @@ RawBytes;Instructions
81EF78563412;[{ "Type": "Sub", "Operands": ["edi", "0x12345678"] }] 81EF78563412;[{ "Type": "Sub", "Operands": ["edi", "0x12345678"] }]
# SUB r/m32, imm32 (opcode 81 /5) with memory operands # SUB r/m32, imm32 (opcode 81 /5) with memory operands
818D10000000FFFFFFFF;[{ "Type": "Sub", "Operands": ["dword ptr [ebp+0x10]", "0xFFFFFFFF"] }] 81AD10000000FFFFFFFF;[{ "Type": "Sub", "Operands": ["dword ptr [ebp+0x10]", "0xFFFFFFFF"] }]
# Additional tests for SubImmFromRm32SignExtendedHandler # Additional tests for SubImmFromRm32SignExtendedHandler
# SUB r/m32, imm8 (opcode 83 /5) with sign extension # SUB r/m32, imm8 (opcode 83 /5) with sign extension
@ -114,4 +114,4 @@ RawBytes;Instructions
83EFFF;[{ "Type": "Sub", "Operands": ["edi", "0xFFFFFFFF"] }] 83EFFF;[{ "Type": "Sub", "Operands": ["edi", "0xFFFFFFFF"] }]
# SUB r/m32, imm8 (opcode 83 /5) with memory operands and sign extension # SUB r/m32, imm8 (opcode 83 /5) with memory operands and sign extension
838D1000000080;[{ "Type": "Sub", "Operands": ["dword ptr [ebp+0x10]", "0xFFFFFF80"] }] 83AD1000000080;[{ "Type": "Sub", "Operands": ["dword ptr [ebp+0x10]", "0xFFFFFF80"] }]

Can't render this file because it contains an unexpected character in line 6 and column 9.

View File

@ -19,6 +19,6 @@ F7C378563412;[{ "Type": "Test", "Operands": ["ebx", "0x12345678"] }]
85D9;[{ "Type": "Test", "Operands": ["ecx", "ebx"] }] 85D9;[{ "Type": "Test", "Operands": ["ecx", "ebx"] }]
# TEST with memory operands # TEST with memory operands
F6042542;[{ "Type": "Test", "Operands": ["byte ptr [eax]", "0x42"] }] F60042;[{ "Type": "Test", "Operands": ["byte ptr [eax]", "0x42"] }]
F7042578563412;[{ "Type": "Test", "Operands": ["dword ptr [eax]", "0x12345678"] }] F70078563412;[{ "Type": "Test", "Operands": ["dword ptr [eax]", "0x12345678"] }]
85042510;[{ "Type": "Test", "Operands": ["dword ptr [eax+0x10]", "eax"] }] 854510;[{ "Type": "Test", "Operands": ["dword ptr [eax+0x10]", "eax"] }]

Can't render this file because it contains an unexpected character in line 6 and column 11.