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

Refactored register operands to separate 8-bit registers into dedicated Register8Operand class

This commit is contained in:
bird_egop 2025-04-16 01:10:33 +03:00
parent 46592d4877
commit e06ea2beb3
12 changed files with 148 additions and 53 deletions

View File

@ -51,7 +51,7 @@ public class AddR8Rm8Handler : InstructionHandler
var (_, reg, _, sourceOperand) = ModRMDecoder.ReadModRM8();
// Create the destination register operand
var destinationOperand = OperandFactory.CreateRegisterOperand(reg, 8);
var destinationOperand = OperandFactory.CreateRegisterOperand8(reg);
// Set the structured operands
instruction.StructuredOperands =

View File

@ -50,9 +50,8 @@ public class AddRm8R8Handler : InstructionHandler
// - The r/m field with mod specifies the destination operand (register or memory)
var (_, reg, _, destinationOperand) = ModRMDecoder.ReadModRM8();
// Create the source register operand
// For high registers, we need to set the IsHighRegister flag
var sourceOperand = OperandFactory.CreateRegisterOperand(reg, 8);
// Create the source register operand using the 8-bit register type
var sourceOperand = OperandFactory.CreateRegisterOperand8(reg);
// Set the structured operands
instruction.StructuredOperands =

View File

@ -56,8 +56,8 @@ public class OrRm8R8Handler : InstructionHandler
// Adjust the operand size to 8-bit
destinationOperand.Size = 8;
// Create the source register operand (8-bit)
var sourceOperand = OperandFactory.CreateRegisterOperand(reg, 8);
// Create the source register operand using the 8-bit register type
var sourceOperand = OperandFactory.CreateRegisterOperand8(reg);
// Set the structured operands
instruction.StructuredOperands =

View File

@ -48,8 +48,8 @@ public class SubR8Rm8Handler : InstructionHandler
// Ensure the source operand has the correct size (8-bit)
sourceOperand.Size = 8;
// Create the destination register operand
var destinationOperand = OperandFactory.CreateRegisterOperand(reg, 8);
// Create the destination register operand using the 8-bit register type
var destinationOperand = OperandFactory.CreateRegisterOperand8(reg);
// Set the structured operands
instruction.StructuredOperands =

View File

@ -43,8 +43,8 @@ public class SubRm8R8Handler : InstructionHandler
// Ensure the destination operand has the correct size (8-bit)
destinationOperand.Size = 8;
// Create the source register operand
var sourceOperand = OperandFactory.CreateRegisterOperand(reg, 8);
// Create the source register operand using the 8-bit register type
var sourceOperand = OperandFactory.CreateRegisterOperand8(reg);
// Set the structured operands
instruction.StructuredOperands =

View File

