mirror of
https://github.com/sampletext32/ParkanPlayground.git
synced 2025-06-20 08:18:36 +03:00
Fix x86 disassembler issues with direct memory addressing and immediate value formatting
This commit is contained in:
@ -29,6 +29,6 @@ public class BaseRegisterMemoryOperand : MemoryOperand
|
||||
public override string ToString()
|
||||
{
|
||||
var registerName = ModRMDecoder.GetRegisterName(BaseRegister, 32);
|
||||
return $"{GetSegmentPrefix()}[{registerName}]";
|
||||
return $"{GetSegmentPrefix()}{GetSizePrefix()}[{registerName}]";
|
||||
}
|
||||
}
|
||||
|
@ -28,6 +28,6 @@ public class DirectMemoryOperand : MemoryOperand
|
||||
/// </summary>
|
||||
public override string ToString()
|
||||
{
|
||||
return $"{GetSegmentPrefix()}[0x{Address:X}]";
|
||||
return $"{GetSegmentPrefix()}{GetSizePrefix()}[0x{Address:X}]";
|
||||
}
|
||||
}
|
||||
|
@ -37,6 +37,12 @@ public class DisplacementMemoryOperand : MemoryOperand
|
||||
{
|
||||
string sign = Displacement >= 0 ? "+" : "";
|
||||
var registerName = ModRMDecoder.GetRegisterName(BaseRegister, 32);
|
||||
return $"{GetSegmentPrefix()}[{registerName}{sign}0x{Math.Abs(Displacement):X}]";
|
||||
|
||||
// Format small displacements (< 256) with at least 2 digits
|
||||
string formattedDisplacement = Math.Abs(Displacement) < 256
|
||||
? $"0x{Math.Abs(Displacement):X2}"
|
||||
: $"0x{Math.Abs(Displacement):X}";
|
||||
|
||||
return $"{GetSegmentPrefix()}{GetSizePrefix()}[{registerName}{sign}{formattedDisplacement}]";
|
||||
}
|
||||
}
|
||||
|
@ -8,7 +8,7 @@ public class ImmediateOperand : Operand
|
||||
/// <summary>
|
||||
/// Gets or sets the immediate value
|
||||
/// </summary>
|
||||
public long Value { get; set; }
|
||||
public ulong Value { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the ImmediateOperand class
|
||||
@ -18,7 +18,17 @@ public class ImmediateOperand : Operand
|
||||
public ImmediateOperand(long value, int size = 32)
|
||||
{
|
||||
Type = OperandType.ImmediateValue;
|
||||
Value = value;
|
||||
|
||||
// For negative values in 32-bit mode, convert to unsigned 32-bit representation
|
||||
if (value < 0 && size == 32)
|
||||
{
|
||||
Value = (ulong)(uint)value; // Sign-extend to 32 bits, then store as unsigned
|
||||
}
|
||||
else
|
||||
{
|
||||
Value = (ulong)value;
|
||||
}
|
||||
|
||||
Size = size;
|
||||
}
|
||||
|
||||
@ -27,13 +37,51 @@ public class ImmediateOperand : Operand
|
||||
/// </summary>
|
||||
public override string ToString()
|
||||
{
|
||||
// For negative values, ensure we show the full 32-bit representation
|
||||
if (Value < 0 && Size == 32)
|
||||
// Mask the value based on its size
|
||||
ulong maskedValue = Size switch
|
||||
{
|
||||
return $"0x{Value & 0xFFFFFFFF:X8}";
|
||||
8 => Value & 0xFF,
|
||||
16 => Value & 0xFFFF,
|
||||
32 => Value & 0xFFFFFFFF,
|
||||
_ => Value
|
||||
};
|
||||
|
||||
// For 8-bit immediate values, always use at least 2 digits
|
||||
if (Size == 8)
|
||||
{
|
||||
return $"0x{maskedValue:X2}";
|
||||
}
|
||||
|
||||
// For positive values or other sizes, show the regular representation
|
||||
return $"0x{Value:X}";
|
||||
// For 16-bit immediate values, format depends on the value
|
||||
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}";
|
||||
}
|
||||
}
|
||||
|
@ -27,6 +27,31 @@ public abstract class MemoryOperand : Operand
|
||||
/// <returns>The segment prefix string</returns>
|
||||
protected string GetSegmentPrefix()
|
||||
{
|
||||
return SegmentOverride != null ? $"{SegmentOverride}:" : "";
|
||||
// Format changed to match expected test output: "dword ptr es:[ebp+0x10]" instead of "es:dword ptr [ebp+0x10]"
|
||||
return "";
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the size prefix string for display (e.g., "byte ptr", "word ptr", "dword ptr")
|
||||
/// </summary>
|
||||
/// <returns>The size prefix string</returns>
|
||||
protected string GetSizePrefix()
|
||||
{
|
||||
string sizePrefix = Size switch
|
||||
{
|
||||
8 => "byte ptr ",
|
||||
16 => "word ptr ",
|
||||
32 => "dword ptr ",
|
||||
64 => "qword ptr ",
|
||||
_ => ""
|
||||
};
|
||||
|
||||
// If we have a segment override, include it in the format "dword ptr es:[reg]"
|
||||
if (SegmentOverride != null)
|
||||
{
|
||||
return $"{sizePrefix}{SegmentOverride}:";
|
||||
}
|
||||
|
||||
return sizePrefix;
|
||||
}
|
||||
}
|
||||
|
@ -22,7 +22,7 @@ public static class OperandFactory
|
||||
/// <param name="value">The immediate value</param>
|
||||
/// <param name="size">The size of the value in bits</param>
|
||||
/// <returns>An immediate value operand</returns>
|
||||
public static ImmediateOperand CreateImmediateOperand(long value, int size = 32)
|
||||
public static ImmediateOperand CreateImmediateOperand(uint value, int size = 32)
|
||||
{
|
||||
return new ImmediateOperand(value, size);
|
||||
}
|
||||
@ -86,7 +86,7 @@ public static class OperandFactory
|
||||
/// <param name="targetAddress">The target address</param>
|
||||
/// <param name="size">The size of the offset in bits (8 or 32)</param>
|
||||
/// <returns>A relative offset operand</returns>
|
||||
public static RelativeOffsetOperand CreateRelativeOffsetOperand(ulong targetAddress, int size = 32)
|
||||
public static RelativeOffsetOperand CreateRelativeOffsetOperand(uint targetAddress, int size = 32)
|
||||
{
|
||||
return new RelativeOffsetOperand(targetAddress, size);
|
||||
}
|
||||
|
@ -8,14 +8,14 @@ public class RelativeOffsetOperand : Operand
|
||||
/// <summary>
|
||||
/// Gets or sets the target address
|
||||
/// </summary>
|
||||
public ulong TargetAddress { get; set; }
|
||||
public uint TargetAddress { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the RelativeOffsetOperand class
|
||||
/// </summary>
|
||||
/// <param name="targetAddress">The target address</param>
|
||||
/// <param name="size">The size of the offset in bits (8 or 32)</param>
|
||||
public RelativeOffsetOperand(ulong targetAddress, int size = 32)
|
||||
public RelativeOffsetOperand(uint targetAddress, int size = 32)
|
||||
{
|
||||
Type = OperandType.RelativeOffset;
|
||||
TargetAddress = targetAddress;
|
||||
|
@ -50,8 +50,8 @@ public class ScaledIndexMemoryOperand : MemoryOperand
|
||||
/// </summary>
|
||||
public override string ToString()
|
||||
{
|
||||
string baseRegPart = BaseRegister != null ? $"{BaseRegister}+" : "";
|
||||
string indexPart = $"{IndexRegister}*{Scale}";
|
||||
string baseRegPart = BaseRegister != null ? $"{ModRMDecoder.GetRegisterName(BaseRegister.Value, 32)}+" : "";
|
||||
string indexPart = $"{ModRMDecoder.GetRegisterName(IndexRegister, 32)}*{Scale}";
|
||||
string dispPart = "";
|
||||
|
||||
if (Displacement != 0)
|
||||
@ -60,6 +60,6 @@ public class ScaledIndexMemoryOperand : MemoryOperand
|
||||
dispPart = $"{sign}0x{Math.Abs(Displacement):X}";
|
||||
}
|
||||
|
||||
return $"{GetSegmentPrefix()}[{baseRegPart}{indexPart}{dispPart}]";
|
||||
return $"{GetSegmentPrefix()}{GetSizePrefix()}[{baseRegPart}{indexPart}{dispPart}]";
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user