namespace X86Disassembler.X86.Operands;
///
/// Represents a far pointer memory operand (m16:32) in an x86 instruction
///
public class FarPointerOperand : MemoryOperand
{
///
/// Gets the base register (if any)
///
public RegisterIndex? BaseRegister { get; }
///
/// Gets the index register (if any)
///
public RegisterIndex? IndexRegister { get; }
///
/// Gets the scale factor (if using an index register)
///
public int Scale { get; }
///
/// Gets the displacement value (if any)
///
public long Displacement { get; }
///
/// Gets the direct memory address (if any)
///
public long? Address { get; }
///
/// Initializes a new instance of the FarPointerOperand class for base register memory operands
///
/// The base register
/// Optional segment override
public FarPointerOperand(RegisterIndex baseRegister, string? segmentOverride = null)
: base(48, segmentOverride)
{
Type = OperandType.MemoryBaseReg;
BaseRegister = baseRegister;
IndexRegister = null;
Scale = 1;
Displacement = 0;
Address = null;
}
///
/// Initializes a new instance of the FarPointerOperand class for displacement memory operands
///
/// The base register
/// The displacement value
/// Optional segment override
public FarPointerOperand(RegisterIndex baseRegister, long displacement, string? segmentOverride = null)
: base(48, segmentOverride)
{
Type = OperandType.MemoryBaseRegPlusOffset;
BaseRegister = baseRegister;
IndexRegister = null;
Scale = 1;
Displacement = displacement;
Address = null;
}
///
/// Initializes a new instance of the FarPointerOperand class for scaled index memory operands
///
/// The index register
/// The scale factor
/// The optional base register
/// The displacement value
/// Optional segment override
public FarPointerOperand(RegisterIndex indexRegister, int scale, RegisterIndex? baseRegister = null, long displacement = 0, string? segmentOverride = null)
: base(48, segmentOverride)
{
Type = OperandType.MemoryIndexed;
BaseRegister = baseRegister;
IndexRegister = indexRegister;
Scale = scale;
Displacement = displacement;
Address = null;
}
///
/// Initializes a new instance of the FarPointerOperand class for direct memory operands
///
/// The memory address
/// Optional segment override
public FarPointerOperand(long address, string? segmentOverride = null)
: base(48, segmentOverride)
{
Type = OperandType.MemoryDirect;
BaseRegister = null;
IndexRegister = null;
Scale = 1;
Displacement = 0;
Address = address;
}
///
/// Creates a FarPointerOperand from an existing memory operand
///
/// The memory operand to convert
/// A new FarPointerOperand with the same properties
public static FarPointerOperand FromMemoryOperand(MemoryOperand memoryOperand)
{
// Create the appropriate type of FarPointerOperand based on the source operand type
if (memoryOperand is BaseRegisterMemoryOperand baseRegMemOperand)
{
return new FarPointerOperand(baseRegMemOperand.BaseRegister, memoryOperand.SegmentOverride);
}
else if (memoryOperand is DisplacementMemoryOperand dispMemOperand)
{
return new FarPointerOperand(dispMemOperand.BaseRegister, dispMemOperand.Displacement, memoryOperand.SegmentOverride);
}
else if (memoryOperand is DirectMemoryOperand directMemOperand)
{
return new FarPointerOperand(directMemOperand.Address, memoryOperand.SegmentOverride);
}
else if (memoryOperand is ScaledIndexMemoryOperand sibMemOperand)
{
return new FarPointerOperand(sibMemOperand.IndexRegister, sibMemOperand.Scale, sibMemOperand.BaseRegister, sibMemOperand.Displacement, memoryOperand.SegmentOverride);
}
// Default case - shouldn't happen if all memory operand types are handled above
throw new System.ArgumentException("Unsupported memory operand type", nameof(memoryOperand));
}
///
/// Returns a string representation of this operand
///
public override string ToString()
{
string prefix = "fword ptr ";
// Add segment override if present
if (SegmentOverride != null)
{
prefix = $"{prefix}{SegmentOverride}:";
}
// Format based on operand type
return Type switch
{
OperandType.MemoryBaseReg => $"{prefix}[{RegisterMapper.GetRegisterName(BaseRegister!.Value, 32)}]",
OperandType.MemoryBaseRegPlusOffset => $"{prefix}[{RegisterMapper.GetRegisterName(BaseRegister!.Value, 32)}+0x{Displacement:X}]",
OperandType.MemoryDirect => $"{prefix}[0x{Address!.Value:X}]",
OperandType.MemoryIndexed => FormatSIBString(prefix),
_ => $"{prefix}[unknown]"
};
}
///
/// Formats the string representation for SIB addressing mode
///
private string FormatSIBString(string prefix)
{
string result = prefix + "[";
// Add base register if present
if (BaseRegister.HasValue)
{
result += RegisterMapper.GetRegisterName(BaseRegister.Value, 32);
}
// Add index register with scale if present
if (IndexRegister.HasValue)
{
// Add + if we already have a base register
if (BaseRegister.HasValue)
{
result += "+";
}
result += RegisterMapper.GetRegisterName(IndexRegister.Value, 32);
// Add scale if not 1
if (Scale > 1)
{
result += $"*{Scale}";
}
}
// Add displacement if non-zero
if (Displacement != 0)
{
// Format as signed value
if (Displacement > 0)
{
result += $"+0x{Displacement:X}";
}
else
{
result += $"-0x{-Displacement:X}";
}
}
result += "]";
return result;
}
}