@ -49,14 +49,14 @@ public class TestRegMem8Handler : InstructionHandler
// Ensure the destination operand has the correct size (8-bit)
destOperand.Size = 8;
// Create the register operand for the reg field (8-bit)
var regOperand = OperandFactory.CreateRegisterOperand(reg, 8);
// Create the register operand for the reg field using the 8-bit register type
var regOperand = OperandFactory.CreateRegisterOperand8(reg);
// Set the structured operands based on addressing mode
if (mod == 3) // Direct register addressing
{
// Create the register operand for the r/m field (8-bit)
var rmOperand = OperandFactory.CreateRegisterOperand(rm, 8);
// Create the register operand for the r/m field using the 8-bit register type
var rmOperand = OperandFactory.CreateRegisterOperand8(rm);
// Set the structured operands
instruction.StructuredOperands =

View File

@ -43,8 +43,8 @@ public class XorR8Rm8Handler : InstructionHandler
// Ensure the source operand has the correct size (8-bit)
sourceOperand.Size = 8;
// Create the destination register operand
var destinationOperand = OperandFactory.CreateRegisterOperand(reg, 8);
// Create the destination register operand using the 8-bit register type
var destinationOperand = OperandFactory.CreateRegisterOperand8(reg);
// Set the structured operands
instruction.StructuredOperands =

View File

@ -43,8 +43,8 @@ public class XorRm8R8Handler : InstructionHandler
// Ensure the destination operand has the correct size (8-bit)
destinationOperand.Size = 8;
// Create the source register operand
var sourceOperand = OperandFactory.CreateRegisterOperand(reg, 8);
// Create the source register operand using the 8-bit register type
var sourceOperand = OperandFactory.CreateRegisterOperand8(reg);
// Set the structured operands
instruction.StructuredOperands =

View File

@ -18,7 +18,6 @@ public class ModRMDecoder
private const byte SIB_BASE_MASK = 0x07; // 00000111b
// Register names for different sizes
private static readonly string[] RegisterNames8 = {"al", "cl", "dl", "bl", "ah", "ch", "dh", "bh"};
private static readonly string[] RegisterNames16 = {"ax", "cx", "dx", "bx", "sp", "bp", "si", "di"};
private static readonly string[] RegisterNames32 = {"eax", "ecx", "edx", "ebx", "esp", "ebp", "esi", "edi"};
@ -65,21 +64,15 @@ public class ModRMDecoder
}
/// <summary>
/// Maps the register index from the ModR/M byte to the RegisterIndex enum value for 8-bit high registers
/// Maps the register index from the ModR/M byte to the RegisterIndex8 enum value
/// </summary>
/// <param name="modRMRegIndex">The register index from the ModR/M byte (0-7)</param>
/// <returns>The corresponding RegisterIndex enum value for 8-bit high registers</returns>
private RegisterIndex MapModRMToHighRegister8Index(int modRMRegIndex)
/// <returns>The corresponding RegisterIndex8 enum value</returns>
private RegisterIndex8 MapModRMToRegisterIndex8(int modRMRegIndex)
{
// For 8-bit high registers (AH, CH, DH, BH), the mapping is different
return modRMRegIndex switch
{
4 => RegisterIndex.A, // AH
5 => RegisterIndex.C, // CH
6 => RegisterIndex.D, // DH
7 => RegisterIndex.B, // BH
_ => MapModRMToRegisterIndex(modRMRegIndex) // Fall back to normal mapping for other indices
};
// The mapping from ModR/M register index to RegisterIndex8 enum is direct:
// 0 -> AL, 1 -> CL, 2 -> DL, 3 -> BL, 4 -> AH, 5 -> CH, 6 -> DH, 7 -> BH
return (RegisterIndex8)modRMRegIndex;
}
/// <summary>
@ -255,7 +248,7 @@ public class ModRMDecoder
/// <returns>A tuple containing the mod, reg, rm fields and the decoded operand</returns>
public (byte mod, RegisterIndex reg, RegisterIndex rm, Operand operand) ReadModRM()
{
return ReadModRMInternal(false, false);
return ReadModRMInternal(false);
}
/// <summary>
@ -264,29 +257,28 @@ public class ModRMDecoder
/// <returns>A tuple containing the mod, reg, rm fields and the decoded operand</returns>
public (byte mod, RegisterIndex reg, RegisterIndex rm, Operand operand) ReadModRM64()
{
return ReadModRMInternal(true, false);
return ReadModRMInternal(true);
}
/// <summary>
/// Reads and decodes a ModR/M byte for 8-bit operands
/// </summary>
/// <returns>A tuple containing the mod, reg, rm fields and the decoded operand</returns>
public (byte mod, RegisterIndex reg, RegisterIndex rm, Operand operand) ReadModRM8()
public (byte mod, RegisterIndex8 reg, RegisterIndex8 rm, Operand operand) ReadModRM8()
{
return ReadModRMInternal(false, true);
return ReadModRM8Internal();
}
/// <summary>
/// Internal implementation for reading and decoding a ModR/M byte
/// Internal implementation for reading and decoding a ModR/M byte for standard 32-bit or 64-bit operands
/// </summary>
/// <param name="is64Bit">True if the operand is 64-bit</param>
/// <param name="is8Bit">True if the operand is 8-bit</param>
/// <returns>A tuple containing the mod, reg, rm fields and the decoded operand</returns>
private (byte mod, RegisterIndex reg, RegisterIndex rm, Operand operand) ReadModRMInternal(bool is64Bit, bool is8Bit)
private (byte mod, RegisterIndex reg, RegisterIndex rm, Operand operand) ReadModRMInternal(bool is64Bit)
{
if (!_decoder.CanReadByte())
{
return (0, RegisterIndex.A, RegisterIndex.A, OperandFactory.CreateRegisterOperand(RegisterIndex.A, is64Bit ? 64 : (is8Bit ? 8 : 32)));
return (0, RegisterIndex.A, RegisterIndex.A, OperandFactory.CreateRegisterOperand(RegisterIndex.A, is64Bit ? 64 : 32));
}
byte modRM = _decoder.ReadByte();
@ -296,21 +288,52 @@ public class ModRMDecoder
byte regIndex = (byte)((modRM & REG_MASK) >> 3);
byte rmIndex = (byte)(modRM & RM_MASK);
// For 8-bit registers with mod=3, we need to check if they are high registers
bool isRmHighRegister = is8Bit && mod == 3 && rmIndex >= 4;
bool isRegHighRegister = is8Bit && regIndex >= 4;
// Map the ModR/M register indices to RegisterIndex enum values
RegisterIndex reg = isRegHighRegister ? MapModRMToHighRegister8Index(regIndex) : MapModRMToRegisterIndex(regIndex);
RegisterIndex rm = isRmHighRegister ? MapModRMToHighRegister8Index(rmIndex) : MapModRMToRegisterIndex(rmIndex);
RegisterIndex reg = MapModRMToRegisterIndex(regIndex);
RegisterIndex rm = MapModRMToRegisterIndex(rmIndex);
// Create the operand based on the mod and rm fields
Operand operand = DecodeModRM(mod, rm, is64Bit);
// For 8-bit operands, set the size to 8
if (is8Bit)
return (mod, reg, rm, operand);
}
/// <summary>
/// Internal implementation for reading and decoding a ModR/M byte for 8-bit operands
/// </summary>
/// <returns>A tuple containing the mod, reg, rm fields and the decoded operand</returns>
private (byte mod, RegisterIndex8 reg, RegisterIndex8 rm, Operand operand) ReadModRM8Internal()
{
operand.Size = 8;
if (!_decoder.CanReadByte())
{
return (0, RegisterIndex8.AL, RegisterIndex8.AL, OperandFactory.CreateRegisterOperand8(RegisterIndex8.AL));
}
byte modRM = _decoder.ReadByte();
// Extract fields from ModR/M byte
byte mod = (byte)((modRM & MOD_MASK) >> 6);
byte regIndex = (byte)((modRM & REG_MASK) >> 3);
byte rmIndex = (byte)(modRM & RM_MASK);
// Map the ModR/M register indices to RegisterIndex8 enum values
RegisterIndex8 reg = MapModRMToRegisterIndex8(regIndex);
RegisterIndex8 rm = MapModRMToRegisterIndex8(rmIndex);
// Create the operand based on the mod and rm fields
Operand operand;
if (mod == 3) // Register operand
{
// For register operands, create an 8-bit register operand
operand = OperandFactory.CreateRegisterOperand8(rm);
}
else // Memory operand
{
// For memory operands, we need to map the RegisterIndex8 to RegisterIndex for base registers
RegisterIndex rmRegIndex = MapRegister8ToBaseRegister(rm);
operand = DecodeModRM(mod, rmRegIndex, false);
operand.Size = 8; // Set size to 8 bits
}
return (mod, reg, rm, operand);
@ -413,17 +436,48 @@ public class ModRMDecoder
/// Gets the register name based on the register index and size
/// </summary>
/// <param name="regIndex">The register index as RegisterIndex enum</param>
/// <param name="size">The register size (8, 16, or 32 bits)</param>
/// <param name="size">The register size (16 or 32 bits)</param>
/// <returns>The register name</returns>
public static string GetRegisterName(RegisterIndex regIndex, int size)
{
return size switch
{
8 => RegisterNames8[(int)regIndex],
16 => RegisterNames16[(int)regIndex],
32 => RegisterNames32[(int)regIndex],
64 => RegisterNames32[(int)regIndex], // For now, reuse 32-bit names for 64-bit
_ => "unknown"
};
}
/// <summary>
/// Gets the 8-bit register name based on the RegisterIndex8 enum value
/// </summary>
/// <param name="regIndex8">The register index as RegisterIndex8 enum</param>
/// <returns>The 8-bit register name</returns>
public static string GetRegisterName(RegisterIndex8 regIndex8)
{
return regIndex8.ToString().ToLower();
}
/// <summary>
/// Maps a RegisterIndex8 enum value to the corresponding RegisterIndex enum value for base registers
/// </summary>
/// <param name="regIndex8">The RegisterIndex8 enum value</param>
/// <returns>The corresponding RegisterIndex enum value</returns>
private RegisterIndex MapRegister8ToBaseRegister(RegisterIndex8 regIndex8)
{
// Map 8-bit register indices to their corresponding 32-bit register indices
return regIndex8 switch
{
RegisterIndex8.AL => RegisterIndex.A,
RegisterIndex8.CL => RegisterIndex.C,
RegisterIndex8.DL => RegisterIndex.D,
RegisterIndex8.BL => RegisterIndex.B,
RegisterIndex8.AH => RegisterIndex.A,
RegisterIndex8.CH => RegisterIndex.C,
RegisterIndex8.DH => RegisterIndex.D,
RegisterIndex8.BH => RegisterIndex.B,
_ => RegisterIndex.A // Default to EAX
};
}
}

