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