/// <summary> /// Returns a string representation of a memory address. /// </summary> /// <param name="memoryOperand">Memory address operand to be converted to a string.</param> /// <param name="prefixes">Current instruction prefixes in effect.</param> /// <returns>String representation of the memory address.</returns> public static string Format(CodeOperand memoryOperand, PrefixState prefixes) { string prefix = GetSizePrefix(memoryOperand.OperandSize); if (memoryOperand.EffectiveAddress == CodeMemoryBase.SIB) { return(prefix + FormatSib(memoryOperand)); } string register; effectiveAddresses.TryGetValue(memoryOperand.EffectiveAddress, out register); string segmentOverride = FormatSegment(prefixes); if (register == null) { return($"{prefix} {segmentOverride}[{memoryOperand.ImmediateValue:X4}]"); } else if (memoryOperand.ImmediateValue == 0) { return($"{prefix} {segmentOverride}[{register}]"); } else { return($"{prefix} {segmentOverride}[{register}+{memoryOperand.ImmediateValue:X4}]"); } }
/// <summary> /// Rebuilds the displayed content. /// </summary> /// <param name="operand">Operand to display.</param> /// <param name="format">Formatting information.</param> /// <returns>FrameworkElement to display as content.</returns> private FrameworkElement BuildContent(CodeOperand operand, IDebuggerTextSettings format) { switch (operand.Type) { case CodeOperandType.Immediate: return(BuildImmediateContent(operand.ImmediateValue)); case CodeOperandType.Register: return(BuildRegisterContent(operand.RegisterValue)); case CodeOperandType.MemoryAddress: return(BuildAddress16Content(operand)); case CodeOperandType.RelativeJumpAddress: return(BuildJumpTargetContent((uint)(this.Instruction.EIP + this.Instruction.Length + (int)operand.ImmediateValue))); } return(null); }
private static string FormatSib(CodeOperand sibOperand) { sibRegisters.TryGetValue(sibOperand.Base, out var baseRegister); var scaleIndex = FormatScaleIndex(sibOperand.Scale, sibOperand.Index); if (baseRegister == null) { return($"[{sibOperand.ImmediateValue:X8}]{scaleIndex}"); } else { if (sibOperand.ImmediateValue == 0) { return($"[{baseRegister}]{scaleIndex}"); } else { return($"[{baseRegister}+{sibOperand.ImmediateValue:X8}]{scaleIndex}"); } } }
private static DecodedOperands Decode(OpcodeInfo opcode, ReadOnlySpan <byte> rawData, PrefixState prefixes, out int length) { var reader = new OperandReader(rawData); var operands = new DecodedOperands(); length = 0; if (opcode.Operands.Count == 0) { return(operands); } if (opcode.ModRmInfo != ModRmInfo.None) { byte modRmByte = reader.ReadByte(); int mod = (modRmByte & 0xC0) >> 6; int rm = modRmByte & 0x07; for (int i = 0; i < opcode.Operands.Count; i++) { var type = opcode.Operands[i]; if (type == OperandType.RegisterOrMemoryByte) { operands.SetOperand(i, DecodeRmbw(mod, rm, true, prefixes, ref reader)); } else if (IsPointerOperand(type)) { var operand = DecodeRmbw(mod, rm, false, prefixes, ref reader); if (type == OperandType.EffectiveAddress) { operand.Type = CodeOperandType.EffectiveAddress; } else if (type == OperandType.FullLinearAddress) { operand.Type = CodeOperandType.FullLinearAddress; } else if (type == OperandType.RegisterOrMemoryWordNearPointer) { operand.Type = CodeOperandType.AbsoluteJumpAddress; } else if (type == OperandType.IndirectFarPointer) { operand.Type = CodeOperandType.IndirectFarMemoryAddress; } else if (type == OperandType.MemoryInt16 || type == OperandType.RegisterOrMemory16) { operand.OperandSize = CodeOperandSize.Word; } else if (type == OperandType.MemoryInt32 || type == OperandType.RegisterOrMemory32) { operand.OperandSize = CodeOperandSize.DoubleWord; } else if (type == OperandType.MemoryInt64) { operand.OperandSize = CodeOperandSize.QuadWord; } else if (type == OperandType.MemoryFloat32) { operand.OperandSize = CodeOperandSize.Single; } else if (type == OperandType.MemoryFloat64) { operand.OperandSize = CodeOperandSize.Double; } else if (type == OperandType.MemoryFloat80) { operand.OperandSize = CodeOperandSize.LongDouble; } operands.SetOperand(i, operand); } } if (opcode.ModRmInfo == ModRmInfo.All) { int reg = (modRmByte & 0x38) >> 3; for (int i = 0; i < opcode.Operands.Count; i++) { var type = opcode.Operands[i]; if (type == OperandType.RegisterByte) { operands.SetOperand(i, DecodeRb(reg)); } else if (type == OperandType.RegisterWord) { operands.SetOperand(i, DecodeRw(reg, prefixes)); } else if (type == OperandType.SegmentRegister) { operands.SetOperand(i, DecodeSreg(reg)); } } } } for (int i = 0; i < opcode.Operands.Count; i++) { var type = opcode.Operands[i]; if (IsKnownRegister(type)) { operands.SetOperand(i, new CodeOperand(DecodeKnownRegister(type, (prefixes & PrefixState.OperandSize) != 0))); } else if (type == OperandType.ImmediateByte) { operands.SetOperand(i, new CodeOperand(CodeOperandType.Immediate, reader.ReadByte(), CodeOperandSize.Byte)); } else if (type == OperandType.ImmediateByteExtend || type == OperandType.ImmediateRelativeByte) { var operand = new CodeOperand(CodeOperandType.Immediate, (uint)(int)reader.ReadSByte(), GetOperandSize(false, prefixes)); if (type == OperandType.ImmediateRelativeByte) { operand.Type = CodeOperandType.RelativeJumpAddress; } operands.SetOperand(i, operand); } else if (type == OperandType.ImmediateInt16) { operands.SetOperand(i, new CodeOperand(CodeOperandType.Immediate, reader.ReadUInt16(), CodeOperandSize.Word)); } else if (type == OperandType.ImmediateInt32) { operands.SetOperand(i, new CodeOperand(CodeOperandType.Immediate, reader.ReadUInt32(), CodeOperandSize.DoubleWord)); } else if (type == OperandType.ImmediateWord) { uint value; if ((prefixes & PrefixState.OperandSize) == 0) { value = reader.ReadUInt16(); } else { value = reader.ReadUInt32(); } operands.SetOperand(i, new CodeOperand(CodeOperandType.Immediate, value, GetOperandSize(false, prefixes))); } else if (type == OperandType.ImmediateRelativeWord) { uint value; if ((prefixes & PrefixState.OperandSize) == 0) { value = (uint)(int)reader.ReadInt16(); } else { value = reader.ReadUInt32(); } operands.SetOperand(i, new CodeOperand(CodeOperandType.RelativeJumpAddress, value, GetOperandSize(false, prefixes))); } else if (type == OperandType.MemoryOffsetByte || type == OperandType.MemoryOffsetWord) { uint value; if ((prefixes & PrefixState.AddressSize) == 0) { value = (uint)(int)reader.ReadInt16(); } else { value = reader.ReadUInt32(); } operands.SetOperand(i, new CodeOperand(CodeMemoryBase.DisplacementOnly, value, GetOperandSize(type == OperandType.MemoryOffsetByte, prefixes))); } else if (type == OperandType.ImmediateFarPointer) { uint value; if ((prefixes & PrefixState.AddressSize) == 0) { value = reader.ReadUInt16(); } else { value = reader.ReadUInt32(); } ushort segment = reader.ReadUInt16(); operands.SetOperand(i, CodeOperand.FarPointer(segment, value)); } } length = reader.Position; return(operands); }
private FrameworkElement BuildAddress16Content(CodeOperand operand) { bool includeDisplacement = true; var textBlock = new TextBlock(); var prefixes = this.Instruction.Prefixes; if (operand.OperandSize == CodeOperandSize.Byte) { textBlock.Inlines.Add("byte ptr "); } else if (operand.OperandSize == CodeOperandSize.Word && (prefixes & PrefixState.OperandSize) == 0) { textBlock.Inlines.Add("word ptr "); } else { textBlock.Inlines.Add("dword ptr "); } var segmentOverride = GetSegmentPrefix(prefixes); if (segmentOverride != null) { textBlock.Inlines.Add(NewRegisterRun(segmentOverride)); textBlock.Inlines.Add(":"); } textBlock.Inlines.Add("["); switch (operand.EffectiveAddress) { case CodeMemoryBase.DisplacementOnly: textBlock.Inlines.Add(NewImmediateRun(operand.ImmediateValue.ToString("X4"))); includeDisplacement = false; break; case CodeMemoryBase.BX_plus_SI: textBlock.Inlines.Add(NewRegisterRun("bx")); textBlock.Inlines.Add("+"); textBlock.Inlines.Add(NewRegisterRun("si")); break; case CodeMemoryBase.BX_plus_DI: textBlock.Inlines.Add(NewRegisterRun("bx")); textBlock.Inlines.Add("+"); textBlock.Inlines.Add(NewRegisterRun("di")); break; case CodeMemoryBase.BP_plus_SI: textBlock.Inlines.Add(NewRegisterRun("bp")); textBlock.Inlines.Add("+"); textBlock.Inlines.Add(NewRegisterRun("si")); break; case CodeMemoryBase.BP_plus_DI: textBlock.Inlines.Add(NewRegisterRun("bp")); textBlock.Inlines.Add("+"); textBlock.Inlines.Add(NewRegisterRun("di")); break; case CodeMemoryBase.SI: textBlock.Inlines.Add(NewRegisterRun("si")); break; case CodeMemoryBase.DI: textBlock.Inlines.Add(NewRegisterRun("di")); break; case CodeMemoryBase.BX: textBlock.Inlines.Add(NewRegisterRun("bx")); break; case CodeMemoryBase.BP: textBlock.Inlines.Add(NewRegisterRun("bp")); break; } if (includeDisplacement && operand.ImmediateValue != 0) { int offset = (short)(ushort)operand.ImmediateValue; textBlock.Inlines.Add(offset >= 0 ? "+" : "-"); textBlock.Inlines.Add(NewDisplacementRun(Math.Abs(offset).ToString())); } textBlock.Inlines.Add("]"); return(textBlock); }