diff --git a/X86Disassembler/X86/ModRMDecoder.cs b/X86Disassembler/X86/ModRMDecoder.cs index c481bd9..e82b159 100644 --- a/X86Disassembler/X86/ModRMDecoder.cs +++ b/X86Disassembler/X86/ModRMDecoder.cs @@ -8,27 +8,27 @@ public class ModRMDecoder // ModR/M byte masks private const byte MOD_MASK = 0xC0; // 11000000b private const byte REG_MASK = 0x38; // 00111000b - private const byte RM_MASK = 0x07; // 00000111b - + private const byte RM_MASK = 0x07; // 00000111b + // SIB byte masks private const byte SIB_SCALE_MASK = 0xC0; // 11000000b private const byte SIB_INDEX_MASK = 0x38; // 00111000b - private const byte SIB_BASE_MASK = 0x07; // 00000111b - + 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" }; + 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"}; // Buffer containing the code to decode private readonly byte[] _codeBuffer; - + // The instruction decoder that owns this ModRM decoder private readonly InstructionDecoder _decoder; - + // Length of the buffer private readonly int _length; - + /// /// Initializes a new instance of the ModRMDecoder class /// @@ -41,7 +41,7 @@ public class ModRMDecoder _decoder = decoder; _length = length; } - + /// /// Decodes a ModR/M byte to get the operand string /// @@ -51,113 +51,116 @@ public class ModRMDecoder /// The operand string public string DecodeModRM(byte mod, RegisterIndex rmIndex, bool is64Bit) { - string sizePrefix = is64Bit ? "qword" : "dword"; - int position = _decoder.GetPosition(); - + string sizePrefix = is64Bit + ? "qword" + : "dword"; + switch (mod) { case 0: // [reg] or disp32 // Special case: [EBP] is encoded as disp32 with no base register if (rmIndex == RegisterIndex.Di) // disp32 (was EBP/BP) { - if (position + 4 <= _length) + if (_decoder.CanReadUInt()) { - uint disp32 = BitConverter.ToUInt32(_codeBuffer, position); - _decoder.SetPosition(position + 4); + uint disp32 = _decoder.ReadUInt32(); return $"{sizePrefix} ptr [0x{disp32:X8}]"; } + return $"{sizePrefix} ptr [???]"; } + // Special case: [ESP] is encoded with SIB byte - else if (rmIndex == RegisterIndex.Si) // SIB (was ESP/SP) + if (rmIndex == RegisterIndex.Si) // SIB (was ESP/SP) { // Handle SIB byte - if (position < _length) + if (_decoder.CanReadByte()) { - byte sib = _codeBuffer[position]; - _decoder.SetPosition(position + 1); + byte sib = _decoder.ReadByte(); return DecodeSIB(sib, 0, is64Bit); } + return $"{sizePrefix} ptr [???]"; } - else - { - // Regular case: [reg] - return $"{sizePrefix} ptr [{GetRegisterName(rmIndex, 32)}]"; - } - + + // Regular case: [reg] + return $"{sizePrefix} ptr [{GetRegisterName(rmIndex, 32)}]"; + case 1: // [reg + disp8] if (rmIndex == RegisterIndex.Si) // SIB + disp8 (was ESP/SP) { // Handle SIB byte - if (position + 1 < _length) + if (_decoder.CanReadByte()) { - byte sib = _codeBuffer[position]; - sbyte disp8 = (sbyte)_codeBuffer[position + 1]; - _decoder.SetPosition(position + 2); + byte sib = _decoder.ReadByte(); + uint disp8 = (uint) (sbyte) _decoder.ReadByte(); return DecodeSIB(sib, disp8, is64Bit); } + return $"{sizePrefix} ptr [???]"; } else { - if (position < _length) + if (_decoder.CanReadByte()) { - sbyte disp8 = (sbyte)_codeBuffer[position]; - _decoder.SetPosition(position + 1); - + sbyte disp8 = (sbyte) _decoder.ReadByte(); + // Only show displacement if it's not zero if (disp8 == 0) { return $"{sizePrefix} ptr [{GetRegisterName(rmIndex, 32)}]"; } - - string dispStr8 = disp8 < 0 ? $"-0x{-disp8:X2}" : $"+0x{disp8:X2}"; + + string dispStr8 = disp8 < 0 + ? $"-0x{-disp8:X2}" + : $"+0x{disp8:X2}"; return $"{sizePrefix} ptr [{GetRegisterName(rmIndex, 32)}{dispStr8}]"; } + return $"{sizePrefix} ptr [{GetRegisterName(rmIndex, 32)}+???]"; } - + case 2: // [reg + disp32] if (rmIndex == RegisterIndex.Si) // SIB + disp32 (was ESP/SP) { // Handle SIB byte - if (position + 4 < _length) + if (_decoder.CanReadUInt()) { - byte sib = _codeBuffer[position]; - int disp32 = BitConverter.ToInt32(_codeBuffer, position + 1); - _decoder.SetPosition(position + 5); + byte sib = _decoder.ReadByte(); + uint disp32 = _decoder.ReadUInt32(); return DecodeSIB(sib, disp32, is64Bit); } + return $"{sizePrefix} ptr [???]"; } else { - if (position + 4 <= _length) + if (_decoder.CanReadUInt()) { - int disp32 = BitConverter.ToInt32(_codeBuffer, position); - _decoder.SetPosition(position + 4); - + uint disp32 = _decoder.ReadUInt32(); + // Only show displacement if it's not zero if (disp32 == 0) { return $"{sizePrefix} ptr [{GetRegisterName(rmIndex, 32)}]"; } - - string dispStr32 = disp32 < 0 ? $"-0x{-disp32:X8}" : $"+0x{disp32:X8}"; - return $"{sizePrefix} ptr [{GetRegisterName(rmIndex, 32)}{dispStr32}]"; + + return $"{sizePrefix} ptr [{GetRegisterName(rmIndex, 32)}+0x{disp32:X8}]"; } + return $"{sizePrefix} ptr [{GetRegisterName(rmIndex, 32)}+???]"; } - + case 3: // reg (direct register access) - return is64Bit ? $"mm{(int)rmIndex}" : GetRegisterName(rmIndex, 32); - + return is64Bit + ? $"mm{(int) rmIndex}" + : GetRegisterName(rmIndex, 32); + default: return "???"; } } - + /// /// Reads and decodes a ModR/M byte /// @@ -165,26 +168,23 @@ public class ModRMDecoder /// A tuple containing the mod, reg, rm fields and the decoded operand string public (byte mod, RegisterIndex reg, RegisterIndex rm, string operand) ReadModRM(bool is64Bit = false) { - int position = _decoder.GetPosition(); - - if (position >= _length) + if (!_decoder.CanReadByte()) { return (0, RegisterIndex.A, RegisterIndex.A, "???"); } - - byte modRM = _codeBuffer[position]; - _decoder.SetPosition(position + 1); - + + byte modRM = _decoder.ReadByte(); + // Extract fields from ModR/M byte - byte mod = (byte)((modRM & MOD_MASK) >> 6); - RegisterIndex reg = (RegisterIndex)((modRM & REG_MASK) >> 3); - RegisterIndex rm = (RegisterIndex)(modRM & RM_MASK); - + byte mod = (byte) ((modRM & MOD_MASK) >> 6); + RegisterIndex reg = (RegisterIndex) ((modRM & REG_MASK) >> 3); + RegisterIndex rm = (RegisterIndex) (modRM & RM_MASK); + string operand = DecodeModRM(mod, rm, is64Bit); - + return (mod, reg, rm, operand); } - + /// /// Decodes a SIB byte /// @@ -192,63 +192,57 @@ public class ModRMDecoder /// The displacement value /// True if the operand is 64-bit /// The decoded SIB string - private string DecodeSIB(byte sib, int displacement, bool is64Bit) + private string DecodeSIB(byte sib, uint displacement, bool is64Bit) { - string sizePrefix = is64Bit ? "qword" : "dword"; - int position = _decoder.GetPosition(); - + string sizePrefix = is64Bit + ? "qword" + : "dword"; + // Extract fields from SIB byte - byte scale = (byte)((sib & SIB_SCALE_MASK) >> 6); - RegisterIndex index = (RegisterIndex)((sib & SIB_INDEX_MASK) >> 3); - RegisterIndex @base = (RegisterIndex)(sib & SIB_BASE_MASK); - + byte scale = (byte) ((sib & SIB_SCALE_MASK) >> 6); + RegisterIndex index = (RegisterIndex) ((sib & SIB_INDEX_MASK) >> 3); + RegisterIndex @base = (RegisterIndex) (sib & SIB_BASE_MASK); + // Special case: ESP/SP (4) in index field means no index register if (index == RegisterIndex.Si) { // Special case: EBP/BP (5) in base field with no displacement means disp32 only if (@base == RegisterIndex.Di && displacement == 0) { - if (position + 4 <= _length) + if (_decoder.CanReadUInt()) { - uint disp32 = BitConverter.ToUInt32(_codeBuffer, position); - _decoder.SetPosition(position + 4); + uint disp32 = _decoder.ReadUInt32(); return $"{sizePrefix} ptr [0x{disp32:X8}]"; } + return $"{sizePrefix} ptr [???]"; } - else + + // Base register only + // Only show displacement if it's not zero + if (displacement == 0) { - // Base register only - // Only show displacement if it's not zero - if (displacement == 0) - { - return $"{sizePrefix} ptr [{GetRegisterName(@base, 32)}]"; - } - - string baseDispStr = displacement < 0 ? - $"-0x{-displacement:X}" : - $"+0x{displacement:X}"; - return $"{sizePrefix} ptr [{GetRegisterName(@base, 32)}{baseDispStr}]"; + return $"{sizePrefix} ptr [{GetRegisterName(@base, 32)}]"; } + + return $"{sizePrefix} ptr [{GetRegisterName(@base, 32)}+0x{displacement:X}]"; } - + // Normal case with base and index registers int scaleFactor = 1 << scale; // 1, 2, 4, or 8 - + // Only include the scale factor if it's not 1 - string scaleStr = scaleFactor > 1 ? $"*{scaleFactor}" : ""; - + string scaleStr = scaleFactor > 1 + ? $"*{scaleFactor}" + : ""; + // Only show displacement if it's not zero if (displacement == 0) { return $"{sizePrefix} ptr [{GetRegisterName(@base, 32)}+{GetRegisterName(index, 32)}{scaleStr}]"; } - - string indexDispStr = displacement < 0 ? - $"-0x{-displacement:X}" : - $"+0x{displacement:X}"; - - return $"{sizePrefix} ptr [{GetRegisterName(@base, 32)}+{GetRegisterName(index, 32)}{scaleStr}{indexDispStr}]"; + + return $"{sizePrefix} ptr [{GetRegisterName(@base, 32)}+{GetRegisterName(index, 32)}{scaleStr}+0x{displacement:X}]"; } /// @@ -260,8 +254,8 @@ public class ModRMDecoder public static string GetRegisterName(RegisterIndex regIndex, int size) { // Convert RegisterIndex to raw index for array access - int index = (int)regIndex; - + int index = (int) regIndex; + return size switch { 8 => RegisterNames8[index], @@ -270,4 +264,4 @@ public class ModRMDecoder _ => RegisterNames32[index] // Default to 32-bit registers }; } -} +} \ No newline at end of file