diff --git a/X86Disassembler/X86/InstructionDecoder.cs b/X86Disassembler/X86/InstructionDecoder.cs index 8686b7e..3efbec6 100644 --- a/X86Disassembler/X86/InstructionDecoder.cs +++ b/X86Disassembler/X86/InstructionDecoder.cs @@ -353,6 +353,44 @@ public class InstructionDecoder switch (opcode) { + case 0xDF: // FISTP and other FPU instructions + if (_position < _length) + { + byte modRM = _codeBuffer[_position++]; + byte mod = (byte)((modRM & MODRM_MOD_MASK) >> 6); + byte reg = (byte)((modRM & MODRM_REG_MASK) >> 3); + byte rm = (byte)(modRM & MODRM_RM_MASK); + + // FISTP with memory operand + if (reg == 7) // FISTP + { + if (mod == 0 && rm == 5) // Displacement only addressing + { + if (_position + 4 <= _length) + { + uint disp32 = BitConverter.ToUInt32(_codeBuffer, _position); + _position += 4; + operands = $"qword ptr [0x{disp32:X8}]"; + } + } + else + { + // Handle other addressing modes if needed + operands = DecodeModRM(mod, rm, true); + } + } + } + break; + + case 0xA1: // MOV EAX, memory + if (_position + 4 <= _length) + { + uint addr = BitConverter.ToUInt32(_codeBuffer, _position); + _position += 4; + operands = $"eax, [0x{addr:X8}]"; + } + break; + case OPCODE_INT3: // No operands for INT3 break; @@ -511,4 +549,102 @@ public class InstructionDecoder return bytesRead; } + + /// + /// Decodes a ModR/M byte to get the operand string + /// + /// The mod field (2 bits) + /// The r/m field (3 bits) + /// True if the operand is 64-bit + /// The operand string + private string DecodeModRM(byte mod, byte rm, bool is64Bit) + { + string sizePrefix = is64Bit ? "qword" : "dword"; + + switch (mod) + { + case 0: // [reg] or disp32 + if (rm == 5) // disp32 + { + if (_position + 4 <= _length) + { + uint disp32 = BitConverter.ToUInt32(_codeBuffer, _position); + _position += 4; + return $"{sizePrefix} ptr [0x{disp32:X8}]"; + } + return $"{sizePrefix} ptr [???]"; + } + else if (rm == 4) // SIB + { + // Handle SIB byte + if (_position < _length) + { + byte sib = _codeBuffer[_position++]; + // Decode SIB byte (not implemented yet) + return $"{sizePrefix} ptr [SIB]"; + } + return $"{sizePrefix} ptr [???]"; + } + else + { + return $"{sizePrefix} ptr [{RegisterNames32[rm]}]"; + } + + case 1: // [reg + disp8] + if (rm == 4) // SIB + disp8 + { + // Handle SIB byte + if (_position + 1 < _length) + { + byte sib = _codeBuffer[_position++]; + sbyte disp8 = (sbyte)_codeBuffer[_position++]; + // Decode SIB byte (not implemented yet) + return $"{sizePrefix} ptr [SIB+0x{disp8:X2}]"; + } + return $"{sizePrefix} ptr [???]"; + } + else + { + if (_position < _length) + { + sbyte disp8 = (sbyte)_codeBuffer[_position++]; + string dispStr = disp8 < 0 ? $"-0x{-disp8:X2}" : $"+0x{disp8:X2}"; + return $"{sizePrefix} ptr [{RegisterNames32[rm]}{dispStr}]"; + } + return $"{sizePrefix} ptr [{RegisterNames32[rm]}+???]"; + } + + case 2: // [reg + disp32] + if (rm == 4) // SIB + disp32 + { + // Handle SIB byte + if (_position + 4 < _length) + { + byte sib = _codeBuffer[_position++]; + int disp32 = BitConverter.ToInt32(_codeBuffer, _position); + _position += 4; + // Decode SIB byte (not implemented yet) + return $"{sizePrefix} ptr [SIB+0x{disp32:X8}]"; + } + return $"{sizePrefix} ptr [???]"; + } + else + { + if (_position + 4 <= _length) + { + int disp32 = BitConverter.ToInt32(_codeBuffer, _position); + _position += 4; + string dispStr = disp32 < 0 ? $"-0x{-disp32:X8}" : $"+0x{disp32:X8}"; + return $"{sizePrefix} ptr [{RegisterNames32[rm]}{dispStr}]"; + } + return $"{sizePrefix} ptr [{RegisterNames32[rm]}+???]"; + } + + case 3: // reg + return is64Bit ? "mm" + rm : RegisterNames32[rm]; + + default: + return "???"; + } + } }