diff --git a/Source/Mosa.Tool.Debugger/Views/InstructionView.cs b/Source/Mosa.Tool.Debugger/Views/InstructionView.cs index 10b7c73c8a..112a44176d 100644 --- a/Source/Mosa.Tool.Debugger/Views/InstructionView.cs +++ b/Source/Mosa.Tool.Debugger/Views/InstructionView.cs @@ -57,19 +57,20 @@ private void UpdateDisplay(ulong address, byte[] memory) { instructions.Clear(); - var disassembler = new Disassembler("x86"); - disassembler.SetMemory(memory, address); + var disassembler = new Disassembler("x86", memory, address); + var instruction = disassembler.DecodeNext(); - foreach (var instruction in disassembler.Decode()) + while (instruction != null) { var entry = new InstructionEntry() { IP = instruction.Address, - Length = instruction.Length, + Length = (int)instruction.Length, Instruction = instruction.Instruction.ToString() }; instructions.Add(entry); + instruction = disassembler.DecodeNext(); } } diff --git a/Source/Mosa.Tool.Debugger/Views/MethodView.cs b/Source/Mosa.Tool.Debugger/Views/MethodView.cs index cc88d84e29..dc705c87f7 100644 --- a/Source/Mosa.Tool.Debugger/Views/MethodView.cs +++ b/Source/Mosa.Tool.Debugger/Views/MethodView.cs @@ -148,10 +148,10 @@ private void UpdateDisplay(ulong address, byte[] memory) { instructions.Clear(); - var disassembler = new Disassembler("x86"); - disassembler.SetMemory(memory, address); + var disassembler = new Disassembler("x86", memory, address); + var instruction = disassembler.DecodeNext(); - foreach (var instruction in disassembler.Decode()) + while (instruction != null) { var addr = MainForm.ParseAddress(instruction.Instruction); @@ -160,12 +160,13 @@ private void UpdateDisplay(ulong address, byte[] memory) var entry = new MethodInstructionEntry() { IP = instruction.Address, // Offset? - Length = instruction.Length, + Length = (int)instruction.Length, Instruction = instruction.Instruction, Info = info }; instructions.Add(entry); + instruction = disassembler.DecodeNext(); } } diff --git a/Source/Mosa.Tool.Debugger/Views/StatusView.cs b/Source/Mosa.Tool.Debugger/Views/StatusView.cs index 09329ce091..f60039afae 100644 --- a/Source/Mosa.Tool.Debugger/Views/StatusView.cs +++ b/Source/Mosa.Tool.Debugger/Views/StatusView.cs @@ -44,15 +44,15 @@ private void UpdateDisplay(ulong address, byte[] memory) if (address != InstructionPointer) return; - var disassembler = new Disassembler("x86"); - disassembler.SetMemory(memory, address); + var disassembler = new Disassembler("x86", memory, address); tbInstruction.Text = "Unable to decode!"; - foreach (var instruction in disassembler.Decode()) + var instruction = disassembler.DecodeNext(); + while (instruction != null) { tbInstruction.Text = instruction.Instruction; - break; + instruction = disassembler.DecodeNext(); } } } diff --git a/Source/Mosa.Tool.Debugger/Views/TraceView.cs b/Source/Mosa.Tool.Debugger/Views/TraceView.cs index 236e1a3d8a..f746d5d0d7 100644 --- a/Source/Mosa.Tool.Debugger/Views/TraceView.cs +++ b/Source/Mosa.Tool.Debugger/Views/TraceView.cs @@ -68,13 +68,13 @@ private void UpdateDisplay(ulong address, byte[] memory) if (address == InstructionPointer) { - var disassembler = new Disassembler("x86"); - disassembler.SetMemory(memory, address); + var disassembler = new Disassembler("x86", memory, address); + var instruction = disassembler.DecodeNext(); - foreach (var instruction in disassembler.Decode()) + while (instruction != null) { opinstruction = instruction.Instruction; - break; + instruction = disassembler.DecodeNext(); } } diff --git a/Source/Mosa.Tool.Explorer.Avalonia/Stages/DisassemblyStage.cs b/Source/Mosa.Tool.Explorer.Avalonia/Stages/DisassemblyStage.cs index d59150f209..521c6a09cd 100755 --- a/Source/Mosa.Tool.Explorer.Avalonia/Stages/DisassemblyStage.cs +++ b/Source/Mosa.Tool.Explorer.Avalonia/Stages/DisassemblyStage.cs @@ -33,19 +33,13 @@ protected void TraceDisassembly() stream.Read(memory, 0, length); stream.Position = oldPosition; - var disassembler = new Disassembler(Architecture.PlatformName); - disassembler.SetMemory(memory, 0); + var disassembler = new Disassembler(Architecture.PlatformName, memory, 0); + var instruction = disassembler.DecodeNext(); - var list = disassembler.Decode(); - - if (list != null) - { - foreach (var instr in list) - trace.Log(instr.Full); - } - else + while (instruction != null) { - PostEvent(CompilerEvent.Error, $"Failed disassembly for method {MethodCompiler.Method}"); + trace.Log(instruction.Full); + instruction = disassembler.DecodeNext(); } } diff --git a/Source/Mosa.Tool.Explorer/Stages/DisassemblyStage.cs b/Source/Mosa.Tool.Explorer/Stages/DisassemblyStage.cs index a83e83f25a..4571ab33b4 100644 --- a/Source/Mosa.Tool.Explorer/Stages/DisassemblyStage.cs +++ b/Source/Mosa.Tool.Explorer/Stages/DisassemblyStage.cs @@ -34,21 +34,13 @@ protected void TraceDisassembly() stream.Read(memory, 0, length); stream.Position = oldPosition; - var disassembler = new Disassembler(Architecture.PlatformName); - disassembler.SetMemory(memory, 0); + var disassembler = new Disassembler(Architecture.PlatformName, memory, 0); + var instruction = disassembler.DecodeNext(); - var list = disassembler.Decode(); - - if (list != null) - { - foreach (var instr in list) - { - trace.Log(instr.Full); - } - } - else + while (instruction != null) { - PostEvent(CompilerEvent.Error, $"Failed disassembly for method {MethodCompiler.Method}"); + trace.Log(instruction.Full); + instruction = disassembler.DecodeNext(); } } diff --git a/Source/Mosa.Utility.Disassembler/DecodedInstruction.cs b/Source/Mosa.Utility.Disassembler/DecodedInstruction.cs index 0dc54452d0..ce1f0102c3 100644 --- a/Source/Mosa.Utility.Disassembler/DecodedInstruction.cs +++ b/Source/Mosa.Utility.Disassembler/DecodedInstruction.cs @@ -2,13 +2,13 @@ namespace Mosa.Utility.Disassembler; -public partial class DecodedInstruction +public class DecodedInstruction { - public ulong Address { get; set; } + public ulong Address { get; init; } - public int Length { get; set; } + public uint Length { get; init; } - public string Instruction { get; set; } + public string Instruction { get; init; } - public string Full { get; set; } + public string Full { get; init; } } diff --git a/Source/Mosa.Utility.Disassembler/Disassembler.cs b/Source/Mosa.Utility.Disassembler/Disassembler.cs index 78d6b562e1..4b3c7223b9 100644 --- a/Source/Mosa.Utility.Disassembler/Disassembler.cs +++ b/Source/Mosa.Utility.Disassembler/Disassembler.cs @@ -5,127 +5,88 @@ using Reko.Arch.Arm; using Reko.Arch.X86; using Reko.Core; +using Reko.Core.Machine; using Reko.Core.Memory; namespace Mosa.Utility.Disassembler; -public partial class Disassembler +public class Disassembler { - private byte[] memory; - public ulong Offset { get; set; } - private readonly ProcessorArchitecture arch; - private MemoryArea memoryArea; + private readonly byte[] memory; + private readonly IEnumerator instructions; + private readonly StringBuilder sb = new StringBuilder(100); - public Disassembler(string platform) + public Disassembler(string platform, byte[] bytes, ulong address) { var services = new ServiceContainer(); var options = new Dictionary(); + var memoryArea = new ByteMemoryArea(Address.Ptr32((uint)address), bytes); - arch = platform.ToLowerInvariant() switch + ProcessorArchitecture arch = platform.ToLowerInvariant() switch { "arm32" => new Arm32Architecture(services, "arm32", options), "arm64" => new Arm64Architecture(services, "arm64", options), "x86" => new X86ArchitectureFlat32(services, "x86-protected-32", options), "x64" => new X86ArchitectureFlat64(services, "x86-protected-64", options), - _ => arch + _ => throw new PlatformNotSupportedException(platform) }; - } - public void SetMemory(byte[] memory, ulong address) - { - this.memory = memory; - memoryArea = new ByteMemoryArea(Address.Ptr32((uint)address), memory); + memory = bytes; + instructions = arch.CreateDisassembler(memoryArea.CreateLeReader((long)Offset)).GetEnumerator(); } - public List Decode(int count = int.MaxValue) + public DecodedInstruction DecodeNext() { - var decoded = new List(); - - var sb = new StringBuilder(100); - - try - { - var dasm = arch.CreateDisassembler(memoryArea.CreateLeReader((long)Offset)); - - foreach (var instr in dasm) - { - var len = instr.Length; - var address = instr.Address.Offset; - var instruction = instr.ToString().Replace('\t', ' '); - - // preference - instruction = instruction.Replace(",", ", "); - - // fix up - //instruction = ChangeHex(instruction); - - sb.AppendFormat("{0:x8}", address); - sb.Append(' '); - var bytes = BytesToHex(memory, (uint)Offset, len); - sb.Append(bytes == null ? string.Empty : bytes.ToString()); - sb.Append(string.Empty.PadRight(41 - sb.Length, ' ')); - sb.Append(instruction); - - decoded.Add(new DecodedInstruction - { - Address = address, - Length = len, - Instruction = instruction, - Full = sb.ToString() - }); - - sb.Clear(); + if (!instructions.MoveNext()) + return null; - count--; + var machineInstruction = instructions.Current; + if (machineInstruction == null) + return null; - if (count == 0) - break; + var length = (uint)machineInstruction.Length; + var address = machineInstruction.Address.Offset; + var instruction = machineInstruction.ToString() + .Replace('\t', ' ') + .Replace(",", ", "); - Offset += (uint)len; - } + // FIXME + //instruction = ChangeHex(instruction); - return decoded; - } - catch + sb.Append(address.ToString("x8")); + sb.Append(' '); + for (var i = 0U; i < length; i++) { - return decoded; + var b = memory[i + Offset]; + sb.Append(b.ToString("x2")); + sb.Append(' '); } - } - - private static StringBuilder BytesToHex(byte[] memory, uint offset, int length) - { - if (length == 0) - return null; + for (var i = sb.Length; i < 41; i++) + sb.Append(' '); + sb.Append(instruction); - var sb = new StringBuilder(); - - for (uint i = 0; i < length; i++) + var decodedInstruction = new DecodedInstruction { - var b = memory[i + offset]; + Address = address, + Length = length, + Instruction = instruction, + Full = sb.ToString() + }; - sb.AppendFormat("{0:x2} ", b); - } + sb.Clear(); - sb.Length--; + Offset += length; - return sb; + return decodedInstruction; } - private static bool IsHex(char c) + private static bool IsHex(char c) => c switch { - if (c >= '0' && c <= '9') - return true; - - if (c >= 'a' && c <= 'f') - return true; - - if (c >= 'A' && c <= 'F') - return true; - - return false; - } + >= '0' and <= '9' or >= 'a' and <= 'f' or >= 'A' and <= 'F' => true, + _ => false + }; private static int IsNextWordHex(string s, int start) { @@ -150,7 +111,6 @@ private static string ChangeHex(string s) for (var i = 0; i < s.Length; i++) { var c = s[i]; - var l = IsNextWordHex(s, i); if (l == 0) @@ -158,17 +118,15 @@ private static string ChangeHex(string s) sb.Append(c); continue; } - else - { - var hex = s.Substring(i, l); - var value = long.Parse(hex, System.Globalization.NumberStyles.HexNumber); - var hex2 = Convert.ToString(value, 16).ToUpper(); - sb.Append("0x"); - sb.Append(hex2); + var hex = s.Substring(i, l); + var value = long.Parse(hex, System.Globalization.NumberStyles.HexNumber); + var hex2 = Convert.ToString(value, 16).ToUpper(); - i += l; - } + sb.Append("0x"); + sb.Append(hex2); + + i += l; } return sb.ToString(); diff --git a/Source/Mosa.Utility.Launcher/Builder.cs b/Source/Mosa.Utility.Launcher/Builder.cs index 6933287cb7..5857a10547 100644 --- a/Source/Mosa.Utility.Launcher/Builder.cs +++ b/Source/Mosa.Utility.Launcher/Builder.cs @@ -241,12 +241,12 @@ private void GenerateASMFile() for (ulong i = fileOffset; i < (ulong)code2.Length; i++) code[i - fileOffset] = code2[i]; - var disassembler = new Disassembler.Disassembler(MosaSettings.Platform); - disassembler.SetMemory(code, startingAddress); + var disassembler = new Disassembler.Disassembler(MosaSettings.Platform, code, startingAddress); using var dest = File.CreateText(MosaSettings.AsmFile); - foreach (var instruction in disassembler.Decode()) + var instruction = disassembler.DecodeNext(); + while (instruction != null) { if (map.TryGetValue(instruction.Address, out List list)) foreach (var entry in list) @@ -256,6 +256,8 @@ private void GenerateASMFile() if (instruction.Address > startingAddress + length) break; + + instruction = disassembler.DecodeNext(); } }