
The MOS has 85 call numbers and 15 monitor commands. A naive design would compare the call number against 85 possibilities, one after another. The MOS does something far more economical, and does it once for both jobs.
At 0282h the ROM holds 85 two-byte addresses, one after another. This is FMTBL, the "function table". The start of it in the source:
FMTBL:
defw ARITH ;0282
defw l0349h ;0284
defw COPY ;0286
defw DECIML ;0288
defw l0402h ;028a
defw MFILL ;028c
defw l03feh ;028e
defw HEX ;0290
defw ERROR ;0292
defw ERROR ;0294
...
S7 showed FMC1 using it: the call number minus 128, doubled, is the offset of the routine's address. 158 is entry 30, at 0282h + 60 = 02BEh.
To find a routine there is no searching at all - an addition and two reads, however many calls there are. Adding a call costs two bytes of table and the routine itself.
Now look at the monitor. When you type a command and press ENTER, this code picks it up:
call sub_01dch ;0184
inc de ;0187
and 05fh ;0188
sub 041h ;018a
jr c,ERROR ;018c
ld hl,FMTBL ;018e
add a,a ;0191
ld c,a ;0192
ld b,000h ;0193
add hl,bc ;0195
ld b,(hl) ;0196
inc hl ;0197
ld h,(hl) ;0198
ld l,b ;0199
The command letter is in A. AND 5Fh turns a lower-case letter into a capital. SUB 41h subtracts the code for A, so A becomes 0, B 1, and so on; anything below A is an error. Then the same doubling and adding, into the same table. The command letter A finds entry 0, which is ARITH, the arithmetic command. D finds entry 3, DECIML. Z finds entry 25, REGSTR, the register display.
So entry k does two jobs: it is the monitor command 'A' + k and the MCAL 128 + k. The first 26 MCAL numbers share their routines with the monitor's commands. Letters with no command - J, K, L and others - hold the address of ERROR, which prints Error!.
One table, read by two pieces of code, serves both. In a ROM where every byte counted, that is an economical choice.
Look again at FMC1 in S7: it does not load 0282h. It loads the address held at FB3Ah, which start-up copied there from the ROM (S6). The monitor's code uses 0282h directly, but every RST 8 call goes through that copy in RAM.
You can prove the table does what this section says by changing one word of it and rebuilding the MOS (S5). In your copy of mos12.asm, find the entry for Q, which is entry 16 (Q - A = 16), at 02A2h:
defw ERROR ;02a2
Change it to:
defw DECIML ;02a2
Build the ROM and boot it as in S5. At the prompt, type Q 003E, then D 003E.
What you should see
>Q 003E
62
>D 003E
62
With the original ROM, Q 003E prints Error!. You have given the monitor a new command by changing two bytes.
Put DEFW ERROR back at 02A2h, and instead change entry 53, at 02ECh - call 181, KSCAN, which reads the keyboard - to DEFW OUTC. Rebuild, then run a program that loads X into A and makes call 181. What will it do, and what does that tell you about how much the MOS knows about which routine belongs to which number?
FMTBL at 0282h holds 85 routine addresses. RST 8 with n reaches entry n - 128 through the table address at FB3Ah; the monitor reaches entry (letter - A) directly. One table is both the list of calls and the list of commands, and changing a word in it changes both.
S9 follows a monitor command from the prompt to its handler and back - and a program from its last RET back to the prompt.
This form is protected by reCAPTCHA, and the Google Privacy Policy and Terms of Service apply.