Even after full-featured assemblers became readily available, a machine code monitor was indispensable for debugging programs.
The usual technique was to set break points in the code undergoing testing (e.g., with a BRK instruction in 6502 assembly language[1][2][3]) and start the program.
When the microprocessor encountered a break point, the test program would be interrupted and control would be transferred to the machine code monitor.
Activities at this point might include examining memory contents, patching code and/or perhaps altering the processor registers prior to restarting the test program.
In most systems where higher-level languages are employed, debuggers are used to present a more abstract and friendly view of what is happening within a program.