// disassemble all memory in a list of text lines public static List <string> Disassemble() { List <string> disassemblyTextLines = new List <string>(); uint memIndex = 0; while (memIndex <= Memory.MEMORY_TOP) { Operation instruction = Disassembly(memIndex); string[] memContent = new string[instruction.Length / 2]; // memory content by operation length for (int _cnt = 0; _cnt < instruction.Length / 2; _cnt++) { memContent[_cnt] = Convert.ToString(Functions.BytesToWord(Memory.Data[memIndex + _cnt * 2], Memory.Data[memIndex + _cnt * 2 + 1]), 16).PadLeft(4, '0'); } string memContentFormatted = string.Join(" ", memContent).PadRight(14, ' '); // room for 3 hex words left aligned // memory ascii by operation length string memascii = string.Empty; for (int _cnt = 0; _cnt < instruction.Length; _cnt++) { byte membyt = Memory.Data[memIndex + _cnt]; if (membyt >= 32 && membyt <= 127) { memascii += (char)membyt; } else { memascii += ' '; } } // labels DasmSymbol symb = BinFileDasmRecord.SymbolsList.Where(w => w.DecimalValue == memIndex).FirstOrDefault(); string label = symb == null ? string.Empty : string.Format("{0}{1}", symb.Name, symb.isLabel ? ":" : string.Empty); // symbolic assembly string assembly = instruction.DebugText; disassemblyTextLines.Add(string.Format("{0} {1} {2} {3} {4} {5}", Convert.ToString(memIndex).PadLeft(5, '0'), Convert.ToString(memIndex, 16).PadLeft(4, '0'), memContentFormatted.ToUpper(), memascii.PadRight(6), label.PadLeft(9, ' '), assembly.Trim().ToUpper())); memIndex += instruction.Length; } return(disassemblyTextLines); }
// debug helper public static Operation Disassembly(uint memIndex) { DasmSymbol symbol = BinFileDasmRecord.SymbolsList.Where(w => w.DecimalValue == memIndex).FirstOrDefault(); Operation instruction = InstructionDecode(memIndex); if (symbol != null) { if (!symbol.isLabel) { // make variable ushort dataWordValue = Functions.BytesToWord(Memory.Data[memIndex], Memory.Data[memIndex + 1]); DasmSymbol valueSymbol = BinFileDasmRecord.SymbolsList.Where(w => w.isLabel == true && w.DecimalValue == dataWordValue).FirstOrDefault(); instruction = new Operation() { OpCode = dataWordValue, OpCodeValue = dataWordValue, Length = 2, Mnemonic = "DW", Type = OperationType.Undefined, Operands = new List <Operand>() { new Operand() { Value = dataWordValue, Symbol = valueSymbol == null? string.Format("${0}", Convert.ToString(dataWordValue, 16).ToUpper().PadLeft(4, '0')) : valueSymbol.Name } } }; } } // undefined mnemonic passed as is if (instruction.Type != OperationType.Undefined) { if (instruction.Width == OperationWidth.Mixed) { instruction.Mnemonic += (instruction.OpCodeValue & 0x020) != 0 ? ".B" : string.Empty; } foreach (Operand op in instruction.Operands) { DasmSymbol valueSymbol = BinFileDasmRecord.SymbolsList.Where(w => w.DecimalValue == op.Value).FirstOrDefault(); // jumps see labels if (instruction.Type != OperationType.Branch && valueSymbol != null) { // not jumps see vars reference if (valueSymbol.isLabel && instruction.Context != OperationContext.Relative) { valueSymbol = null; } } // lovely operands values to dump if doMonitor switch (op.AddressingMode) { case AddressingMode.RegisterDirect: op.DebugText = string.Format("{0}={1}", op.Symbol, Convert.ToString(State.A[op.Value], 16).PadLeft(4, '0')); break; case AddressingMode.RegisterReference: op.DebugText = string.Format("{0}={1}", op.Symbol, Convert.ToString(Functions.BytesToWord(Memory.Data[State.A[op.Value]], Memory.Data[State.A[op.Value] + 1]), 16).PadLeft(4, '0')); break; case AddressingMode.ImmediateQuick: op.DebugText = string.Format("{0}={1}", op.Symbol, op.Value); break; case AddressingMode.Immediate: if (valueSymbol != null) // && instruction.Type == OperationType.Branch) { op.Symbol = valueSymbol.Name; } op.DebugText = string.Format("{0}={1}", op.Symbol, Convert.ToString(op.Value, 16).PadLeft(4, '0')); break; case AddressingMode.MemoryReference: if (valueSymbol != null) { op.Symbol = string.Format("({0})", valueSymbol.Name); } op.DebugText = string.Format("{0}={1}", op.Symbol, Convert.ToString(Functions.BytesToWord(Memory.Data[op.Value], Memory.Data[op.Value + 1]), 16).PadLeft(4, '0')); break; case AddressingMode.StackPointer: op.DebugText = string.Format("{0}={1}", "SP", Convert.ToString(State.SP, 16).PadLeft(4, '0')); break; case AddressingMode.StatusRegister: op.DebugText = string.Format("{0}={1}", "SR", StatusRegisterValue()); break; case AddressingMode.ProgramCounter: op.DebugText = string.Format("{0}={1}", "PC", Convert.ToString(State.PC, 16).PadLeft(4, '0'));; break; } } } instruction.DebugText = instruction.Mnemonic; if (instruction.Type == OperationType.Undefined || instruction.AddressingModeSource == AddressingMode.Internal || instruction.AddressingModeDestination == AddressingMode.Internal) { instruction.DebugText += " " + instruction.Operands[0].Symbol; } else if (instruction.Type == OperationType.Memory && instruction.AddressingModeDestination == AddressingMode.StackPointer) { instruction.DebugText += instruction.Operands[0].Symbol + " "; } else if (instruction.Type == OperationType.Memory && instruction.AddressingModeSource == AddressingMode.Internal) { instruction.DebugText += " " + instruction.Operands[0].Symbol + " "; } else { instruction.DebugText += instruction.Operands.Count() > 0 ? " " + instruction.Operands[0].Symbol + "," : string.Empty; } // GETSP if (instruction.Type == OperationType.Memory && instruction.AddressingModeSource == AddressingMode.StackPointer) { instruction.DebugText = "GETSP" + " " + instruction.Operands[0].Symbol; } else { instruction.DebugText += instruction.Operands.Count() > 1 ? instruction.Operands[1].Symbol : string.Empty; } return(instruction); }