
When your program finishes, the MOS shows its registers and waits at >. From there you can type a command - T to look at memory, M to change it, D and H to convert numbers - and come back to the same prompt. This section reads the loop that makes that work, and the clever route your program takes back into it.
The prompt is MONITR, at 0171h:
MONITR:
ld sp,0fcffh ;0171
ei ;0174
rst 8 ;0175
defb 0a7h ;0176
l0177h:
ld a,(0fb40h) ;0177
rst 10h ;017a
ld de,0fbb8h ;017b
rst 8 ;017e
defb 09dh ;017f
ld a,(de) ;0180
or a ;0181
jr z,l0177h ;0182
M FB40, ENTER, 23, ENTER, then . and ENTER, and the prompt becomes #.RST 8 / 9Dh is call 157, the same line reader your programs can use, reading what you type into memory at FBB8h.Then S8's code takes the first letter, finds its entry in FMTBL, reads the numbers you typed after it, and enters the handler.
Every handler is entered with one address already on the stack as its return address: MONDUN, at 01F2h.
MONDUN:
jp nc,MONITR ;01f2
ERROR:
rst 18h ;01f5
defb ' Erro','r'+80h
rst 18h
defb '!',07h,0dh,0ah+80h
jp MONITR ;0201
(The source shows the two messages as bytes; they are written out here.)
A handler that worked returns with the carry flag clear, and JP NC goes straight back to the prompt. A handler that failed returns with carry set, and falls into ERROR, which prints Error! and then goes back. A letter with no command has ERROR itself as its table entry, so it arrives at the same message by a shorter road.
One flag, one instruction: the whole of the monitor's error handling.
Your program's last RET has to arrive somewhere in the MOS. But your program runs with RAM in, and the MOS's code is in the ROM. The return cannot be a plain jump into the ROM.
The MOS solves it with one byte. The return address your program pops is 0FA5h, and in RAM at 0FA5h there is the byte FFh. FFh is the opcode of RST 38h: a one-byte call to 0038h. And at 0038h in RAM is:
out (024h),a ; RAM 0038h: switch the ROM in
jp 0204h ; into the ROM: BREAK
BREAK, at 0204h, saves your registers before anything can disturb them:
BREAK:
ld (0fb65h),sp ;0204
di ;0208
ld sp,0fb77h ;0209
push hl ;020c
push de ;020d
push bc ;020e
push af ;020f
With SP set to FB77h, the four pushes lay HL, DE, BC and AF down in memory from FB76h to FB6Fh - a neat way to store four registers in four instructions. The register display that follows prints them from there.
The display shows PC as the address of the RST 38h that brought the MOS in. After a normal return, that is 0FA5h.
The same route serves another purpose. Because RST 38h is one byte, FFh, it can be put into any program in place of an instruction, and the program will stop there and show its registers, with PC giving the address where it stopped - a breakpoint. The name of the routine says so: BREAK.
ORG 256
LD A,12h
LD BC,3456h
LD DE,789Ah
LD HL,0BCDEh
SCF ; carry set
RET
Build and run
Press Run.
What you should see
A BC DE HL PC SZ-H-PNC
12 3456 789A BCDE 0FA5 00101001
Every value your program left is there. The last column is F, the flags, as eight bits; the final 1 is the carry your SCF set.
MONITR resets the stack, prints the prompt from FB40h, reads a line with call 157 and dispatches the letter through FMTBL. Handlers return to MONDUN with carry clear for success or set for Error!. Your program's RET reaches the MOS through an RST 38h byte at 0FA5h and a ROM switch at RAM 0038h, and BREAK saves your registers for the display.
S10: every character you have seen so far was drawn by the MOS. How, and where do their shapes come from?
This form is protected by reCAPTCHA, and the Google Privacy Policy and Terms of Service apply.