Was there ever a commercially available hobbyist/teaching computer with the ability to single-step the processor? Maybe a Z80-based machine?
Next to every SBC/Kit computer, especially microprocessor systems could do so. Back then a system without this ability was something out of the norm.
For the 8080/Z80, already the grandpa of all hobby computers, the Altair 8800, included that feature. Single step could be issued from the front panel and all cards I've ever seen follow that (hardware) protocol - as, eventually, did the first Z80 card for the S100, the Ithaca Audio Z80 card (IA-1010).
Beside such hardware based solutions, which could even step thru ROM code, virtually every monitor program offered some way of single stepping through (RAM based) code. Like Commodores TIM, or the monitor Woz supplied for the Apple II. After all, what good would be a machine monitor if you couldn't use it for tracing?
Hardware single-stepping the Z80 is nice and simple: when the processor asserts the M1 line (meaning it's executing the first machine cycle of an instruction), pull WAIT low until you're ready for it to continue. You could easily build an add on board to do this for just about any Z80 machine with an exposed bus (although in many cases you'd also need to halt the display hardware too).
An alternative option (similar to the system described by Peter Camilleri above) is to wait for the M1 line to be asserted the number of times you want, then issue an interrupt or NMI to cause a jump back to your monitor program. An example of this is seen in the Nascom computers, which were ideal for assembly language development because their 2KiB monitor program and 1KiB video RAM left a very large amount of address space available for user programs, while the monitor itself was fully featured. Although its ability to handle break points was based on changing instruction memory to insert an
RST instruction, its single-step function was hardware assisted, as shown in this schematic:
The computer has a latch attached to I/O port 0; on the left side of the schematic bit 3 of this is connected to the clock of a flip-flop (IC14a), which becomes set whenever bit 3 goes high (edge triggered, not level triggered -- this will be relevant later). When this output goes high, two changes occur: the 'set' signal to flip-flops IC14b and IC15a is deasserted, allowing them to start changing (they'll initially both be '1'), and an input to IC10a goes high, which prevents IC15b's reset signal from being asserted while the IC14a state is high.
On the start of the next instruction (call it instruction 1), M1B goes low, then high again; this causes the output of IC14b to toggle from 1 to 0. Instruction 2 causes it to toggle from 0 to 1 again; this causes the clock signal to IC15a to go high, toggling that from 1 to 0. Instruction 3 again causes IC14b to go low; instruction 4 sends it high again, toggling IC15a back to high. This sends a clock signal to IC15b whose /Q output goes from high to low -- this has two effects: the original IC14a flip-flop is reset back to low (and because the input is level triggered it won't become high again until port 0 bit 3 is set low and then back to high again) and an NMI signal is generated until the start of the next instruction. This causes a jump back to the monitor program, which stores the program state, toggles the single step port signal back to low, shows the register contents and waits for a user command. The code in the monitor to issue a single step instruction is:
exec2: pop bc pop de pop hl pop af ; restore user sp ld sp,(rsp) ; put user pc on top of stack push hl ld hl,(rpc) ex (sp),hl ; set bit 3 of p0, to ; activate nmi push af ld a,8 out (0),a pop af ; ** INSTRUCTION 1 ; execute one step of program retn ; ** INSTRUCTION 2
Instruction 3 is therefore the executed user instruction, and the NMI occurs at the beginning of instruction 4.
I recall my old Z-80 based SD Systems Z80 Starter kit had single stepping in hardware.
A programmable timer had its output attached to the Non-Maskable Interrupt (NMI) pin. The debugger firmware would setup the timer to trigger that interrupt just as the instruction in question was fetching its first byte. This would fire off that interrupt when the instruction concluded or reached an interruptible point. Since the interrupt could not be masked, the processor had to respond.
The firmware was tricky in that the timer had to be very precisely programmed, but as a single stepper it was rock solid.
As a bonus, this method allows single stepping through ROMs and the firmware did not need to know how long the instruction was. Just where it started, which was typically the last saved PC value.
The RCA 1802 microprocessor was implemented in fully static CMOS. You could stop and single step the clock to the processor. Perhaps using a debounced front panel switch, which could be done with a slight modification to a Cosmac Elf kit.
A debugger only pretends to single step a program by inserting breakpoints or copying instructions, but the debugger itself is still running.
Since the 8080 and Z80 don't do any memory protection, it's fairly easy to do single stepping with them.
The hardest part is that a debugger that wants to do debuggging has to figure out where one instruction ends, and the next one starts. It then (for example) inserts a
ret immediately after the next instruction to execute1. Do a
call to execute that instruction, and it executes the instruction and immediately returns to the caller (the debugger). The debugger then looks at register values (or whatever it wants to). When it's ready to execute the next instruction, it replaces the
ret it inserted with the original content of that byte, finds the end of the next instruction, and inserts another
ret immediately after it. Lather, rinse repeat.
Many newer processors (e.g., the 8086 and newer) have a single step flag (normally called the "trap flag" on x86) to do single stepping without having to modify the target instructions, which is certainly handy.
It can get more difficult with processors that have MMUs, so it's harder to write to the code to be executed. In such cases, either you need something like the 8086's trap flag, or else the debugger needs enough privileges to modify the target code (e.g., it may need to run as a privileged process).
- Another fairly popular possibility is to insert an
In my time as an electronics student I worked with a trainer based on 6502 that allowed the execution step by step.
It had a hexadecimal keyboard and a 7-segment display with 8 digits (if I remember correctly).
Binging (not Googling) "6502 trainer" I found a couple of interesting names: KIM-1 and EMMA II
- For KIM-1 there's a software emulator -> Soft6502 (KIM-1) looks cool! In eBay I see a few, but with expasinve Price ($599, $999, $4.995)
- You can see ENMA II here EMMA II sold!
- Searching "6502" on eBay you can found some trainers some at good Price ($120 -> Looks good)
The 6502 procesor is simplest than z80, and it's a good start too, but I prefer a z80 on a ZX Spectrum 48K :)
The Nascom computers provided single-stepping. They did it by outputting a certain value to a port. Special circuitry then waited for enough M1 cycles (opcode fetches) to complete
POP AF RETN
and have another command start before triggering an NMI signal. A built-in debugger in the 2k of system monitor ROM then produced a register dump and put you back at the system prompt (where you could continue stepping or do other things).
There also was a 1kB debugger available (interesting since you could put it anywhere in RAM, not a mean feat on a Z80) that used the 3kB disassembler for displaying the actual opcodes if you were tired of reading hex codes. The usual setup of those computers had 8kB of ROM Basic (as delivered), 4kB of editor/assembler and the 3kB/1kB combination of debugger/disassembler (free sockets on the main board taking 1kB EPROMS). Oh, and of course the system ROM (2kB).
The DEC PDP-1 was a commercially available computer, launched in 1961. It was not a minicomputer, much less a microcomputer. It was only a "teaching machine" in the sense that about half of them were sold to universities, where they were used for both learning and research.
The PDP-1 had a hardware single step function, operated by a console switch. More importantly, it had a debugging program, written by Alan Kotok at MIT. You could set breakpoints in a program, and when it hit a breakpoint, you could examine and modify memory locations, including both variables and instructions.
Online searches say that DDT dates from 1964, but I have a distinct recollection of using it as early as the summer of 1963, and I believe it was already written by early 1962.
Was there ever a commercially available hobbyist/teaching computer with the ability to single-step the processor?
The first Z80 hardware book by Steve Ciarcia describes a circuit to provide single step capability. This is discussed in section 4, and a circuit provided in Figure 4.5. Most of the Z80 computers could do single stepping if only to help with debugging.
Maybe a Z80-based machine?
At the moment, there are two machines, to my knowledge, that can do single stepping and are available for hobbyist / teaching purposes.
The other option is the YAZ180 for which printed circuit boards can be obtained on Tindie. The YAZ180 has TIL311 Hexadecimal LEDs which show address and data contents when single stepping. The schematic shows the circuit implemented.
In my homebrew Z180-based system I'm using the following SW mechanism:
- the debugger has a specific "execution buffer", which is preced by an EI instruction
- debugger recognizes EI and DI instructions and skips them
- next 4 bytes (maximum lenght of instruction) are fetched into the execution buffer
- interrupts are disable, highest possible interrupt request is activated to be pending
- code enters the EI instruction, which enables interrupts after the NEXT instruction
- interrupt happens, SW deactivates the interrupt, collects the corresponding data, computes address for next instruction after JR instructions, etc.
I have used this mechanism for more than 20 years, first with a Z80 based system, nowadays with a Z180 based board. My debugger combines the base mechanism with things like:
- execute step by step until call of sub-program or return from sub-program
- execute step by step until given address has been reached
- execute step by step given condition happens. For e.g. until HL=0
- execute (without stepping) a sub-program
- execute (without stepping) a sub-program, and tell how many useconds it took to execute
- execute (without stepping) up to given address. I.e. kind of breakpoint
In other words, the mechanism is pretty flexible. Also, the overhead is very low, so the multiuser operating system runs normally during debugging. I'm even able to use the debugger simultaneously for several user processes (little need for that, though).
The main part of the debugger is implemented in BASIC, the assembler part is pretty small (less than 0.5KB, including data areas) and is used as an external library.
The only needed HW is some interrupt source, which can be used to go active at demand. My latest boards use an otherwise unused UART port for that purpose, but any suitable mechanism should work. However, the debug interrupt must be the highest one, otherwise you'll find out that the debugged code has branched into some system code... Still, the actual interrupt line (like Z180 INTx) can be shared with other interrupt sources; in my current system the interrupt line is shared with an other UART port and timer on the same chip.
The Exidy Sorcerer included a 4K ROM monitor which included debug capability and, IIRC, single step execution.
I believe MS-DOS/PC DOS debug program could single step through the execution of other DOS programs. I just checked, and see that the CP/M operating system included ddt (dynamic debugging tool) program. I'm guessing it was likely the model from which debug was built.
So yes, the capability was not only available, but common.