namespace X86Disassembler.X86; /// /// Handles decoding of instruction prefixes /// public class PrefixDecoder { // Prefix flags private bool _operandSizePrefix; private bool _addressSizePrefix; private bool _segmentOverridePrefix; private bool _lockPrefix; private bool _repPrefix; private bool _repnePrefix; private string _segmentOverride = string.Empty; /// /// Initializes a new instance of the PrefixDecoder class /// public PrefixDecoder() { Reset(); } /// /// Resets all prefix flags /// public void Reset() { _operandSizePrefix = false; _addressSizePrefix = false; _segmentOverridePrefix = false; _lockPrefix = false; _repPrefix = false; _repnePrefix = false; _segmentOverride = string.Empty; } /// /// Decodes a prefix byte /// /// The prefix byte /// True if the byte was a prefix, false otherwise public bool DecodePrefix(byte prefix) { if (prefix == 0x66) // Operand size prefix { _operandSizePrefix = true; return true; } else if (prefix == 0x67) // Address size prefix { _addressSizePrefix = true; return true; } else if ((prefix >= 0x26 && prefix <= 0x3E && (prefix & 0x7) == 0x6) || prefix == 0x64 || prefix == 0x65) // Segment override prefix { _segmentOverridePrefix = true; switch (prefix) { case 0x26: _segmentOverride = "es"; break; case 0x2E: _segmentOverride = "cs"; break; case 0x36: _segmentOverride = "ss"; break; case 0x3E: _segmentOverride = "ds"; break; case 0x64: _segmentOverride = "fs"; break; case 0x65: _segmentOverride = "gs"; break; } return true; } else if (prefix == 0xF0) // LOCK prefix { _lockPrefix = true; return true; } else if (prefix == 0xF3) // REP prefix { _repPrefix = true; return true; } else if (prefix == 0xF2) // REPNE prefix { _repnePrefix = true; return true; } return false; } /// /// Checks if the operand size prefix is present /// /// True if the operand size prefix is present public bool HasOperandSizePrefix() { return _operandSizePrefix; } /// /// Checks if the address size prefix is present /// /// True if the address size prefix is present public bool HasAddressSizePrefix() { return _addressSizePrefix; } /// /// Checks if a segment override prefix is present /// /// True if a segment override prefix is present public bool HasSegmentOverridePrefix() { return _segmentOverridePrefix; } /// /// Gets the segment override prefix /// /// The segment override prefix, or an empty string if none is present public string GetSegmentOverride() { return _segmentOverride; } /// /// Checks if the LOCK prefix is present /// /// True if the LOCK prefix is present public bool HasLockPrefix() { return _lockPrefix; } /// /// Checks if the REP prefix is present /// /// True if the REP prefix is present public bool HasRepPrefix() { return _repPrefix; } /// /// Checks if the REPNE prefix is present /// /// True if the REPNE prefix is present public bool HasRepnePrefix() { return _repnePrefix; } /// /// Applies the segment override prefix to the operands string if applicable /// /// The operands string /// The operands string with segment override applied public string ApplySegmentOverride(string operands) { if (_segmentOverridePrefix && !string.IsNullOrEmpty(operands)) { // If the instruction has memory operands, add the segment override if (operands.Contains("[")) { // Replace the first '[' with the segment override return operands.Replace("[", $"{_segmentOverride}:[" ); } } return operands; } /// /// Applies the REP/REPNE prefix to the mnemonic if applicable /// /// The mnemonic /// The mnemonic with REP/REPNE prefix applied public string ApplyRepPrefix(string mnemonic) { if (_repnePrefix && !mnemonic.StartsWith("repne")) { return $"repne {mnemonic}"; } else if (_repPrefix && !mnemonic.StartsWith("rep")) { return $"rep {mnemonic}"; } return mnemonic; } }