4BC8H - The Overlay Length (Data)
Every system file from SYS1/SYS to SYS12/SYS carries a load block for the two bytes 4BC8H-4BC9H in the resident area of SYS0/SYS. They hold the length of the file's part in the overlay area: for SYS5/SYS 03FFH, the 1023 bytes 4E00H-51FEH. In the file this block is the last load block, after the four blocks of 4E00H-51FEH and before the transfer address record (4E00H). The two bytes are data, not instructions.
4BC8-4BC9
DEFW 03FFH FF 03
4BC8H-4BC9H: 03FFH (1023), the number of bytes from 4E00H that SYS5/SYS takes up (4E00H-51FEH). Loading SYS5/SYS puts it over the length the system file loaded before it left here.
4E00H - DEBUG Entry: Save Every Register
The supervisor dispatcher (4BCCH) loads SYS5/SYS into 4E00H for request 87H and calls 4E00H. Request 87H comes only from 440DH (PUSH AF / LD A,87H / RST 28H), which three roads lead to: the RST 30H vector at 400FH (a breakpoint F7H that DEBUG planted, or the start of a program run while DEBUG is on, SYS0/SYS 4C72H), the BREAK trap when 4406H holds 400FH or 440DH, and @DEBUG at 440DH (the D key held at boot). The dispatcher drops the return address of its RST 28H, so on entry the stack holds the dispatcher's return 4BE6H, then the program's Register Pair AF pushed by 440DH, then the program's address (its PC): the address after the RST 30H, the interrupted address, or the program's transfer address. DEBUG never returns to 4BE6H, so the BREAK trap switch at 4405H stays off (C9H, stored by the dispatcher at 4BD9H) until the G command turns it on. The registers are pushed and copied in one move to the register save area 4065H-407CH.
4E00
POP AF F1
Remove the top of the stack into Register Pair AF: the dispatcher's return address 4BE6H, which is dropped. DEBUG ends with the G command (4FA3H) and never goes back through the end of the dispatcher.
4E01
POP AF F1
Restore the program's Register Pair AF from the stack, the one 440DH pushed. The program's address (its PC) is now on top of the stack.
4E02
PUSH AF F5
Save the program's Register Pair AF to the stack again. With the PC above it, the eleventh and twelfth words of the save area (4079H and 407BH) get the AF copy and the PC; 4E1FH writes the Stack Pointer over the AF copy.
4E03
PUSH IY FD E5
Save the program's Index Register IY to the stack: it becomes the word at 4077H-4078H.
4E05
PUSH IX DD E5
Save the program's Index Register IX to the stack: it becomes the word at 4075H-4076H.
4E07
EX AF,AF' 08
Exchange Register Pair AF with the alternate Register Pair AF': the program's AF' is now in Register Pair AF.
4E08
EXX D9
Exchange Register Pairs BC, DE and HL with the alternate set BC', DE' and HL' (EXX): the program's BC', DE' and HL' are now in Register Pairs BC, DE and HL.
4E09
PUSH HL E5
Save Register Pair HL (the program's HL') to the stack: it becomes the word at 4073H-4074H.
4E0A
PUSH DE D5
Save Register Pair DE (the program's DE') to the stack: it becomes the word at 4071H-4072H.
4E0B
PUSH BC C5
Save Register Pair BC (the program's BC') to the stack: it becomes the word at 406FH-4070H.
4E0C
PUSH AF F5
Save Register Pair AF (the program's AF') to the stack: it becomes the word at 406DH-406EH.
4E0D
EX AF,AF' 08
Exchange Register Pair AF with the alternate Register Pair AF' again: the program's AF is back in Register Pair AF and its AF' back in AF'.
4E0E
EXX D9
Exchange Register Pairs BC, DE and HL with the alternate set again (EXX): the program's BC, DE and HL are back in the main set and its BC', DE' and HL' in the alternate set.
4E0F
PUSH HL E5
Save the program's Register Pair HL to the stack: it becomes the word at 406BH-406CH.
4E10
PUSH DE D5
Save the program's Register Pair DE to the stack: it becomes the word at 4069H-406AH.
4E11
PUSH BC C5
Save the program's Register Pair BC to the stack: it becomes the word at 4067H-4068H.
4E12
PUSH AF F5
Save the program's Register Pair AF to the stack: it becomes the word at 4065H-4066H. The stack now holds, from the Stack Pointer up, AF, BC, DE, HL, AF', BC', DE', HL', IX, IY, AF and the PC: twelve words.
4E13
LD HL,0000H 21 00 00
Load Register Pair HL with 0000H, to add the Stack Pointer to it.
4E16
ADD HL,SP 39
ADD the Stack Pointer to Register Pair HL: Register Pair HL = the address of the program's Register Pair AF just pushed, the first of the twelve words.
4E17
LD DE,4065H 11 65 40
Load Register Pair DE with 4065H, the register save area (the first byte after the two breakpoint slots at 405DH-4062H and the memory window address at 4063H-4064H).
4E1A
LD BC,0018H 01 18 00
Load Register Pair BC with 0018H (24), the twelve words on the stack.
4E1D
LDIR ED B0
Copy the 24 bytes at Register Pair HL (the stack) to Register Pair DE (4065H), counting Register Pair BC down to 0000H: 4065H-407CH get AF, BC, DE, HL, AF', BC', DE', HL', IX, IY, the second AF and the PC, each word low byte first. Register Pair HL ends one past the PC on the stack: the Stack Pointer the program had before its address was pushed.
4E1F
LD (4079H),HL 22 79 40
Store Register Pair HL (the program's Stack Pointer) at 4079H-407AH, over the second copy of Register Pair AF: the save area now holds SP in its eleventh word and the PC (407BH-407CH) in its twelfth.
4E22
LD SP,HL F9
Load the Stack Pointer with Register Pair HL (the program's Stack Pointer): the twelve words are dropped from the stack, now that they are in the save area. DEBUG runs on the program's stack, below its Stack Pointer.
4E23H - Back the PC onto a Breakpoint
A breakpoint is an F7H (RST 30H) written over the first byte of an instruction. When it runs, the RST pushes the address after it, so the saved PC is one past the breakpoint. If the byte before the saved PC is F7H, the PC is moved back one, onto the instruction the breakpoint stood on; 4E2FH then puts its first byte back. The test is made on every entry, so a BREAK or a program start whose address follows an F7H byte is moved back too.
4E23
LD HL,(407BH) 2A 7B 40
Load Register Pair HL with the saved PC from 407BH-407CH: the address after the RST 30H when a breakpoint fired.
4E26
DEC HL 2B
DECrement Register Pair HL: the address of the byte before the PC.
4E27
LD A,(HL) 7E
Fetch the byte at Register Pair HL (the byte before the PC) into Register A.
4E28
CP F7H FE F7
Compare Register A (the byte before the PC) against F7H, the RST 30H opcode of a breakpoint.
4E2A
If the NZ FLAG is set (no F7H there), JUMP to 4E2FH to clear the breakpoints; the PC stays as it is.
4E2C
LD (407BH),HL 22 7B 40
Store Register Pair HL (the address of the F7H) at 407BH-407CH as the saved PC: when the program goes on, it starts at the instruction the breakpoint stood on, whose first byte 4E2FH puts back.
4E2FH - Clear the Two Breakpoint Slots
Two slots of three bytes: slot A at 405DH-405FH and slot B at 4060H-4062H, each the address of a breakpoint (low byte first) and the byte the F7H was written over. For each slot the address is read and cleared; if it is not 0000H and the byte there is still F7H, the saved byte is put back. Both addresses are 0000H afterwards. The same bytes are used for other things between breakpoints: 405DH is the memory display mode, 405EH the screen layout and 4060H-4061H the address the M command changes, so entering DEBUG sets the display back to the hexadecimal register screen and the M address to 0000H. When the G command set only one breakpoint, or none, 405DH-405EH still hold the display mode bytes and are taken as an address; the saved byte is written there only if that address holds F7H. The G command (4FD0H) also jumps here when a breakpoint cannot be written, to take back the breakpoints already planted.
4E2F
LD HL,405DH 21 5D 40
Load Register Pair HL with 405DH, slot A of the breakpoints: its address at 405DH-405EH and its saved byte at 405FH.
4E32
LD B,02H 06 02
Load Register B with 02H, the two slots A (405DH-405FH) and B (4060H-4062H).
4E34
XOR A AF
Set Register A to 00H (XOR A), the value that clears the address bytes.
4E35
LD E,(HL) 5E
Fetch the low byte of the slot's breakpoint address at Register Pair HL (405DH or 4060H) into Register E.
4E36
LD (HL),A 77
Store Register A (00H) at Register Pair HL, clearing the low byte of the slot's address.
4E37
INC HL 23
INCrement Register Pair HL to the high byte of the slot's address (405EH or 4061H).
4E38
LD D,(HL) 56
Fetch the high byte of the slot's address at Register Pair HL into Register D: Register Pair DE = the breakpoint address of the slot.
4E39
LD (HL),A 77
Store Register A (00H) at Register Pair HL, clearing the high byte of the slot's address.
4E3A
INC HL 23
INCrement Register Pair HL to the slot's saved byte (405FH or 4062H), the first byte of the instruction the F7H was written over.
4E3B
LD A,E 7B
Copy Register E (the low byte of the slot's address) into Register A.
4E3C
OR D B2
OR Register D (the high byte) into Register A: the Z FLAG is set when Register Pair DE is 0000H, an empty slot.
4E3D
If the Z FLAG is set (the slot is empty), JUMP to 4E46H to go to the next slot.
4E3F
LD A,(DE) 1A
Fetch the byte at the breakpoint address in Register Pair DE into Register A.
4E40
CP F7H FE F7
Compare Register A (the byte at the breakpoint address) against F7H, the breakpoint DEBUG wrote there.
4E42
If the NZ FLAG is set (the F7H is no longer there, or the address only holds display mode bytes), JUMP to 4E46H and leave the byte alone.
4E44
LD A,(HL) 7E
Fetch the saved byte at Register Pair HL (405FH or 4062H) into Register A: the first byte of the instruction the F7H covered.
4E45
LD (DE),A 12
Store Register A (the saved byte) at Register Pair DE, the breakpoint address: the program's instruction is whole again.
4E46
INC HL 23
INCrement Register Pair HL to the first byte of the next slot (4060H after slot A).
4E47
DECrement Register B (the slots left) and LOOP BACK to 4E34H for slot B while it is not zero.
4E49H - The Command Loop
Every command but G comes back here. The Stack Pointer is put back to the program's (from 4079H), the screen is drawn, the cursor goes to the start of the bottom line (3FC0H) and one key is read by 5189H, which shows it there in lower case. G (67H) is tested first; for the other commands the address 4E49H is pushed so that each handler's RET comes back here. The keys: S full screen memory, ; and - move the memory display, A and H the ASCII or hexadecimal memory display, C and I single step, D set the memory display address, M change memory, R change a register pair, U keep redrawing, X the register screen. Any other key goes to the address held at 4400H (4876H, which only returns, unless SYS9/SYS has put its extended commands there), with Register A = the key and 4E49H on the stack.
4E49
LD SP,(4079H) ED 7B 79 40
Load the Stack Pointer from 4079H-407AH, the program's Stack Pointer in the save area: whatever a command left on the stack is dropped, and DEBUG works below the program's stack again.
4E4D
GOSUB to 4ECFH to draw the screen: the register screen, or with 405EH not 00H the full screen of memory.
4E50
LD HL,3FC0H 21 C0 3F
Load Register Pair HL with 3FC0H, the first character of the bottom line of the screen (row 15 of video memory 3C00H-3FFFH).
4E53
LD (4020H),HL 22 20 40
Store Register Pair HL (3FC0H) at 4020H-4021H, the cursor position of the video device control block (DODCB$ +03H): the command is shown from the start of the bottom line.
4E56
GOSUB to 5189H to wait for a key: Register A = the key in lower case, the Z FLAG set for ENTER, a space or a comma.
4E59
CP 67H FE 67
Compare Register A (the key) against 67H, g, the G command.
4E5B
If the Z FLAG is set (G), JUMP to 4F7FH to read the go address and the breakpoints and run the program. G is the one command that does not come back to the loop.
4E5E
LD HL,4E49H 21 49 4E
Load Register Pair HL with 4E49H, the address of the command loop.
4E61
PUSH HL E5
Save Register Pair HL (4E49H) to the stack: the RET of each handler below goes back to the command loop.
4E62
CP 73H FE 73
Compare Register A (the key) against 73H, s, the S command.
4E64
If the Z FLAG is set (S), JUMP to 4E9AH to store 73H at 405EH: the full screen of memory.
4E66
CP 3BH FE 3B
Compare Register A (the key) against 3BH, the semicolon command.
4E68
If the Z FLAG is set (;), JUMP to 4EAEH to move the memory display forward.
4E6A
CP 2DH FE 2D
Compare Register A (the key) against 2DH, the minus sign command.
4E6C
If the Z FLAG is set (-), JUMP to 4EC6H to move the memory display back.
4E6E
CP 61H FE 61
Compare Register A (the key) against 61H, a, the A command.
4E70
If the Z FLAG is set (A), JUMP to 4ECBH to store 61H at 405DH: memory shown as characters.
4E72
CP 63H FE 63
Compare Register A (the key) against 63H, c, the C command.
4E74
If the Z FLAG is set (C), JUMP to 4E80H, the JP Z,505EH of the I command: both single step from 505EH, which tells them apart by the key it saved.
4E76
CP 64H FE 64
Compare Register A (the key) against 64H, d, the D command.
4E78
If the Z FLAG is set (D), JUMP to 4EA8H to read a new memory display address.
4E7A
CP 68H FE 68
Compare Register A (the key) against 68H, h, the H command.
4E7C
If the Z FLAG is set (H), JUMP to 4ECBH to store 68H at 405DH: memory shown in hexadecimal.
4E7E
CP 69H FE 69
Compare Register A (the key) against 69H, i, the I command.
4E80
If the Z FLAG is set (I, or C from 4E74H), JUMP to 505EH to single step the instruction at the saved PC. Register A = the key.
4E83
CP 6DH FE 6D
Compare Register A (the key) against 6DH, m, the M command.
4E85
If the Z FLAG is set (M), JUMP to 4FDAH to change memory byte by byte.
4E88
CP 72H FE 72
Compare Register A (the key) against 72H, r, the R command.
4E8A
If the Z FLAG is set (R), JUMP to 5010H to change a register pair in the save area.
4E8D
CP 75H FE 75
Compare Register A (the key) against 75H, u, the U command.
4E8F
If the Z FLAG is set (U), JUMP to 4E9EH to keep redrawing the screen until a key is pressed.
4E91
CP 78H FE 78
Compare Register A (the key) against 78H, x, the X command.
4E93
If the Z FLAG is set (X), JUMP to 4E99H to store 00H at 405EH: the register screen.
4E95
LD HL,(4400H) 2A 00 44
Load Register Pair HL with the address held at 4400H-4401H: 4876H (OR A / RET in SYS0/SYS) unless SYS9/SYS has stored the address of its extended commands there.
4E98
JP (HL) E9
JUMP to the address in Register Pair HL with Register A = the key. The command loop's 4E49H is on the stack, so the RET of 4876H, or of the extended command, comes back to the loop.
4E99H - X and S: Choose the Screen
405EH is the screen layout: 00H the register screen (twelve register pairs and four lines of memory), any other value the full screen of sixteen lines of memory. X enters at 4E99H with Register A cleared; S enters at 4E9AH with Register A = 73H, its key.
4E99
XOR A AF
Set Register A to 00H (XOR A): the register screen, for the X command.
4E9A
LD (405EH),A 32 5E 40
Store Register A at 405EH, the screen layout: 00H from X, 73H (the key s) from S. 405EH is also the high byte of the address in breakpoint slot A, cleared on every entry (4E2FH).
4E9D
RET C9
RETurn to the command loop at 4E49H, which draws the chosen screen.
4E9EH - U: Keep Redrawing the Screen
The screen is drawn again and again so that memory a background task changes (the clock at 4217H-4219H, for instance) is seen changing, until a key is pressed.
4E9E
GOSUB to the ROM at 002BH to look at the keyboard once: Register A = the key pressed, or 00H when none is.
4EA1
OR A B7
Set the flags from Register A (OR A): the Z FLAG is set when no key is pressed.
4EA2
RET NZ C0
If the NZ FLAG is set (a key is pressed), RETurn to the command loop at 4E49H.
4EA3
GOSUB to 4ECFH to draw the screen again from the memory as it is now.
4EA6
LOOP BACK to 4E9EH to look at the keyboard again.
4EA8H - D: Set the Memory Display Address
Reads a hexadecimal address and makes it the first address of the memory display (4063H-4064H). D with no number leaves it as it is.
4EA8
GOSUB to 51A4H to read a hexadecimal number: Register Pair HL = the number, the Z FLAG set when no digit was typed.
4EAB
RET Z C8
If the Z FLAG is set (no number), RETurn to the command loop at 4E49H; the display address is not changed.
4EAC
JUMP to 4EC2H to store Register Pair HL (the number) at 4063H-4064H, the memory display address, and return.
4EAEH - ; and -: Move the Memory Display
The semicolon moves the memory display address at 4063H-4064H forward and the minus sign moves it back: by 64 bytes (the four lines) on the register screen, by 256 bytes (the sixteen lines) on the full screen. The minus sign enters at 4EC6H with Register Pair BC = FFC0H; for the full screen Register B tells the two apart (00H forward, FFH back).
4EAE
LD BC,0040H 01 40 00
Load Register Pair BC with 0040H (64), the four lines of the register screen's memory display.
4EB1
LD HL,(4063H) 2A 63 40
Load Register Pair HL with the memory display address from 4063H-4064H.
4EB4
LD A,(405EH) 3A 5E 40
Fetch the screen layout from 405EH into Register A: 00H the register screen.
4EB7
OR A B7
Set the flags from Register A (OR A): the Z FLAG is set for the register screen.
4EB8
If the Z FLAG is set (the register screen), JUMP to 4EC1H to add Register Pair BC (+64 or -64) to Register Pair HL.
4EBA
LD C,00H 0E 00
Load Register C with 00H: Register Pair BC becomes 0000H for the semicolon (Register B = 00H) and FF00H (-256) for the minus sign (Register B = FFH).
4EBC
LD A,B 78
Copy Register B (00H for the semicolon, FFH for the minus sign) into Register A.
4EBD
OR A B7
Set the flags from Register A (OR A): the NZ FLAG is set for the minus sign.
4EBE
If the NZ FLAG is set (the minus sign: Register Pair BC = FF00H, -256), JUMP to 4EC1H.
4EC0
INC B 04
INCrement Register B: Register Pair BC = 0100H (+256), the sixteen lines of the full screen, for the semicolon.
4EC1
ADD HL,BC 09
ADD Register Pair BC (+64, -64, +256 or -256) to Register Pair HL (the memory display address).
4EC2
LD (4063H),HL 22 63 40
Store Register Pair HL at 4063H-4064H, the memory display address. The D command (4EACH) comes here too, with the number it read.
4EC5
RET C9
RETurn to the command loop at 4E49H, which draws the screen from the new address.
4EC6
LD BC,FFC0H 01 C0 FF
The minus sign: Load Register Pair BC with FFC0H (-64), the four lines of the register screen backwards; Register B = FFH tells 4EBCH the direction for the full screen.
4EC9
JUMP to 4EB1H to apply Register Pair BC to the memory display address.
4ECBH - A and H: Choose the Memory Display Mode
Register A holds the key: 61H (a) or 68H (h). It is kept at 405DH, which 5143H tests for 61H: memory is then shown as characters, otherwise in hexadecimal. 405DH is also the low byte of the address in breakpoint slot A, cleared on every entry (4E2FH), so DEBUG starts in hexadecimal.
4ECB
LD (405DH),A 32 5D 40
Store Register A (61H for A, 68H for H) at 405DH, the memory display mode.
4ECE
RET C9
RETurn to the command loop at 4E49H, which draws the screen in the new mode.
4ECFH - Draw the Register Screen
With 405EH = 00H the screen shows twelve lines, one for each register pair of the save area (4065H-407CH) in the order of the name table at 4F53H: the name, an equals sign, the high and the low byte in hexadecimal; for AF and AF' then the eight flags of Register F by name (4F77H), for the others the sixteen bytes of memory the pair points at (5131H). Four lines of memory from the display address at 4063H-4064H follow (4F2EH). All text goes through the ROM's display routine at 0033H, which also takes the control codes 0DH (next line) and 1CH (cursor to the top left corner) and the codes C0H-FFH, each of which shows 0-63 spaces. With 405EH not 00H, 4F44H draws sixteen lines of memory instead.
4ECF
LD A,(405EH) 3A 5E 40
Fetch the screen layout from 405EH into Register A: 00H the register screen.
4ED2
OR A B7
Set the flags from Register A (OR A): the NZ FLAG is set for the full screen of memory.
4ED3
If the NZ FLAG is set (the full screen), JUMP to 4F44H to draw sixteen lines of memory instead.
4ED5
LD A,1CH 3E 1C
Load Register A with 1CH, the control code that puts the cursor at the top left corner of the screen.
4ED7
GOSUB to the ROM at 0033H to send the character in Register A (1CH) to the display: the cursor goes to 3C00H.
4EDA
LD HL,4065H 21 65 40
Load Register Pair HL with 4065H, the first word of the register save area (the program's Register Pair AF).
4EDD
PUSH HL E5
Save Register Pair HL (4065H) to the stack: the loop keeps its place in the save area on the stack and its place in the name table in Register Pair HL, swapping them with EX (SP),HL.
4EDE
LD HL,4F53H 21 53 4F
Load Register Pair HL with 4F53H, the table of the twelve register pair names, three characters each.
4EE1
LD B,0CH 06 0C
Load Register B with 0CH (12), the number of register pairs, counted down: 12 for AF to 1 for PC.
4EE3
JUMP to 4EEAH: the first line needs no carriage return before it.
4EE5
LD A,0DH 3E 0D
Load Register A with 0DH, a carriage return, to start a new line of the screen.
4EE7
GOSUB to the ROM at 0033H to send the character in Register A (0DH) to the display.
4EEA
GOSUB to 51F5H to display the three characters at Register Pair HL, the register pair's name (AF , BC , ... PC ): Register Pair HL ends at the next name.
4EED
EX (SP),HL E3
Exchange Register Pair HL with the word at the Stack Pointer, the top of the stack: Register Pair HL = the place in the save area, and the place of the next name goes onto the stack.
4EEE
LD E,(HL) 5E
Fetch the low byte of the register pair from the save area at Register Pair HL into Register E.
4EEF
INC HL 23
INCrement Register Pair HL to the high byte of the register pair.
4EF0
LD D,(HL) 56
Fetch the high byte of the register pair at Register Pair HL into Register D: Register Pair DE = the register pair's saved value.
4EF1
INC HL 23
INCrement Register Pair HL to the next word of the save area.
4EF2
PUSH HL E5
Save Register Pair HL (the next word of the save area) to the stack, above the place of the next name.
4EF3
EX DE,HL EB
Exchange Register Pairs DE and HL: Register Pair HL = the register pair's value.
4EF4
LD A,3DH 3E 3D
Load Register A with 3DH, an equals sign, to follow the register pair's name.
4EF6
GOSUB to the ROM at 0033H to display the character in Register A (=).
4EF9
GOSUB to 51F1H to display a space after the equals sign.
4EFC
LD A,H 7C
Copy Register H (the high byte of the register pair's value) into Register A.
4EFD
GOSUB to 51EEH to display Register A (the high byte) as two hexadecimal digits and a space.
4F00
LD A,L 7D
Copy Register L (the low byte of the register pair's value) into Register A.
4F01
GOSUB to 51EEH to display Register A (the low byte) as two hexadecimal digits and a space. The line has eleven characters so far.
4F04
LD A,B 78
Copy Register B (the line counter, 12 for AF to 1 for PC) into Register A.
4F05
AND 0BH E6 0B
Mask Register A (the line counter) with 0BH, keeping bits 3, 1 and 0: only 12 (AF, 0CH) and 8 (AF', 08H) give 08H.
4F07
CP 08H FE 08
Compare Register A against 08H: the Z FLAG is set for the lines of AF and AF', whose Register F is shown as flags.
4F09
If the NZ FLAG is set (another register pair), JUMP to 4F26H, where the CALL NZ shows the sixteen bytes it points at.
4F0B
LD C,L 4D
Copy Register L (the low byte of AF or AF', Register F) into Register C, to shift its bits out one by one.
4F0C
PUSH BC C5
Save Register Pair BC (Register B = the line counter, Register C = the flags) to the stack.
4F0D
LD HL,4F77H 21 77 4F
Load Register Pair HL with 4F77H, the eight flag names SZ1H1PNC, one for each bit of Register F from bit 7 down.
4F10
LD B,08H 06 08
Load Register B with 08H, the eight bits of Register F.
4F12
SLA C CB 21
Shift Register C (the flags) left: the CARRY FLAG takes the next bit, bit 7 first.
4F14
LD A,(HL) 7E
Fetch the flag's name from the table at Register Pair HL into Register A. LD does not change the CARRY FLAG.
4F15
If the CARRY FLAG is set (the flag is 1), JUMP to 4F19H to show its name.
4F17
LD A,2DH 3E 2D
Load Register A with 2DH, a minus sign, shown for a flag that is 0.
4F19
GOSUB to the ROM at 0033H to display Register A, the flag's name or the minus sign.
4F1C
INC HL 23
INCrement Register Pair HL to the next flag name.
4F1D
DECrement Register B (the bits left) and LOOP BACK to 4F12H while it is not zero.
4F1F
POP BC C1
Restore Register Pair BC (Register B = the line counter) from the stack.
4F20
LD A,ECH 3E EC
Load Register A with ECH: the ROM shows a code C0H-FFH as that many spaces less C0H, here 2CH (44), which take the line of 19 characters to 63.
4F22
GOSUB to the ROM at 0033H to display the code in Register A (ECH, 44 spaces).
4F25
XOR A AF
Set Register A to 00H (XOR A): the Z FLAG is set, so the CALL NZ that follows is not made for AF and AF'.
4F26
If the NZ FLAG is set (a register pair other than AF and AF'), GOSUB to 5131H to display the sixteen bytes of memory at Register Pair HL, the pair's value, in the chosen mode.
4F29
POP HL E1
Restore Register Pair HL from the stack: the next word of the save area.
4F2A
EX (SP),HL E3
Exchange Register Pair HL with the word at the Stack Pointer, the top of the stack: Register Pair HL = the place of the next name, and the place in the save area goes onto the stack.
4F2B
DECrement Register B (the register pairs left) and LOOP BACK to 4EE5H while it is not zero.
4F2D
POP HL E1
Remove the place in the save area (4065H + 24 = 407DH) from the stack into Register Pair HL; it is not used.
4F2EH - Draw the Memory Lines
Register B lines of sixteen bytes, from the address in Register Pair HL. Each line starts with seven spaces (code C7H), of which the first completes the line before (the register lines and the memory lines are each 63 characters long, without a carriage return), then the address in hexadecimal and a space, then the sixteen bytes (5131H): with seven, four, one and 52 characters, each line ends exactly at the last column, so the next one starts on a new line. The register screen enters at 4F2EH for four lines from the memory display address; the full screen enters at 4F33H with sixteen lines.
4F2E
LD HL,(4063H) 2A 63 40
Load Register Pair HL with the memory display address from 4063H-4064H.
4F31
LD B,04H 06 04
Load Register B with 04H, the four memory lines under the registers.
4F33
LD A,C7H 3E C7
Load Register A with C7H: the ROM shows it as seven spaces (C7H less C0H).
4F35
GOSUB to the ROM at 0033H to display the code in Register A (C7H, seven spaces).
4F38
GOSUB to 51D5H to display Register Pair HL, the address of the line, as four hexadecimal digits.
4F3B
GOSUB to 51F1H to display a space between the address and the bytes.
4F3E
GOSUB to 5131H to display the sixteen bytes at Register Pair HL; Register Pair HL ends sixteen bytes further on, at the address of the next line.
4F41
DECrement Register B (the lines left) and LOOP BACK to 4F33H while it is not zero.
4F43
RET C9
RETurn to the caller (4ECFH's caller, or the caller of 4F44H) with the memory lines drawn.
4F44H - Draw the Full Screen of Memory
The S command's screen: the 256 bytes of the page that holds the memory display address, on sixteen lines. The cursor starts at 3BFFH, one byte before video memory, so the first of the seven spaces of the first line falls outside the screen and the 1024 characters end at 3FFEH: the screen is filled without scrolling.
4F44
LD HL,3BFFH 21 FF 3B
Load Register Pair HL with 3BFFH, the byte before video memory (3C00H).
4F47
LD (4020H),HL 22 20 40
Store Register Pair HL (3BFFH) at 4020H-4021H, the cursor position of the video device control block (DODCB$ +03H).
4F4A
LD HL,(4063H) 2A 63 40
Load Register Pair HL with the memory display address from 4063H-4064H.
4F4D
LD L,00H 2E 00
Load Register L with 00H: Register Pair HL = the start of the 256 byte page that holds the display address.
4F4F
LD B,10H 06 10
Load Register B with 10H (16), the sixteen lines of the full screen.
4F51
JUMP to 4F33H to draw the Register B (16) lines from Register Pair HL; the RET at 4F43H returns to the caller of 4ECFH.
4F53H - The Register Pair and Flag Names (Data)
Twelve names of three characters, in the order of the register save area at 4065H-407CH: 4EEAH shows them on the register screen and the R command (502CH) looks a name up here to find the word it changes. Then the eight flag names, one for each bit of Register F from bit 7 to bit 0: S sign, Z zero, 1 for bit 5, H half carry, 1 for bit 3, P parity or overflow, N subtract, C carry. Bits 5 and 3 have no name of their own and show 1 when they are set.
4F53-4F55
DEFM "AF " 41 46 20
4F53H-4F55H: the name of the first word of the save area, 4065H-4066H, Register Pair AF.
4F56-4F58
DEFM "BC " 42 43 20
4F56H-4F58H: the name of the second word, 4067H-4068H, Register Pair BC.
4F59-4F5B
DEFM "DE " 44 45 20
4F59H-4F5BH: the name of the third word, 4069H-406AH, Register Pair DE.
4F5C-4F5E
DEFM "HL " 48 4C 20
4F5CH-4F5EH: the name of the fourth word, 406BH-406CH, Register Pair HL.
4F5F-4F61
DEFM "AF'" 41 46 27
4F5FH-4F61H: the name of the fifth word, 406DH-406EH, the alternate Register Pair AF'.
4F62-4F64
DEFM "BC'" 42 43 27
4F62H-4F64H: the name of the sixth word, 406FH-4070H, the alternate Register Pair BC'.
4F65-4F67
DEFM "DE'" 44 45 27
4F65H-4F67H: the name of the seventh word, 4071H-4072H, the alternate Register Pair DE'.
4F68-4F6A
DEFM "HL'" 48 4C 27
4F68H-4F6AH: the name of the eighth word, 4073H-4074H, the alternate Register Pair HL'.
4F6B-4F6D
DEFM "IX " 49 58 20
4F6BH-4F6DH: the name of the ninth word, 4075H-4076H, Index Register IX.
4F6E-4F70
DEFM "IY " 49 59 20
4F6EH-4F70H: the name of the tenth word, 4077H-4078H, Index Register IY.
4F71-4F73
DEFM "SP " 53 50 20
4F71H-4F73H: the name of the eleventh word, 4079H-407AH, the program's Stack Pointer.
4F74-4F76
DEFM "PC " 50 43 20
4F74H-4F76H: the name of the twelfth word, 407BH-407CH, the program's address, where it goes on. The R command finds this name too, so R PC changes the address G starts at.
4F77-4F7E
DEFM "SZ1H1PNC" 53 5A 31 48 31 50 4E 43
4F77H-4F7EH: the flag names for bits 7 to 0 of Register F, shown for a 1 bit (a minus sign for a 0 bit): S sign, Z zero, 1 bit 5, H half carry, 1 bit 3, P parity or overflow, N subtract, C carry.
4F7FH - G: Go, with up to Two Breakpoints
G aaaa,b1,b2 then ENTER. aaaa, when given, replaces the saved PC at 407BH-407CH; each breakpoint address given is planted by 4FC9H, the first in slot B (4060H-4062H), the second in slot A (405DH-405FH). ENTER ends the line at any point. Then the BREAK trap is turned on with 400FH as its address, so BREAK enters DEBUG again, and the program goes on at 4FA3H with every register taken from the save area.
4F7F
LD B,02H 06 02
Load Register B with 02H, the two breakpoints G accepts.
4F81
LD DE,4062H 11 62 40
Load Register Pair DE with 4062H, the last byte of slot B: 4FC9H stores the saved byte, then the address high and low bytes, going down, and leaves Register Pair DE at 405FH, the last byte of slot A, for the second breakpoint.
4F84
GOSUB to 51A4H to read a hexadecimal number: Register Pair HL = the number, the Z FLAG set when no digit was typed, the CARRY FLAG set when ENTER ended it.
4F87
If the Z FLAG is set (no go address), JUMP to 4F8CH: the saved PC is kept.
4F89
LD (407BH),HL 22 7B 40
Store Register Pair HL (the go address) at 407BH-407CH, the saved PC: the program goes on there.
4F8C
If the CARRY FLAG is set (ENTER ended the line), JUMP to 4F98H to run the program with the breakpoints given so far.
4F8E
GOSUB to 51A4H to read a breakpoint address: Register Pair HL = the address, the Z FLAG set when none was typed, the CARRY FLAG set when ENTER ended it.
4F91
PUSH AF F5
Save Register Pair AF (the flags from 51A4H) to the stack, since 4FC9H changes them.
4F92
If the NZ FLAG is set (an address was typed), GOSUB to 4FC9H to plant a breakpoint at Register Pair HL, keeping its byte in the slot that ends at Register Pair DE (4062H, then 405FH).
4F95
POP AF F1
Restore Register Pair AF (the flags from 51A4H) from the stack.
4F96
DECrement Register B (the breakpoints still allowed) and LOOP BACK to 4F8CH while it is not zero, to test for ENTER and read the next one.
4F98
LD HL,400FH 21 0F 40
Load Register Pair HL with 400FH, the RST 30H vector of SYS0/SYS, which jumps to 440DH and so enters DEBUG.
4F9B
LD (4406H),HL 22 06 44
Store Register Pair HL (400FH) at 4406H-4407H, the address the BREAK trap goes to.
4F9E
LD A,C3H 3E C3
Load Register A with C3H, the value that turns the BREAK trap on.
4FA0
LD (4405H),A 32 05 44
Store Register A (C3H) at 4405H, the BREAK trap switch: BREAK pressed while the program runs goes to 400FH and enters DEBUG with the program's registers (the interrupt service routine of SYS0/SYS, 44E3H-44F9H).
4FA3H - Run the Program with the Saved Registers
The G command and the single step (50B5H) come here. The eleven words of the save area from AF to SP are pushed onto the stack from the top down and popped into the registers, both sets; the Stack Pointer is set to the program's, the saved PC is pushed onto the program's stack and a RET jumps to it, with Register Pair HL loaded from the save area just before.
4FA3
LD HL,407AH 21 7A 40
Load Register Pair HL with 407AH, the high byte of the saved Stack Pointer, the eleventh word of the save area (4079H-407AH).
4FA6
LD B,0BH 06 0B
Load Register B with 0BH (11), the words from SP (4079H) down to AF (4065H).
4FA8
LD D,(HL) 56
Fetch the high byte of the word at Register Pair HL into Register D.
4FA9
DEC HL 2B
DECrement Register Pair HL to the low byte of the word.
4FAA
LD E,(HL) 5E
Fetch the low byte of the word at Register Pair HL into Register E: Register Pair DE = the saved register pair.
4FAB
DEC HL 2B
DECrement Register Pair HL to the high byte of the word below.
4FAC
PUSH DE D5
Save Register Pair DE (the saved register pair) to the stack: SP first, AF last, so AF ends on top.
4FAD
DECrement Register B (the words left) and LOOP BACK to 4FA8H while it is not zero.
4FAF
POP AF F1
Restore Register Pair AF from the stack: the program's AF from 4065H-4066H.
4FB0
POP BC C1
Restore Register Pair BC from the stack: the program's BC from 4067H-4068H.
4FB1
POP DE D1
Restore Register Pair DE from the stack: the program's DE from 4069H-406AH.
4FB2
POP HL E1
Restore Register Pair HL from the stack: the program's HL from 406BH-406CH.
4FB3
EX AF,AF' 08
Exchange Register Pair AF with the alternate Register Pair AF': the program's AF goes into AF', so the next POP AF fills the main AF register.
4FB4
EXX D9
Exchange Register Pairs BC, DE and HL with the alternate set (EXX): the program's BC, DE and HL go into BC', DE' and HL' for the moment.
4FB5
POP AF F1
Restore Register Pair AF from the stack: the program's AF' from 406DH-406EH.
4FB6
POP BC C1
Restore Register Pair BC from the stack: the program's BC' from 406FH-4070H.
4FB7
POP DE D1
Restore Register Pair DE from the stack: the program's DE' from 4071H-4072H.
4FB8
POP HL E1
Restore Register Pair HL from the stack: the program's HL' from 4073H-4074H.
4FB9
EX AF,AF' 08
Exchange Register Pair AF with the alternate Register Pair AF' again: the program's AF is back in AF and its AF' in the alternate AF'.
4FBA
EXX D9
Exchange Register Pairs BC, DE and HL with the alternate set again (EXX): the program's BC, DE and HL are in the main set and its BC', DE' and HL' in the alternate set.
4FBB
POP IX DD E1
Restore Index Register IX from the stack: the program's IX from 4075H-4076H.
4FBD
POP IY FD E1
Restore Index Register IY from the stack: the program's IY from 4077H-4078H.
4FBF
POP HL E1
Restore Register Pair HL from the stack: the program's Stack Pointer from 4079H-407AH.
4FC0
LD SP,HL F9
Load the Stack Pointer with Register Pair HL: the program's own stack.
4FC1
LD HL,(407BH) 2A 7B 40
Load Register Pair HL with the saved PC from 407BH-407CH, the address where the program goes on.
4FC4
PUSH HL E5
Save Register Pair HL (the PC) to the program's stack, for the RET.
4FC5
LD HL,(406BH) 2A 6B 40
Load Register Pair HL with the program's Register Pair HL from 406BH-406CH again, since it was used for the Stack Pointer and the PC.
4FC8
RET C9
RETurn: the PC comes off the stack and the program goes on there with all its registers and its own Stack Pointer.
4FC9H - Plant a Breakpoint
Register Pair HL = the address, Register Pair DE = the last byte of a slot (4062H for slot B, 405FH for slot A). The byte at the address is kept in the slot, F7H (RST 30H) is written over it and read back: if the byte did not change to F7H (ROM, or no memory there), the command is given up at 4E2FH, which takes back the breakpoints already planted and goes back to the command loop. Otherwise the address is stored in the slot, high byte then low byte going down, and Register Pair DE is left at the last byte of the slot below (405FH after slot B).
4FC9
LD A,(HL) 7E
Fetch the byte at Register Pair HL (the breakpoint address) into Register A: the first byte of the instruction there.
4FCA
LD (DE),A 12
Store Register A (that byte) at Register Pair DE, the saved byte of the slot (4062H or 405FH).
4FCB
DEC DE 1B
DECrement Register Pair DE to the high byte of the slot's address (4061H or 405EH).
4FCC
LD A,F7H 3E F7
Load Register A with F7H, the RST 30H opcode of a breakpoint.
4FCE
LD (HL),A 77
Store Register A (F7H) at Register Pair HL, over the first byte of the instruction.
4FCF
CP (HL) BE
Compare Register A (F7H) against the byte at Register Pair HL, read back: the Z FLAG is set when the write took.
4FD0
If the NZ FLAG is set (the address is not in RAM), JUMP to 4E2FH to take back the breakpoints planted so far and go on to the command loop: the command is ignored. The slot's address bytes still hold what they held before.
4FD3
LD A,H 7C
Copy Register H (the high byte of the breakpoint address) into Register A.
4FD4
LD (DE),A 12
Store Register A at Register Pair DE (4061H or 405EH), the high byte of the slot's address.
4FD5
DEC DE 1B
DECrement Register Pair DE to the low byte of the slot's address (4060H or 405DH).
4FD6
LD A,L 7D
Copy Register L (the low byte of the breakpoint address) into Register A.
4FD7
LD (DE),A 12
Store Register A at Register Pair DE (4060H or 405DH), the low byte of the slot's address.
4FD8
DEC DE 1B
DECrement Register Pair DE to the last byte of the slot below: 405FH, the saved byte of slot A, after slot B.
4FD9
RET C9
RETurn to the caller with Register Pair HL = the breakpoint address.
4FDAH - M: Change Memory
M aaaa then a space. The address typed (or, when none is typed, the one at 4060H-4061H) becomes the M address at 4060H-4061H, which the memory display marks with bars on both sides of its byte. If ENTER ended the address the command stops there. Otherwise the screen is drawn, the address is shown at the start of line 13 (3F40H) and its byte at the start of line 14 (3F80H) with a minus sign, and a new value is read: a space stores it and goes on to the next address, ENTER stores it and stops, a space or ENTER with no digits leaves the byte as it is, and any other key that is not a hexadecimal digit (X, say) stops without storing. Only the last two digits typed count.
4FDA
LD HL,(4060H) 2A 60 40
Load Register Pair HL with the M address from 4060H-4061H, the one used when no address is typed (51A4H returns at once and leaves Register Pair HL as it is).
4FDD
GOSUB to 51A4H to read a hexadecimal address: Register Pair HL = the address, or the old M address when no digit was typed; the CARRY FLAG set when ENTER ended it.
4FE0
LD (4060H),HL 22 60 40
Store Register Pair HL at 4060H-4061H, the M address. The loop comes back here (500EH) with the next address.
4FE3
RET C D8
If the CARRY FLAG is set (ENTER), RETurn to the command loop at 4E49H, which draws the screen with the bars at the M address.
4FE4
PUSH HL E5
Save Register Pair HL (the M address) to the stack, for 5004H.
4FE5
GOSUB to 4ECFH to draw the screen, with the bars around the byte at the M address when it is on the screen.
4FE8
LD HL,3F40H 21 40 3F
Load Register Pair HL with 3F40H, the first character of line 13 of the screen (row 13 of 3C00H-3FFFH).
4FEB
LD (4020H),HL 22 20 40
Store Register Pair HL (3F40H) at 4020H-4021H, the cursor position of the video device control block (DODCB$ +03H).
4FEE
LD HL,(4060H) 2A 60 40
Load Register Pair HL with the M address from 4060H-4061H.
4FF1
GOSUB to 51D5H to display Register Pair HL (the M address) as four hexadecimal digits at the start of line 13.
4FF4
PUSH HL E5
Save Register Pair HL (the M address) to the stack.
4FF5
LD HL,3F80H 21 80 3F
Load Register Pair HL with 3F80H, the first character of line 14 of the screen.
4FF8
LD (4020H),HL 22 20 40
Store Register Pair HL (3F80H) at 4020H-4021H, the cursor position of the video device control block (DODCB$ +03H).
4FFB
POP HL E1
Restore Register Pair HL (the M address) from the stack.
4FFC
GOSUB to 51D1H to display the byte at Register Pair HL (the M address) as two hexadecimal digits; Register Pair HL is incremented past it, which the code does not use.
4FFF
LD A,2DH 3E 2D
Load Register A with 2DH, a minus sign, after which the new value is typed.
5001
GOSUB to the ROM at 0033H to display the character in Register A (-).
5004
POP DE D1
Restore Register Pair DE from the stack: the M address saved at 4FE4H.
5005
GOSUB to 51A4H to read the new value: Register Pair HL = the number (Register L its last two digits), the Z FLAG set when no digit was typed, the CARRY FLAG set when ENTER ended it. A key that is not a hexadecimal digit ends the command at 4E49H.
5008
EX DE,HL EB
Exchange Register Pairs DE and HL: Register Pair HL = the M address and Register E = the low byte of the new value.
5009
If the Z FLAG is set (no digits), JUMP to 500CH: the byte at the M address is left as it is.
500B
LD (HL),E 73
Store Register E (the new value) at Register Pair HL, the M address.
500C
RET C D8
If the CARRY FLAG is set (ENTER), RETurn to the command loop at 4E49H.
500D
INC HL 23
INCrement Register Pair HL to the next address. INC of a register pair does not change the flags, so the CARRY FLAG stays clear for 4FE3H.
500E
LOOP BACK to 4FE0H to make Register Pair HL (the next address) the M address and show it.
5010H - R: Change a Register Pair
R, the name of a register pair (two letters, a third character for the alternate pairs: AF', BC', DE', HL'), a space, the new value in hexadecimal and ENTER. The name is looked up in the table at 4F53H, which gives the word of the save area at 4065H + 2 x its place; every pair can be changed this way, the Stack Pointer and the PC too. A name not in the table, or ENTER before the value, ends the command with nothing changed; a space or ENTER with no digits leaves the pair as it is. Letters come from 5189H in lower case and are made capitals here (RES 5) to match the table.
5010
GOSUB to 5189H to wait for the first character of the name: Register A = the key in lower case, the Z FLAG set for ENTER, a space or a comma.
5013
RET Z C8
If the Z FLAG is set (no name), RETurn to the command loop at 4E49H.
5014
RES 5,A CB AF
Reset bit 5 of Register A: the letter becomes a capital, as in the name table.
5016
LD C,A 4F
Copy Register A (the first character) into Register C.
5017
GOSUB to 5189H to wait for the second character of the name into Register A.
501A
RET Z C8
If the Z FLAG is set (the name ended after one character), RETurn to the command loop at 4E49H.
501B
RES 5,A CB AF
Reset bit 5 of Register A: the letter becomes a capital.
501D
LD D,A 57
Copy Register A (the second character) into Register D.
501E
LD E,20H 1E 20
Load Register E with 20H, a space: the third character of the names of the main register pairs in the table.
5020
GOSUB to 5189H to wait for the next key into Register A.
5023
RET C D8
If the CARRY FLAG is set (ENTER), RETurn to the command loop at 4E49H: no value follows.
5024
If the Z FLAG is set (a space or a comma), JUMP to 502CH to look the name up with Register E = a space as its third character.
5026
LD E,A 5F
Copy Register A (the third character, an apostrophe for the alternate pairs) into Register E.
5027
GOSUB to 5189H to wait for the key after the name into Register A.
502A
RET NZ C0
If the NZ FLAG is set (not a space or a comma), RETurn to the command loop at 4E49H: the name is too long.
502B
RET C D8
If the CARRY FLAG is set (ENTER), RETurn to the command loop at 4E49H: no value follows.
502C
LD HL,4F53H 21 53 4F
Load Register Pair HL with 4F53H, the table of the twelve register pair names, three characters each.
502F
LD B,0CH 06 0C
Load Register B with 0CH (12), the names to look at, counted down.
5031
LD A,(HL) 7E
Fetch the first character of the name at Register Pair HL into Register A.
5032
INC HL 23
INCrement Register Pair HL to the second character of the name.
5033
CP C B9
Compare Register A (the table's first character) against Register C (the first character typed).
5034
If the Z FLAG is set (they match), JUMP to 503BH to compare the second character.
5036
INC HL 23
INCrement Register Pair HL to the third character of the name.
5037
INC HL 23
INCrement Register Pair HL to the first character of the next name.
5038
DECrement Register B (the names left) and LOOP BACK to 5031H while it is not zero.
503A
RET C9
RETurn to the command loop at 4E49H: the name typed is not in the table, nothing is changed.
503B
LD A,(HL) 7E
Fetch the second character of the name at Register Pair HL into Register A.
503C
CP D BA
Compare Register A against Register D (the second character typed).
503D
If the NZ FLAG is set (no match), JUMP to 5036H to step to the next name.
503F
INC HL 23
INCrement Register Pair HL to the third character of the name.
5040
LD A,(HL) 7E
Fetch the third character of the name at Register Pair HL into Register A.
5041
SUB E 93
SUBtract Register E (the third character typed, a space or an apostrophe) from Register A: 00H and the Z FLAG when they match.
5042
If the NZ FLAG is set (no match), JUMP to 5037H to step to the next name.
5044
LD D,A 57
Copy Register A (00H) into Register D, the high byte of the offset into the save area.
5045
LD A,18H 3E 18
Load Register A with 18H (24), twice the number of names.
5047
SUB B 90
SUBtract Register B (the names left, 12 for AF down to 1 for PC) from Register A.
5048
SUB B 90
SUBtract Register B again from Register A: Register A = 24 less twice Register B = twice the name's place (0 for AF to 22 for PC).
5049
LD E,A 5F
Copy Register A (the offset) into Register E: Register Pair DE = the offset of the word in the save area.
504A
LD HL,4065H 21 65 40
Load Register Pair HL with 4065H, the first word of the register save area.
504D
ADD HL,DE 19
ADD Register Pair DE (the offset) to Register Pair HL: Register Pair HL = the word of the register pair named (4065H for AF to 407BH for PC).
504E
PUSH HL E5
Save Register Pair HL (the word's address) to the stack.
504F
LD A,1EH 3E 1E
Load Register A with 1EH, the control code that clears the rest of the line from the cursor.
5051
GOSUB to the ROM at 0033H to send the character in Register A (1EH) to the display: the rest of the bottom line is cleared for the value.
5054
POP DE D1
Restore Register Pair DE from the stack: the address of the word to change.
5055
GOSUB to 51A4H to read the new value: Register Pair HL = the number, the Z FLAG set when no digit was typed. A key that is not a hexadecimal digit ends the command at 4E49H.
5058
RET Z C8
If the Z FLAG is set (no value), RETurn to the command loop at 4E49H: the register pair is left as it is.
5059
EX DE,HL EB
Exchange Register Pairs DE and HL: Register Pair HL = the word's address, Register Pair DE = the new value.
505A
LD (HL),E 73
Store Register E (the low byte of the new value) at Register Pair HL, the word's low byte.
505B
INC HL 23
INCrement Register Pair HL to the word's high byte.
505C
LD (HL),D 72
Store Register D (the high byte of the new value) at Register Pair HL.
505D
RET C9
RETurn to the command loop at 4E49H, which shows the register pair with its new value.
505EH - C and I: Single Step
Runs the one instruction at the saved PC. The first byte (or, after a prefix DDH, FDH or EDH, the second) is looked up in one of the three tables at 50E0H: each entry is a mask, a value and a result; the first entry for which the byte AND the mask equals the value gives the result, and when none does the table's last byte is the result. Bits 3-0 of the result are the instruction's length, bits 7-4 its kind: 0 none, 1 JP (HL), 2 JP (IX) or JP (IY), 3 a relative jump (JR, DJNZ), 4 an absolute jump, 5 a return, 6 a call. A breakpoint is planted after the instruction (slot B); for kinds 1-5 a second one at the place it goes to (slot A): Register Pair HL from the save area, Index Register IY from the save area, the relative target, the operand, the return address on the program's stack. A call gets the second breakpoint at its operand for I only; for C it runs in full and stops after it. Then the program runs (4FA3H) and either breakpoint brings it back to DEBUG. A breakpoint that cannot be written (ROM) gives the command up (4FD0H). The RST instructions are not in the tables: they count as one byte with no target.
505E
PUSH AF F5
Save Register Pair AF (Register A = the key: 63H for C, 69H for I) to the stack, for 50B0H. When the instruction is not a call the word is left there; 4FA3H sets the Stack Pointer from the save area, so it does not matter.
505F
LD DE,(407BH) ED 5B 7B 40
Load Register Pair DE with the saved PC from 407BH-407CH, the address of the instruction to step.
5063
LD A,(DE) 1A
Fetch the instruction's first byte at Register Pair DE into Register A.
5064
LD HL,5115H 21 15 51
Load Register Pair HL with 5115H, the table for the instructions with the prefix DDH or FDH.
5067
CP DDH FE DD
Compare Register A (the first byte) against DDH, the prefix of the Index Register IX instructions.
5069
If the Z FLAG is set (DDH), JUMP to 5079H to look up the byte after the prefix in the table at 5115H.
506B
CP FDH FE FD
Compare Register A (the first byte) against FDH, the prefix of the Index Register IY instructions.
506D
If the Z FLAG is set (FDH), JUMP to 5079H to look up the byte after the prefix in the table at 5115H.
506F
LD HL,50E0H 21 E0 50
Load Register Pair HL with 50E0H, the table for the instructions with no prefix.
5072
CP EDH FE ED
Compare Register A (the first byte) against EDH, the prefix of the extended instructions.
5074
If the NZ FLAG is set (no prefix), JUMP to 507CH with Register A = the first byte and Register Pair HL = 50E0H.
5076
LD HL,510EH 21 0E 51
Load Register Pair HL with 510EH, the table for the instructions with the prefix EDH.
5079
INC DE 13
INCrement Register Pair DE to the byte after the prefix.
507A
LD A,(DE) 1A
Fetch the byte after the prefix at Register Pair DE into Register A.
507B
DEC DE 1B
DECrement Register Pair DE back to the instruction's address.
507C
LD C,A 4F
Copy Register A (the byte to look up: the first byte, or the one after the prefix) into Register C.
507D
LD A,(HL) 7E
Fetch the entry's mask at Register Pair HL into Register A.
507E
AND C A1
AND Register A (the mask) with Register C (the instruction byte).
507F
INC HL 23
INCrement Register Pair HL to the entry's value.
5080
CP (HL) BE
Compare Register A (the byte masked) against the value at Register Pair HL.
5081
INC HL 23
INCrement Register Pair HL to the entry's result. INC of a register pair does not change the flags.
5082
If the Z FLAG is set (the entry matches), JUMP to 508AH to take the result at Register Pair HL.
5084
INC HL 23
INCrement Register Pair HL to the first byte of the next entry.
5085
LD A,(HL) 7E
Fetch that byte at Register Pair HL into Register A: the next entry's mask, or the table's last byte.
5086
CP 05H FE 05
Compare Register A against 05H: every mask is 05H or more, while the last byte of a table, the result when nothing matches, is a length of 1 or 2 with kind 0.
5088
If the NO CARRY FLAG is set (a mask), LOOP BACK to 507DH to try the next entry. Otherwise Register Pair HL points at the table's last byte, taken as the result.
508A
LD A,(HL) 7E
Fetch the result at Register Pair HL into Register A: bits 7-4 the kind, bits 3-0 the length.
508B
LD B,A 47
Copy Register A (the result) into Register B, for 509AH.
508C
AND 0FH E6 0F
Mask Register A with 0FH, keeping the length of the instruction (1-4).
508E
LD L,A 6F
Copy Register A (the length) into Register L.
508F
LD H,00H 26 00
Load Register H with 00H: Register Pair HL = the length.
5091
ADD HL,DE 19
ADD Register Pair DE (the instruction's address) to Register Pair HL: Register Pair HL = the address of the next instruction.
5092
PUSH DE D5
Save Register Pair DE (the instruction's address) to the stack.
5093
LD DE,4062H 11 62 40
Load Register Pair DE with 4062H, the last byte of breakpoint slot B.
5096
GOSUB to 4FC9H to plant a breakpoint at Register Pair HL (the next instruction) in slot B; Register Pair DE comes back as 405FH, the last byte of slot A.
5099
POP HL E1
Restore Register Pair HL from the stack: the instruction's address.
509A
LD A,B 78
Copy Register B (the result) into Register A.
509B
AND F0H E6 F0
Mask Register A with F0H, keeping the kind of instruction in bits 7-4.
509D
If the Z FLAG is set (kind 0: no jump, call or return), JUMP to 50B5H to run the instruction; the breakpoint after it is enough.
509F
INC HL 23
INCrement Register Pair HL to the instruction's second byte (the offset of a relative jump, the operand of a jump or call).
50A0
CP 20H FE 20
Compare Register A (the kind in bits 7-4) against 20H: CARRY for kind 1, Z FLAG for kind 2.
50A2
If the CARRY FLAG is set (kind 1, JP (HL)), JUMP to 50D8H, inside the instruction at 50D7H, where LD HL,(406BH) takes the program's Register Pair HL as the target.
50A4
If the Z FLAG is set (kind 2, JP (IX) or JP (IY)), JUMP to 50CDH to take the target from the saved index register.
50A6
CP 40H FE 40
Compare Register A (the kind in bits 7-4) against 40H: CARRY for kind 3, Z FLAG for kind 4.
50A8
If the CARRY FLAG is set (kind 3, a relative jump), JUMP to 50C1H to add the offset.
50AA
If the Z FLAG is set (kind 4, an absolute jump), JUMP to 50BBH to take the operand at Register Pair HL as the target.
50AC
CP 60H FE 60
Compare Register A (the kind in bits 7-4) against 60H: CARRY for kind 5; kind 6 (a call) is left.
50AE
If the CARRY FLAG is set (kind 5, a return), JUMP to 50B8H to take the target from the program's stack.
50B0
POP AF F1
Kind 6, a call: Restore Register Pair AF from the stack: Register A = the key saved at 505EH.
50B1
CP 69H FE 69
Compare Register A (the key) against 69H, i, the I command.
50B3
If the Z FLAG is set (I), JUMP to 50BBH to plant the second breakpoint at the called address, so the step goes into the call.
50B5
JUMP to 4FA3H to run the program from the saved registers until a breakpoint brings it back. For C a call runs in full and stops at the breakpoint after it.
50B8
LD HL,(4079H) 2A 79 40
Kind 5, a return: Load Register Pair HL with the program's Stack Pointer from 4079H-407AH, where the return address is.
50BB
LD A,(HL) 7E
Fetch the low byte of the target at Register Pair HL (the operand, or the return address on the stack) into Register A.
50BC
INC HL 23
INCrement Register Pair HL to the high byte of the target.
50BD
LD H,(HL) 66
Fetch the high byte of the target at Register Pair HL into Register H.
50BE
LD L,A 6F
Copy Register A (the low byte) into Register L: Register Pair HL = the target address.
50BF
JUMP to 50DBH to plant the second breakpoint at Register Pair HL.
50C1
LD C,(HL) 4E
Kind 3, a relative jump: Fetch the offset at Register Pair HL (the instruction's second byte) into Register C.
50C2
XOR A AF
Set Register A to 00H (XOR A), the high byte of a positive offset.
50C3
BIT 7,C CB 79
Test bit 7 of Register C (the offset): set for a jump backwards.
50C5
If the Z FLAG is set (a positive offset), JUMP to 50C8H with Register A = 00H.
50C7
CPL 2F
Complement Register A: FFH, the high byte of a negative offset.
50C8
LD B,A 47
Copy Register A (00H or FFH) into Register B: Register Pair BC = the offset, sign extended to 16 bits.
50C9
INC HL 23
INCrement Register Pair HL to the address after the two byte jump, from which the offset counts.
50CA
ADD HL,BC 09
ADD Register Pair BC (the offset) to Register Pair HL: Register Pair HL = the target of the relative jump.
50CB
JUMP to 50DBH to plant the second breakpoint at Register Pair HL.
50CD
LD HL,(4075H) 2A 75 40
Kind 2, JP (IX) or JP (IY): Load Register Pair HL with the program's Index Register IX from 4075H-4076H.
50D0
BIT 5,C CB 69
Test bit 5 of Register C. Register C holds the byte after the prefix, E9H (from 507CH), not the prefix, and its bit 5 is set, so the Z FLAG is always clear here.
50D2
If the Z FLAG is set, JUMP to 50DBH with Register Pair HL = the saved IX. Since the Z FLAG is clear, the jump is never taken: JP (IX) is stepped like JP (IY), with the breakpoint at the address in the saved Index Register IY.
50D4
LD HL,(4077H) 2A 77 40
Load Register Pair HL with the program's Index Register IY from 4077H-4078H.
50D7
LD IX,(406BH) DD 2A 6B 40
Load Index Register IX with the word at 406BH-406CH (the program's Register Pair HL); IX is not used again before 4FA3H. Kind 1, JP (HL), comes in at 50D8H, the second byte of this instruction, where the bytes 2AH 6BH 40H read LD HL,(406BH): Register Pair HL = the program's Register Pair HL from the save area, the target of the JP (HL).
50DB
GOSUB to 4FC9H to plant the second breakpoint at Register Pair HL (the target) in slot A, which ends at Register Pair DE (405FH).
50DE
LOOP BACK to 50B5H to run the program from the saved registers until a breakpoint brings it back.
50E0H - The Instruction Tables of the Single Step (Data)
Three tables of entries of three bytes: a mask, a value and a result. The single step (507DH) takes the first entry for which the instruction byte AND the mask equals the value; each table ends with one byte, below 05H, that is the result when no entry matches. In a result, bits 3-0 are the length of the instruction in bytes and bits 7-4 its kind: 0 none, 1 JP (HL), 2 JP (IX) or JP (IY), 3 a relative jump, 4 an absolute jump, 5 a return, 6 a call. 50E0H is for the first byte of an instruction with no prefix, 510EH for the byte after EDH, 5115H for the byte after DDH or FDH.
50E0-50E2
DEFB C7H, C0H, 51H C7 C0 51
50E0H-50E2H: mask C7H, value C0H: C0H, C8H, D0H ... F8H, RET with a condition. Result 51H: kind 5 (a return), one byte.
50E3-50E5
DEFB FFH, C9H, 51H FF C9 51
50E3H-50E5H: mask FFH, value C9H: RET. Result 51H: kind 5 (a return), one byte.
50E6-50E8
DEFB FFH, E9H, 11H FF E9 11
50E6H-50E8H: mask FFH, value E9H: JP (HL). Result 11H: kind 1 (the target is the saved Register Pair HL), one byte.
50E9-50EB
DEFB CFH, 01H, 03H CF 01 03
50E9H-50EBH: mask CFH, value 01H: 01H, 11H, 21H, 31H, LD BC/DE/HL/SP with a 16 bit value. Result 03H: kind 0, three bytes.
50EC-50EE
DEFB E7H, 22H, 03H E7 22 03
50ECH-50EEH: mask E7H, value 22H: 22H, 2AH, 32H, 3AH, LD (nn),HL, LD HL,(nn), LD (nn),A and LD A,(nn). Result 03H: kind 0, three bytes.
50EF-50F1
DEFB C7H, C2H, 43H C7 C2 43
50EFH-50F1H: mask C7H, value C2H: C2H, CAH ... FAH, JP with a condition. Result 43H: kind 4 (an absolute jump), three bytes.
50F2-50F4
DEFB FFH, C3H, 43H FF C3 43
50F2H-50F4H: mask FFH, value C3H: JP. Result 43H: kind 4 (an absolute jump), three bytes.
50F5-50F7
DEFB C7H, C4H, 63H C7 C4 63
50F5H-50F7H: mask C7H, value C4H: C4H, CCH ... FCH, CALL with a condition. Result 63H: kind 6 (a call), three bytes.
50F8-50FA
DEFB FFH, CDH, 63H FF CD 63
50F8H-50FAH: mask FFH, value CDH: CALL. Result 63H: kind 6 (a call), three bytes.
50FB-50FD
DEFB C7H, 06H, 02H C7 06 02
50FBH-50FDH: mask C7H, value 06H: 06H, 0EH ... 3EH, LD of a register or (HL) with an 8 bit value. Result 02H: kind 0, two bytes.
50FE-5100
DEFB F7H, D3H, 02H F7 D3 02
50FEH-5100H: mask F7H, value D3H: D3H and DBH, OUT (n),A and IN A,(n). Result 02H: kind 0, two bytes.
5101-5103
DEFB C7H, C6H, 02H C7 C6 02
5101H-5103H: mask C7H, value C6H: C6H, CEH ... FEH, the arithmetic and logic instructions with an 8 bit value (ADD A,n to CP n). Result 02H: kind 0, two bytes.
5104-5106
DEFB FFH, CBH, 02H FF CB 02
5104H-5106H: mask FFH, value CBH: the prefix of the bit, shift and rotate instructions. Result 02H: kind 0, two bytes.
5107-5109
DEFB F7H, 10H, 32H F7 10 32
5107H-5109H: mask F7H, value 10H: 10H and 18H, DJNZ and JR. Result 32H: kind 3 (a relative jump), two bytes.
510A-510C
DEFB E7H, 20H, 32H E7 20 32
510AH-510CH: mask E7H, value 20H: 20H, 28H, 30H, 38H, JR with a condition. Result 32H: kind 3 (a relative jump), two bytes.
510D
DEFB 01H 01
510DH: the end of the table for no prefix: 01H, one byte of kind 0, for every other instruction (the RST instructions among them).
510E-5110
DEFB C7H, 43H, 04H C7 43 04
510EH-5110H: after EDH, mask C7H, value 43H: 43H, 4BH ... 7BH, LD (nn) from and to BC, DE, HL and SP. Result 04H: kind 0, four bytes.
5111-5113
DEFB F7H, 45H, 52H F7 45 52
5111H-5113H: after EDH, mask F7H, value 45H: 45H and 4DH, RETN and RETI. Result 52H: kind 5 (a return), two bytes.
5114
DEFB 02H 02
5114H: the end of the table for EDH: 02H, two bytes of kind 0, for every other instruction after EDH.
5115-5117
DEFB FEH, 34H, 03H FE 34 03
5115H-5117H: after DDH or FDH, mask FEH, value 34H: 34H and 35H, INC (IX+d) and DEC (IX+d). Result 03H: kind 0, three bytes.
5118-511A
DEFB C0H, 40H, 03H C0 40 03
5118H-511AH: after DDH or FDH, mask C0H, value 40H: 40H-7FH, the loads with (IX+d). Result 03H: kind 0, three bytes.
511B-511D
DEFB C0H, 80H, 03H C0 80 03
511BH-511DH: after DDH or FDH, mask C0H, value 80H: 80H-BFH, the arithmetic and logic instructions with (IX+d). Result 03H: kind 0, three bytes.
511E-5120
DEFB FFH, 21H, 04H FF 21 04
511EH-5120H: after DDH or FDH, mask FFH, value 21H: LD IX,nn. Result 04H: kind 0, four bytes.
5121-5123
DEFB FFH, 22H, 04H FF 22 04
5121H-5123H: after DDH or FDH, mask FFH, value 22H: LD (nn),IX. Result 04H: kind 0, four bytes.
5124-5126
DEFB FFH, 2AH, 04H FF 2A 04
5124H-5126H: after DDH or FDH, mask FFH, value 2AH: LD IX,(nn). Result 04H: kind 0, four bytes.
5127-5129
DEFB FFH, 36H, 04H FF 36 04
5127H-5129H: after DDH or FDH, mask FFH, value 36H: LD (IX+d),n. Result 04H: kind 0, four bytes.
512A-512C
DEFB FFH, CBH, 04H FF CB 04
512AH-512CH: after DDH or FDH, mask FFH, value CBH: the bit, shift and rotate instructions with (IX+d). Result 04H: kind 0, four bytes.
512D-512F
DEFB FFH, E9H, 22H FF E9 22
512DH-512FH: after DDH or FDH, mask FFH, value E9H: JP (IX) and JP (IY). Result 22H: kind 2, two bytes.
5130
DEFB 02H 02
5130H: the end of the table for DDH and FDH: 02H, two bytes of kind 0, for every other instruction after the prefix (PUSH IX, ADD IX,BC and the like).
5131H - Show Sixteen Bytes of Memory
Register Pair HL = the first address. Shows => and a space, then the sixteen bytes, each after one separator character (5164H): in hexadecimal, two digits; with 405DH = 61H (the A command), a space and the byte as a character, a period for 00H-1FH and C0H-FFH. Register Pair HL ends sixteen bytes further on. Register Pair BC is kept.
5131
PUSH BC C5
Save Register Pair BC (Register B = the caller's line counter) to the stack, since Register B counts the bytes here.
5132
LD A,3DH 3E 3D
Load Register A with 3DH, an equals sign, the first character of =>.
5134
GOSUB to the ROM at 0033H to display the character in Register A (=).
5137
INC A 3C
INCrement Register A to 3EH, the greater than sign.
5138
GOSUB to the ROM at 0033H to display the character in Register A (>): the line now shows =>.
513B
GOSUB to 51F1H to display a space after the => before the first byte.
513E
LD B,10H 06 10
Load Register B with 10H (16), the bytes of the line, counted down.
5140
GOSUB to 5164H to display the separator before the byte at Register Pair HL: a space, a bar on either side of the M address's byte, and one more space before the ninth byte.
5143
LD A,(405DH) 3A 5D 40
Fetch the memory display mode from 405DH into Register A: 61H after the A command.
5146
CP 61H FE 61
Compare Register A (the mode) against 61H, a.
5148
If the NZ FLAG is set (hexadecimal), JUMP to 515DH, where the CALL NZ shows the byte as two hexadecimal digits.
514A
GOSUB to 51F1H to display a space: in the character mode each byte takes three places, as in hexadecimal.
514D
LD A,(HL) 7E
Fetch the byte at Register Pair HL into Register A.
514E
CP 20H FE 20
Compare Register A (the byte) against 20H, the first character that is shown as itself.
5150
If the CARRY FLAG is set (00H-1FH, the control codes), JUMP to 5156H to show a period instead.
5152
CP C0H FE C0
Compare Register A (the byte) against C0H, the first of the space compression codes.
5154
If the CARRY FLAG is set (20H-BFH: characters and graphics), JUMP to 5158H to show the byte as it is.
5156
LD A,2EH 3E 2E
Load Register A with 2EH, a period, shown for a byte that is a control code or a space compression code.
5158
GOSUB to the ROM at 0033H to display Register A, the byte or the period.
515B
INC HL 23
INCrement Register Pair HL to the next byte of memory to show.
515C
XOR A AF
Set Register A to 00H (XOR A): the Z FLAG is set, so the CALL NZ that follows is not made in the character mode.
515D
If the NZ FLAG is set (hexadecimal), GOSUB to 51D1H to display the byte at Register Pair HL as two hexadecimal digits and step Register Pair HL to the next byte.
5160
DECrement Register B (the bytes left) and LOOP BACK to 5140H while it is not zero.
5162
POP BC C1
Restore Register Pair BC (the caller's line counter in Register B) from the stack.
5163
RET C9
RETurn to the caller with Register Pair HL at the address after the sixteen bytes.
5164H - The Separator before a Byte
Register Pair HL = the address of the byte about to be shown, Register B = the bytes left on the line (16 down to 1). Before the byte at the M address (4060H-4061H) the code AAH is shown, a graphics character lit on its right half: a bar just left of the byte. Before the byte after it the code 95H is shown, lit on its left half: a bar just right of the M address's byte. Before any other byte a space. Before the ninth byte of the line (Register B = 08H) one more space splits the line in two halves of eight.
5164
LD DE,(4060H) ED 5B 60 40
Load Register Pair DE with the M address from 4060H-4061H.
5168
INC DE 13
INCrement Register Pair DE: the address of the byte after the M address's byte.
5169
PUSH HL E5
Save Register Pair HL (the address of the byte about to be shown) to the stack.
516A
XOR A AF
Set Register A to 00H (XOR A), which also clears the CARRY FLAG for the SBC.
516B
SBC HL,DE ED 52
SUBtract Register Pair DE (the M address plus one) from Register Pair HL with the CARRY FLAG: the Z FLAG is set when the byte about to be shown is the one after the M address's byte.
516D
LD A,95H 3E 95
Load Register A with 95H, the graphics character lit on its left half: the bar on the right of the M address's byte. LD does not change the flags.
516F
If the Z FLAG is set (the byte after the M address), JUMP to 517EH to show 95H.
5171
GOSUB to 5182H to show the extra space when this is the ninth byte (Register B = 08H).
5174
INC HL 23
INCrement Register Pair HL: Register Pair HL = the address about to be shown less the M address, 0000H when they are the same.
5175
LD A,L 7D
Copy Register L (the low byte of the difference) into Register A.
5176
OR H B4
OR Register H into Register A: the Z FLAG is set when Register Pair HL is 0000H, the byte at the M address.
5177
POP HL E1
Restore Register Pair HL (the address of the byte about to be shown) from the stack.
5178
LD A,AAH 3E AA
Load Register A with AAH, the graphics character lit on its right half: the bar on the left of the M address's byte. LD does not change the flags.
517A
If the Z FLAG is set (the byte at the M address), JUMP to 51EBH to show Register A (AAH) and return.
517C
JUMP to 5186H, which jumps to 51F1H to show a space and return.
517E
GOSUB to the ROM at 0033H to show the character in Register A (95H), the bar after the M address's byte.
5181
POP HL E1
Restore Register Pair HL (the address of the byte about to be shown) from the stack.
5182
LD A,B 78
Copy Register B (the bytes left on the line) into Register A.
5183
CP 08H FE 08
Compare Register A against 08H: the Z FLAG is set for the ninth byte of the line.
5185
RET NZ C0
If the NZ FLAG is set (not the ninth byte), RETurn to the caller.
5186
JUMP to 51F1H to show a space and return: the extra space before the ninth byte, or the separator before a byte that has no bar.
5188
DEFB 00H 00
5188H: 00H, a byte no code reaches: the JR at 5186H jumps over it and 5189H is the next entry. It is shown as data.
5189H - Read One Key of a Command
Waits for a key and shows it at the cursor. ENTER returns at once, not shown, with the Z FLAG and the CARRY FLAG set. Keys below 20H are ignored. Any other key is made lower case (bit 5 set) and shown, and returns with the CARRY FLAG clear and the Z FLAG set for a comma or a space, clear for anything else. Register Pair DE is kept. SYS9/SYS's extended debugger changes the byte at 5196H (EFH, the SET 5,A of 5195H) to 6FH while text is typed, making the instruction BIT 5,A so that capitals are kept, and puts EFH back afterwards.
5189
PUSH DE D5
Save Register Pair DE to the stack: the ROM's keyboard routine changes it.
518A
GOSUB to the ROM at 0049H to wait for a key: Register A = its character.
518D
CP 0DH FE 0D
Compare Register A (the key) against 0DH, ENTER.
518F
If the Z FLAG is set (ENTER), JUMP to 51A1H to return with the CARRY FLAG set.
5191
CP 20H FE 20
Compare Register A (the key) against 20H, a space: the CARRY FLAG is set for a control code (00H-1FH).
5193
If the CARRY FLAG is set (a control code, such as BACKSPACE, which DEBUG does not take), LOOP BACK to 518AH to wait for another key.
5195
SET 5,A CB EF
Set bit 5 of Register A: a capital letter becomes lower case; digits, the space, the comma and the semicolon have bit 5 set already. SYS9/SYS writes 6FH at 5196H to make this BIT 5,A, which leaves Register A as typed.
5197
GOSUB to the ROM at 0033H to show Register A (the key) at the cursor.
519A
POP DE D1
Restore Register Pair DE from the stack, as the caller had it.
519B
CP 2CH FE 2C
Compare Register A (the key) against 2CH, a comma.
519D
RET Z C8
If the Z FLAG is set (a comma), RETurn to the caller with the Z FLAG set and the CARRY FLAG clear.
519E
CP 20H FE 20
Compare Register A (the key) against 20H, a space: the Z FLAG is set for a space; Register A is 20H or more, so the CARRY FLAG is clear.
51A0
RET C9
RETurn to the caller: the Z FLAG set for a space, clear for any other key, the CARRY FLAG clear.
51A1
POP DE D1
ENTER: Restore Register Pair DE from the stack.
51A2
SCF 37
Set the CARRY FLAG: ENTER. The Z FLAG is still set from the CP 0DH at 518DH.
51A3
RET C9
RETurn to the caller with the Z FLAG and the CARRY FLAG set.
51A4H - Read a Hexadecimal Number
Reads keys until a comma, a space or ENTER. When that is the first key, returns at once with the Z FLAG set (the CARRY FLAG too for ENTER) and Register Pair HL as it was. Otherwise Register Pair HL = the number, the last four digits typed, and the Z FLAG is clear; the CARRY FLAG is set when ENTER ended it. A key that is not a hexadecimal digit ends the command: JP C,4E49H back to the command loop, which resets the Stack Pointer (the X key is used for this). SYS9/SYS calls this routine for its own commands.
51A4
GOSUB to 5189H to wait for the first key: Register A = the key, the Z FLAG set for a comma, a space or ENTER (with the CARRY FLAG for ENTER).
51A7
RET Z C8
If the Z FLAG is set (no digits), RETurn to the caller with Register Pair HL unchanged and the flags from 5189H.
51A8
LD HL,0000H 21 00 00
Load Register Pair HL with 0000H, the number so far.
51AB
GOSUB to 51C0H to turn Register A (the key) into its digit value 00H-0FH; the CARRY FLAG is set when it is not a hexadecimal digit.
51AE
If the CARRY FLAG is set (not a hexadecimal digit), JUMP to 4E49H, the command loop: the command is given up.
51B1
ADD HL,HL 29
ADD Register Pair HL to itself: the number times 2.
51B2
ADD HL,HL 29
ADD Register Pair HL to itself: the number times 4.
51B3
ADD HL,HL 29
ADD Register Pair HL to itself: the number times 8.
51B4
ADD HL,HL 29
ADD Register Pair HL to itself: the number times 16, one hexadecimal digit to the left; a digit shifted out of bit 15 is lost, so only the last four count.
51B5
OR L B5
OR Register L (its low four bits now 0) into Register A (the digit value).
51B6
LD L,A 6F
Copy Register A into Register L: Register Pair HL = the number with the new digit at the right.
51B7
GOSUB to 5189H to wait for the next key into Register A.
51BA
If the NZ FLAG is set (not a comma, a space or ENTER), LOOP BACK to 51ABH to take it as the next digit.
51BC
RRA 1F
Rotate Register A (the key that ended the number: 2CH, 20H or 0DH) right through the CARRY FLAG, which is set only for ENTER: 16H, 10H, or 86H with the CARRY FLAG set again from bit 0 of 0DH.
51BD
ADC A,81H CE 81
ADD 81H and the CARRY FLAG to Register A: 97H or 91H with no carry for a comma or a space, 08H with a carry for ENTER. The result is never 00H, so the Z FLAG is clear: a number was read; the CARRY FLAG is set only for ENTER.
51BF
RET C9
RETurn to the caller with Register Pair HL = the number, the Z FLAG clear and the CARRY FLAG set for ENTER.
51C0H - Hexadecimal Digit to Its Value
Register A = a character. Returns Register A = 00H-0FH with the CARRY FLAG clear for 0-9 and a-f (the keys come lower case from 5189H), or the CARRY FLAG set for any other character. Each test is an addition that carries out of Register A when the character is past the end of a range.
51C0
SUB 30H D6 30
SUBtract 30H from Register A: 0-9 become 00H-09H; a character below 0 borrows.
51C2
RET C D8
If the CARRY FLAG is set (below 30H), RETurn: not a digit.
51C3
ADD A,C9H C6 C9
ADD C9H to Register A: the value 37H, the character 67H (g), and above carry out.
51C5
RET C D8
If the CARRY FLAG is set (67H or above), RETurn: not a hexadecimal digit.
51C6
ADD A,06H C6 06
ADD 06H to Register A: the CARRY FLAG is set for the characters 61H-66H (a-f), which now sit at FDH + 06H and above.
51C8
If the CARRY FLAG is set (a-f), JUMP to 51CDH to make the value 0AH-0FH.
51CA
ADD A,27H C6 27
ADD 27H to Register A: the characters 3AH-60H (between 9 and a) carry out; 0-9 are now F6H-FFH.
51CC
RET C D8
If the CARRY FLAG is set (3AH-60H), RETurn: not a hexadecimal digit.
51CD
ADD A,0AH C6 0A
ADD 0AH to Register A: 0-9 become 00H-09H and a-f become 0AH-0FH, both with a carry out of Register A.
51CF
OR A B7
Set the flags from Register A (OR A): the CARRY FLAG is cleared, a hexadecimal digit.
51D0
RET C9
RETurn with Register A = the digit's value and the CARRY FLAG clear.
51D1H - Hexadecimal Output
51D1H shows the byte at Register Pair HL and steps Register Pair HL past it; 51D5H shows Register Pair HL as four digits; 51DAH shows Register A as two digits; 51E3H shows bits 3-0 of Register A as one digit. Each digit goes to the ROM's display routine at 0033H, which 51EBH jumps to. SYS9/SYS calls 51D1H, 51D5H and 51DAH too.
51D1
LD A,(HL) 7E
Fetch the byte at Register Pair HL into Register A.
51D2
INC HL 23
INCrement Register Pair HL to the next byte, past the one being shown.
51D3
JUMP to 51DAH to show Register A (the byte) as two hexadecimal digits.
51D5
LD A,H 7C
Copy Register H (the high byte of Register Pair HL) into Register A.
51D6
GOSUB to 51DAH to show Register A (the high byte) as two hexadecimal digits.
51D9
LD A,L 7D
Copy Register L (the low byte of Register Pair HL) into Register A, and go on into 51DAH to show it.
51DA
PUSH AF F5
Save Register Pair AF (Register A = the byte to show) to the stack, for its low digit.
51DB
RRA 1F
Rotate Register A right through the CARRY FLAG (the first of four).
51DC
RRA 1F
Rotate Register A right through the CARRY FLAG (the second of four).
51DD
RRA 1F
Rotate Register A right through the CARRY FLAG (the third of four).
51DE
RRA 1F
Rotate Register A right through the CARRY FLAG (the fourth of four): bits 7-4 of the byte are now in bits 3-0 of Register A.
51DF
GOSUB to 51E3H to show bits 3-0 of Register A (the high digit of the byte).
51E2
POP AF F1
Restore Register Pair AF (Register A = the byte) from the stack, and go on into 51E3H to show its low digit.
51E3
AND 0FH E6 0F
Mask Register A with 0FH, keeping one hexadecimal digit (00H-0FH).
51E5
ADD A,90H C6 90
ADD 90H to Register A: 90H-99H for 0-9, 9AH-9FH for 0AH-0FH.
51E7
DAA 27
Decimal adjust Register A: 90H-99H stay with no carry; 9AH-9FH become 00H-05H with the CARRY FLAG set.
51E8
ADC A,40H CE 40
ADD 40H and the CARRY FLAG to Register A: D0H-D9H for 0-9, 41H-46H for 0AH-0FH.
51EA
DAA 27
Decimal adjust Register A: D0H-D9H become 30H-39H, the characters 0-9; 41H-46H stay, the characters A-F.
51EB
JUMP to the ROM at 0033H to display Register A; its RET returns to the caller. 517AH, 51F3H and 51FDH jump here too.
51EEH - A Byte and a Space, or a Space
51EEH shows Register A as two hexadecimal digits and a space; 51F1H shows only the space. SYS9/SYS calls 51F1H.
51EE
GOSUB to 51DAH to show Register A as two hexadecimal digits, and go on into 51F1H for the space.
51F1
LD A,20H 3E 20
Load Register A with 20H, a space, the character to display.
51F3
JUMP to 51EBH to display Register A (the space) through the ROM at 0033H and return.
51F5H - Show Three Characters
Shows the three bytes from Register Pair HL as characters (the register pair names at 4F53H) and leaves Register Pair HL past them: 51F5H calls 51FBH twice and then goes on into it.
51F5
GOSUB to 51FBH to show the character at Register Pair HL and step past it: the first character.
51F8
GOSUB to 51FBH to show the character at Register Pair HL and step past it: the second character, then go on into 51FBH for the third.
51FB
LD A,(HL) 7E
Fetch the character at Register Pair HL into Register A.
51FC
INC HL 23
INCrement Register Pair HL to the next character.
51FD
JUMP to 51EBH to display Register A (the character) through the ROM at 0033H and return.