/// <summary> /// Extracts operand information from an instruction /// </summary> /// <param name="inx">The source instruction</param> static AsmOperandInfo[] DistillOperands(this Instruction inx, MethodAsmBody asm) { var args = new AsmOperandInfo[inx.OpCount]; for (byte j = 0; j < inx.OpCount; j++) { var operandKind = inx.GetOpKind(j); var imm = inx.ImmediateInfo(j); var reg = operandKind == AsmOpKind.Register ? inx.RegisterInfo(j) : null; var mem = operandKind.IsMemory() ? inx.MemoryInfo(j) : null; var branch = operandKind.IsBranch() ? inx.BranchInfo(j, asm.StartAddress) : null; args[j] = new AsmOperandInfo(j, operandKind.ToString(), imm, mem, reg, branch); } return(args); }
public static string Format(this MethodAsmBody src) { if (src.Instructions.Length == 0) { return(string.Empty); } Span <byte> nativeData = src.NativeBlocks.Single().Data; var baseAddress = src.Instructions[0].IP; var formatter = new MasmFormatter(FormatOptions); var sb = sbuild(); var writer = new StringWriter(sb); var output = new AsmFormatterOutput(writer, baseAddress); for (var j = 0; j < src.Instructions.Length; j++) { ref var i = ref src.Instructions[j]; var startAddress = i.IP; var relAddress = (int)(startAddress - baseAddress); var relAddressFmt = relAddress.ToString("x4"); sb.Append($"{relAddressFmt}h "); formatter.Format(ref i, output); var padding = " "; var encoding = i.Encoding == EncodingKind.Legacy ? string.Empty : $" ({i.Encoding} encoded)"; var encoded = embrace(nativeData.Slice(relAddress, i.ByteLength).FormatHex(false, ',')); sb.Append($"{padding}; opcode := {i.Code}{encoding} | encoded := {encoded} ({i.ByteLength} bytes)"); if (j != src.Instructions.Length - 1) { sb.AppendLine(); } }