View File

@ -16,6 +16,17 @@ public static class OperandFactory
return new RegisterOperand(register, size);
}
/// <summary>
/// Creates an 8-bit register operand using RegisterIndex8 enum
/// </summary>
/// <param name="register8">The 8-bit register</param>
/// <returns>A register operand for 8-bit registers</returns>
public static Register8Operand CreateRegisterOperand8(RegisterIndex8 register8)
{
// Create a new Register8Operand with the 8-bit register
return new Register8Operand(register8);
}
/// <summary>
/// Creates an immediate value operand
/// </summary>

View File

@ -0,0 +1,31 @@
namespace X86Disassembler.X86.Operands;
/// <summary>
/// Represents an 8-bit register operand in an x86 instruction
/// </summary>
public class Register8Operand : Operand
{
/// <summary>
/// Gets or sets the 8-bit register
/// </summary>
public RegisterIndex8 Register { get; set; }
/// <summary>
/// Initializes a new instance of the Register8Operand class
/// </summary>
/// <param name="register">The 8-bit register</param>
public Register8Operand(RegisterIndex8 register)
{
Type = OperandType.Register;
Register = register;
Size = 8; // Always 8 bits for this operand type
}
/// <summary>
/// Returns a string representation of this operand
/// </summary>
public override string ToString()
{
return ModRMDecoder.GetRegisterName(Register);
}
}

View File

@ -1,7 +1,7 @@
namespace X86Disassembler.X86.Operands;
/// <summary>
/// Represents a register operand in an x86 instruction
/// Represents a standard register operand (16/32/64-bit) in an x86 instruction
/// </summary>
public class RegisterOperand : Operand
{
@ -14,7 +14,7 @@ public class RegisterOperand : Operand
/// Initializes a new instance of the RegisterOperand class
/// </summary>
/// <param name="register">The register</param>
/// <param name="size">The size of the register in bits</param>
/// <param name="size">The size of the register in bits (16, 32, or 64)</param>
public RegisterOperand(RegisterIndex register, int size = 32)
{
Type = OperandType.Register;