public VirtualMachine(int memorySize) { if (memorySize < 512 * 1024) throw new ArgumentOutOfRangeException("memorySize", "VM should have at least 512kB of memory"); Registers = new int[(int)Register.Count]; Memory = new byte[memorySize]; IP = 0; SP = Memory.Length; Flags = VmFlags.None; IVT = 0; _instruction = new Instruction(this); _interruptsEnabled = false; _interrupted = false; _devices = new IDevice[16]; Attach(this); _timer = new Devices.Timer(); Attach(_timer); Attach(new Devices.SysCall()); }
private IEnumerable<Line> Disassemble(Computer target, int ip) { var machine = target.Vm; var debugInfo = target.Code.DebugInfo; var instruction = new Instruction(machine); var buffer = new byte[8]; while (true) { var instrAddr = machine.IP; if (instrAddr >= machine.Memory.Length) break; ShipDebug.Line? nextLine = null; if (debugInfo != null) { var symbol = debugInfo.FindSymbol(instrAddr); if (symbol.HasValue && symbol.Value.Address == instrAddr) yield return new Line(instrAddr, string.Format("< {0} >", symbol.Value.Name), false, 1); nextLine = debugInfo.FindLine(instrAddr, 1); } var decodeFailed = false; try { instruction.Decode(); } catch { decodeFailed = true; } if (decodeFailed || !instruction.IsValid || (nextLine.HasValue && instrAddr + instruction.Length > nextLine.Value.Address)) { if (nextLine.HasValue) machine.IP = nextLine.Value.Address; else machine.IP += 4; var read = 0; while (instrAddr <= machine.IP) { if (instrAddr >= machine.Memory.Length) break; buffer[read++] = machine.Memory[instrAddr++]; if (read == buffer.Length || instrAddr == machine.IP) { if (read > 0) { var bufferStr = string.Join(", ", buffer.Take(read).Select(v => string.Format("0x{0:X2}", v))); yield return new Line(instrAddr - read, string.Format(" db {0}", bufferStr), false, 8); } read = 0; } } } else { string sourceLine = null; if (debugInfo != null) { var line = debugInfo.FindLine(instrAddr); if (line.HasValue && line.Value.Address == instrAddr) sourceLine = string.Format("{0}:{1}", line.Value.FileName, line.Value.LineNumber); } var fg = instrAddr == ip ? 4 : 0; var bg = target.HasBreakpoint(instrAddr) ? 15 : 7; yield return new Line(instrAddr, string.Format(" {0}", instruction), true, (byte)fg, (byte)bg, sourceLine); machine.IP += instruction.Length; } } }