TRS-80 DOS - NEWDOS/80 v2.0 for the Model III - SYS5/SYS Disassembled

Page Customization

Introduction/Summary

NEWDOS/80 v2.0 SYS5/SYS Disassembly - DEBUG (Model III)

SYS5/SYS is DEBUG, the machine language monitor of this DOS. It loads into the overlay area at 4D00H-51E7H (1,256 bytes in five load records, transfer address 4D00H). SYS0/SYS enters it with PUSH AF / LD A,27H / RST 28H at 45D4H, the target of RST 30H (400FH) and of the DEBUG vector 440DH. Those are reached when a breakpoint (F7H = RST 30H) is executed, when the 1-2-3 key combination is pressed (SYS0/SYS 459DH, entering at 45D5H), and when a program is loaded and run after the DEBUG command (SYS2/SYS enters 440DH instead of starting the program when bit 7 of 4289H is set). There is only one function: SYS5/SYS does not look at the RST 28H code.

DEBUG saves every register of the interrupted program, removes its breakpoints, draws the screen and reads one-line commands on the bottom line. The page shows every byte of the file once, in address order.

Commands

All numbers are hexadecimal except the sector number of L and WR. A line may start with 2 or 3 to make D, ; and - act on the second or third memory window instead of the first. A wrong command, a bad number or a forbidden address displays Error; DEBUG then waits for ENTER.

CommandWhat it does
XRegister display: three windows of 4 lines x 16 bytes, each followed by a line of four registers (4FC7H). This is the form after a reset (42C4H = 01H as loaded by SYS0/SYS).
SFull screen display: 16 lines x 16 bytes, the 256-byte page holding the first window's address (5034H).
DaddrSet the window's address (4EB5H).
; and -Move the window forward or back: 40H bytes in the X form, 100H in the S form (4ECFH).
MaddrChange memory digit by digit with a blinking cursor, in the S form (4F0AH).
Rrr,valueChange a register: AF, BC, DE, HL, AF', BC', DE', HL', PC, SP, IX or IY (4DCDH).
G[addr][,bp][,bp]Resume the program, at addr if given, with up to two breakpoints at 5200H or above (4D79H).
IRun one instruction (5140H).
CRun one instruction; a CALL runs to its end.
Faddr,b1,b2...Find a byte string from addr up; F alone finds the next occurrence (4E03H).
Ld,sectorRead a sector (decimal number from the start of the diskette) into 4300H and show it (4E59H).
WRd,sectorWrite 4300H to the sector, keeping its data mark, and read it back (4E6BH).
QAbandon the program and go to DOS READY through SYS1/SYS function 7 sub-function 0CH (4EACH).

L and WR display Error when bit 7 of 428CH is set (option AA, passwords are checked), so the disk cannot be read or changed around the passwords.

Breakpoints and Single Steps

A breakpoint is an F7H (RST 30H) written over the first byte of an instruction. The two breakpoints are kept at 4052H-4057H (address and original byte for each). When DEBUG is entered every breakpoint that still holds F7H gets its byte back, and if the program stopped at one of them the resume PC is moved back by one so that the instruction runs when the program continues (4D27H).

I and C work the same way: DEBUG decodes the instruction at the PC just far enough to know its length and whether it branches (5140H, table at 510CH), puts breakpoints on the instruction that follows and on the branch target (a conditional JP, JR, DJNZ, CALL or RET can go either way; JP, JR, JP (HL), JP (IX), JP (IY), RET, RETN and RETI only to the target; for RET the target is read from the program's stack), and resumes the program. C puts no breakpoint on a CALL's target, so the subroutine runs at full speed. An RST is treated as a one-byte instruction, so with I and C alike it runs to its end. Every breakpoint address must be 5200H or above, so an I into a ROM or DOS routine displays Error; C steps over it.

The length decoding has two slips: DD 39H / FD 39H (ADD IX,SP and ADD IY,SP, two bytes) is counted as three bytes (513CH), and OUTI, OUTD, OTIR and OTDR (ED A3H, ABH, B3H, BBH, two bytes) as four (51A6H), so stepping over one of them puts the breakpoint past the next instruction.

Register Save Area

The registers are pushed on the program's own stack at 4D00H. The base address (the stack pointer after the pushes) is kept in 4D44H. The PC and SP are kept in the operands at 4DC7H and 4DC3H and used when the program is resumed at 4DA1H.

OffsetRegisterOffsetRegister
+00HIY+0CHDE
+02HIX+0EHBC
+04HHL'+10HHL
+06HDE'+12HAF
+08HBC'+14HPC (copied to 4DC7H)
+0AHAF'+16Hthe program's stack pointer (stored at 4DC3H)

DEBUG itself also runs on the program's stack, below the save area.

Variables

Memory Used by SYS5/SYS

Address
Size
Contents
4052H-4057H
6 bytes
Breakpoints
The two breakpoints: the address (2 bytes) and the original byte, set at 4DA7H-4DACH and removed at 4D2CH-4D36H. 00H in the SYS0/SYS file (address 0000H, in the ROM, where a write has no effect).
404CH-4051H
6 bytes
Memory Windows
The addresses of memory windows 1, 2 and 3 (404CH, 404EH, 4050H). The S form, M, F, L and WR use window 1.
4020H-4021H
2 bytes
Cursor Position
The ROM cursor address, set to the bottom line (3FC0H) at 4D50H before the command is read.
428CH
1 byte
Options
Bit 7 (option AA, passwords checked) refuses L and WR (4E87H). Bit 4, which the SYS0/SYS reset always sets (its 4E7FH), shows 21H-7FH as characters (5052H).
42C4H
1 byte
Display Form
01H the X form (as loaded with SYS0/SYS), 00H the S form. Set by X, S, F, L, WR and M.
4D44H-4D45H
2 bytes
Save Area Base (Self-Modifying Code)
Operand of the LD SP,nnnn at 4D43H, stored at 4D0DH: the base of the register save area. Read by 50C9H and 5192H.
4DC3H-4DC4H
2 bytes
Program Stack Pointer (Self-Modifying Code)
Operand of the LD SP,nnnn at 4DC2H, stored at 4D1FH or by R SP: register SP.
4DC7H-4DC8H
2 bytes
Resume PC (Self-Modifying Code)
Operand of the LD HL,nnnn at 4DC6H, stored at 4D18H, 4D3CH, 4D86H or by R PC: register PC.
4E08H-4E09H
2 bytes
Last Match (Self-Modifying Code)
Operand of the LD DE,nnnn at 4E07H, stored at 4E4BH: the address of the last match of F.
4E0CH
1 byte
String Length (Self-Modifying Code)
Operand of the LD B,nn at 4E0BH, stored at 4E2FH: the length of the F byte string.
4EBDH-4EBEH
2 bytes
Chosen Window (Self-Modifying Code)
Operand of the LD HL,nnnn at 4EBCH, stored at 4D6AH: where the address of the window chosen for this command is kept (404CH, 404EH or 4050H).
51E8H-51FFH
24 bytes
F String and Command Line
Not in the file. The F byte string from 51E8H, and the command line (up to 18 characters and 0DH) from 51ECH. They overlap: after a new command line only the first four bytes of the string are left for F without parameters.
3C00H-3FFFH
1,024 bytes
Screen
Drawn by 4FC7H and 503BH; the M cursor blinks at the digit (4F39H).

Outside Routines Called

AddressContents
0040HROM: read a line (4D58H).
0049HROM: wait for a key (50BFH).
002BHROM: scan the keyboard (4FBAH).
RST 18HROM: compare Register Pair HL with Register Pair DE (4D38H).
44D2H, 44D7HSYS0/SYS: display Register Pair DE or Register A in hexadecimal at Register Pair HL (503FH, 504FH, 5009H).
4467HSYS0/SYS: display a message (4FCAH, 50BCH).
4548HSYS0/SYS: upper case (4D71H, 4FBEH).
45DBH, 45DFH, 45EBH, 45E7HSYS0/SYS: read, verify read, write, and write with the directory mark (4E61H, 4E78H, 4E7BH, 4E82H).
4723HSYS0/SYS: select a drive (4E93H).
4BC5HSYS0/SYS: the end of the RST 28H dispatcher, used to resume the program (4DCAH).
4C39HSYS0/SYS: multiply Register Pair HL by Register A (508BH).
4C92HSYS0/SYS: delay (4D24H).
RST 28H, code E3HSYS1/SYS function 7 sub-function 0CH, the Q command (4EB4H).

Disassembly

4D00H - Entry: Save the Registers

SYS5/SYS is DEBUG. SYS0/SYS reaches it through 45D4H (the target of RST 30H at 400FH and of the DEBUG vector 440DH), which pushes AF and does LD A,27H / RST 28H. The dispatcher drops the RST return address and CALLs 4D00H, so on entry the stack holds 4BC5H (the dispatcher's return), the program's AF, and the program's PC (the address after the RST 30H, or the return address of a CALL 440DH). All registers are pushed below them; the Stack Pointer after the pushes is the base of the register save area, kept at 4D44H: +00H IY, +02H IX, +04H HL', +06H DE', +08H BC', +0AH AF', +0CH DE, +0EH BC, +10H HL, +12H AF, +14H PC, and +16H is the program's Stack Pointer.

4D00
EX (SP),HL E3
Exchange Register Pair HL with the word at the top of the stack (Stack Pointer): Register Pair HL = 4BC5H, the dispatcher's return address, which is not needed; the program's HL goes onto the stack in its place (save area +10H).
4D01
PUSH BC C5
Save Register Pair BC (the program's) onto the stack, save area +0EH.
4D02
PUSH DE D5
Save Register Pair DE (the program's) onto the stack, save area +0CH.
4D03
EX AF,AF' 08
Exchange Register Pair AF with the alternate AF': the main AF held the RST 28H code 27H, and the program's AF is already on the stack (+12H). The main AF now holds the program's AF'.
4D04
EXX D9
Exchange Register Pairs BC, DE and HL with the alternate set (EXX): the main set now holds the program's BC', DE' and HL'.
4D05
PUSH AF F5
Save Register Pair AF (the program's AF') onto the stack, save area +0AH.
4D06
PUSH BC C5
Save Register Pair BC (the program's BC') onto the stack, save area +08H.
4D07
PUSH DE D5
Save Register Pair DE (the program's DE') onto the stack, save area +06H.
4D08
PUSH HL E5
Save Register Pair HL (the program's HL') onto the stack, save area +04H.
4D09
PUSH IX DD E5
Save Index Register IX (the program's) onto the stack, save area +02H.
4D0B
PUSH IY FD E5
Save Index Register IY (the program's) onto the stack, save area +00H.
4D0D
LD (4D44H),SP ED 73 44 4D
Store the Stack Pointer, the base of the save area, at 4D44H, the operand of the LD SP,nnnn at 4D43H. 50C9H and 5192H also read it there.
4D11
LD HL,0014H 21 14 00
Load Register Pair HL with 0014H, the offset of the saved PC in the save area.
4D14
ADD HL,SP 39
ADD the Stack Pointer (the base of the save area) to Register Pair HL: Register Pair HL = the address of the saved PC.
4D15
LD E,(HL) 5E
Fetch the low byte of the program's PC at Register Pair HL into Register E.
4D16
INC HL 23
INCrement Register Pair HL to the high byte of the saved PC.
4D17
LD D,(HL) 56
Fetch the high byte at Register Pair HL into Register D: Register Pair DE = the program's PC.
4D18
LD (4DC7H),DE ED 53 C7 4D
Store Register Pair DE (the program's PC) at 4DC7H, the operand of the LD HL,nnnn at 4DC6H: the PC to resume at.
4D1C
INC HL 23
INCrement Register Pair HL to save area +16H: this address is the program's Stack Pointer, the stack as it was before the RST 30H or the CALL.
4D1D
DEC DE 1B
DECrement Register Pair DE to PC minus 1. After a breakpoint (RST 30H, one byte) this is the address of the breakpoint itself.
4D1E
PUSH DE D5
Save Register Pair DE (PC minus 1) onto the stack for the breakpoint check at 4D37H.
4D1F
LD (4DC3H),HL 22 C3 4D
Store Register Pair HL (the program's Stack Pointer) at 4DC3H, the operand of the LD SP,nnnn at 4DC2H, used when the program resumes and shown as register SP.
4D22
LD B,80H 06 80
Load Register B with 80H, the length of the delay.
4D24
GOSUB to 4C92H (SYS0/SYS) to wait Register B x 256 passes of the ROM delay at 0060H (times option BJ), so that the key that stopped the program is let go.

4D27H - Remove the Breakpoints

The two breakpoints of the G command are kept at 4052H-4057H in three-byte entries: the address (2 bytes) and the byte that the F7H (RST 30H) replaced. Each one that still holds F7H gets its original byte back. If the program stopped at one of them (PC minus 1 equals its address), the resume PC is backed up to that address so that the replaced instruction runs when the program goes on.

4D27
LD HL,4052H 21 52 40
Point Register Pair HL to 4052H, the breakpoint table.
4D2A
LD B,02H 06 02
Load Register B with 02H: two entries in the breakpoint table.

Breakpoint Loop
Register Pair HL = the entry, Register B = the entries left.

4D2C
LD E,(HL) 5E
Fetch the low byte of the breakpoint address at Register Pair HL into Register E.
4D2D
INC HL 23
INCrement Register Pair HL to the high byte of the address.
4D2E
LD D,(HL) 56
Fetch the high byte at Register Pair HL into Register D: Register Pair DE = the breakpoint address.
4D2F
INC HL 23
INCrement Register Pair HL to the saved original byte of the entry.
4D30
LD A,(DE) 1A
Fetch the byte now at the breakpoint address (Register Pair DE) into Register A.
4D31
CP F7H FE F7
Compare Register A against F7H, the RST 30H that marks a breakpoint in place.
4D33
If the NZ FLAG is set (no F7H there: the breakpoint was already removed, or the address is in the ROM), JUMP to 4D40H.
4D35
LD A,(HL) 7E
Fetch the saved original byte at Register Pair HL into Register A.
4D36
LD (DE),A 12
Store Register A (the original byte) at the breakpoint address (Register Pair DE).
4D37
EX (SP),HL E3
Exchange Register Pair HL with the word at the top of the stack (Stack Pointer): Register Pair HL = PC minus 1, pushed at 4D1EH.
4D38
RST 18H DF
RST 18H (the ROM compare of Register Pair HL with Register Pair DE): the Z FLAG if PC minus 1 is this breakpoint's address.
4D39
EX (SP),HL E3
Exchange Register Pair HL with the word at the top of the stack (Stack Pointer) again: Register Pair HL = the entry, PC minus 1 back on the stack.
4D3A
If the NZ FLAG is set (the program did not stop at this breakpoint), JUMP to 4D40H.
4D3C
LD (4DC7H),DE ED 53 C7 4D
The program stopped here: store Register Pair DE (the breakpoint address) at 4DC7H, the resume PC.
4D40
INC HL 23
INCrement Register Pair HL to the next entry of the breakpoint table. 4D33H and 4D3AH come here.
4D41
DECrement Register B (the entries left) and LOOP BACK to 4D2CH for the second breakpoint.

4D43H - Command Loop

Every command returns here (4D43H is pushed as the return address). The stack is reset to the save area, the screen is drawn, and a command line of up to 18 characters is read on the bottom line into 51ECH. A first character of 2 or 3 selects the second or third memory window for the D, ; and - commands; otherwise the first window (404CH) is used. The line is converted to upper case and the command letter is tested.

4D43
LD SP,0000H 31 00 00
Load the Stack Pointer with the base of the register save area (0000H in the file). Self-Modifying Code
The operand at 4D44H is stored at 4D0DH. This also drops the PC minus 1 pushed at 4D1EH. 50C6H comes here after Error.
4D46
LD HL,4D43H 21 43 4D
Load Register Pair HL with 4D43H, the start of this loop.
4D49
PUSH HL E5
Save Register Pair HL (4D43H) onto the stack, so that a command that RETurns comes back to the loop.
4D4A
GOSUB to 4FC7H to clear the screen and display the registers and memory.
4D4D
LD HL,3FC0H 21 C0 3F
Point Register Pair HL to 3FC0H, the start of the bottom line of the screen.
4D50
LD (4020H),HL 22 20 40
Store Register Pair HL (3FC0H) at 4020H, the ROM cursor position.
4D53
LD HL,51ECH 21 EC 51
Point Register Pair HL to 51ECH, the input buffer (after the end of the file).
4D56
LD B,12H 06 12
Load Register B with 12H: up to 18 characters.
4D58
GOSUB to 0040H (ROM) to read a line into the buffer at Register Pair HL. Register B returns the number of characters typed; the line ends with 0DH.
4D5B
LD DE,404CH 11 4C 40
Point Register Pair DE to 404CH, where the address of the first memory window is kept.
4D5E
LD A,(HL) 7E
Fetch the first character at Register Pair HL into Register A.
4D5F
SUB 32H D6 32
SUBtract 32H (the character 2) from Register A.
4D61
CP 02H FE 02
Compare Register A against 02H: the CARRY FLAG for 2 or 3 (Register A = 00H or 01H).
4D63
If the NO CARRY FLAG is set (not 2 or 3), JUMP to 4D6AH to use the first window.
4D65
INC A 3C
INCrement Register A: 1 for window 2, 2 for window 3.
4D66
ADD A,A 87
ADD Register A to itself: 2 or 4, the offset of the window word.
4D67
ADD A,E 83
ADD Register E (4CH, the low byte of 404CH) to Register A.
4D68
LD E,A 5F
Copy Register A into Register E: Register Pair DE = 404EH (window 2) or 4050H (window 3).
4D69
INC HL 23
INCrement Register Pair HL past the window number on the command line.
4D6A
LD (4EBDH),DE ED 53 BD 4E
Store Register Pair DE (where the window address is kept) at 4EBDH, the operand of the LD HL,nnnn at 4EBCH used by the D, ; and - commands. 4D63H comes here.
4D6E
PUSH HL E5
Save Register Pair HL (the command letter) onto the stack.
4D6F
INC B 04
INCrement Register B (the characters typed): the loop also covers the 0DH at the end.

Upper Case Loop

4D70
LD A,(HL) 7E
Fetch the character at Register Pair HL into Register A.
4D71
GOSUB to 4548H (SYS0/SYS) to change Register A to upper case if it is a lower case letter.
4D74
LD (HL),A 77
Store Register A (the character in upper case) back at Register Pair HL.
4D75
INC HL 23
INCrement Register Pair HL to the next character.
4D76
DECrement Register B and LOOP BACK to 4D70H until the whole line is in upper case.
4D78
POP HL E1
Restore Register Pair HL from the stack: the command letter.

4D79H - G Command: Go

G resumes the program. Forms: G, Gaddr (resume at addr), and either followed by up to two breakpoints ,bp1,bp2. All numbers are hexadecimal. A breakpoint address must be 5200H or higher (DEBUG cannot put breakpoints into the DOS). Missing breakpoints get an address in the ROM (Register D = 00H), where writing F7H has no effect.

4D79
LD A,(HL) 7E
Fetch the command letter at Register Pair HL into Register A.
4D7A
CP 47H FE 47
Compare Register A (the command letter) against 47H (G).
4D7C
If the NZ FLAG is set (not G), JUMP to 4DCDH.
4D7E
GOSUB to 509BH to move Register Pair HL to the next character and test it: the CARRY FLAG for a hexadecimal digit.
4D81
If the NO CARRY FLAG is set (no address, a comma or the end of the line), JUMP to 4D8AH to resume at the current PC.
4D83
GOSUB to 5079H to read the hexadecimal address at Register Pair HL into Register Pair DE.
4D86
LD (4DC7H),DE ED 53 C7 4D
Store Register Pair DE (the address) at 4DC7H, the resume PC.
4D8A
LD B,02H 06 02
Load Register B with 02H: two breakpoints may follow. 4D81H comes here.

Breakpoint Address Loop

4D8C
LD D,00H 16 00
Load Register D with 00H: an address in the ROM (no breakpoint) unless one is given.
4D8E
LD A,(HL) 7E
Fetch the next character at Register Pair HL into Register A.
4D8F
CP 2CH FE 2C
Compare Register A (the character after the address) against 2CH (a comma).
4D91
If the NZ FLAG is set (no comma), JUMP to 4D9BH to push the empty breakpoint.
4D93
GOSUB to 5078H to move Register Pair HL past the comma and read the breakpoint address into Register Pair DE.
4D96
LD A,D 7A
Copy Register D (the high byte of the breakpoint) into Register A.
4D97
CP 52H FE 52
Compare Register A against 52H: the CARRY FLAG for an address below 5200H.
4D99
If the CARRY FLAG is set (below 5200H), JUMP to 4DE9H to display Error.
4D9B
PUSH DE D5
Save Register Pair DE (the breakpoint address) onto the stack. 4D91H comes here.
4D9C
DECrement Register B and LOOP BACK to 4D8CH for the second breakpoint.
4D9E
GOSUB to 50B5H: the line at Register Pair HL must end here, otherwise Error.

4DA1H - Set the Breakpoints and Resume the Program

Also reached from 51B5H for the I and C commands, with the two addresses pushed. Takes two breakpoint addresses from the stack, stores each with its original byte at 4052H-4057H and writes F7H (RST 30H) in its place. Then drops the command loop's return address, restores every register, switches to the program's stack, and resumes at the saved PC through SYS0/SYS 4BC5H (which clears bit 6 of 4289H, the overlay-running flag, before its RET).

4DA1
LD HL,4052H 21 52 40
Point Register Pair HL to 4052H, the breakpoint table. 51B5H comes here.
4DA4
LD B,02H 06 02
Load Register B with 02H: two breakpoint addresses on the stack.

Breakpoint Set Loop

4DA6
POP DE D1
Restore Register Pair DE from the stack: a breakpoint address.
4DA7
LD (HL),E 73
Store Register E (the low byte of the address) at Register Pair HL in the table.
4DA8
INC HL 23
INCrement Register Pair HL to the high byte of the entry.
4DA9
LD (HL),D 72
Store Register D (the high byte of the address) at Register Pair HL.
4DAA
INC HL 23
INCrement Register Pair HL to the saved byte of the entry.
4DAB
LD A,(DE) 1A
Fetch the byte at the breakpoint address (Register Pair DE) into Register A.
4DAC
LD (HL),A 77
Store Register A (the original byte) at Register Pair HL in the table.
4DAD
INC HL 23
INCrement Register Pair HL to the next entry of the table.
4DAE
LD A,F7H 3E F7
Load Register A with F7H, the RST 30H opcode.
4DB0
LD (DE),A 12
Store Register A (F7H) at the breakpoint address (Register Pair DE). In the ROM the write has no effect.
4DB1
DECrement Register B and LOOP BACK to 4DA6H for the second breakpoint.
4DB3
POP AF F1
Drop the command loop's return address (4D43H) from the stack into Register Pair AF.
4DB4
POP IY FD E1
Restore Index Register IY from the stack (save area +00H).
4DB6
POP IX DD E1
Restore Index Register IX from the stack (save area +02H).
4DB8
POP HL E1
Restore Register Pair HL from the stack: the program's HL' (save area +04H), for now in the main set.
4DB9
POP DE D1
Restore Register Pair DE from the stack: the program's DE' (+06H).
4DBA
POP BC C1
Restore Register Pair BC from the stack: the program's BC' (+08H).
4DBB
POP AF F1
Restore Register Pair AF from the stack: the program's AF' (+0AH).
4DBC
EX AF,AF' 08
Exchange Register Pair AF with the alternate AF': the program's AF' is now in the alternate set.
4DBD
EXX D9
Exchange Register Pairs BC, DE and HL with the alternate set (EXX): the program's BC', DE' and HL' are now in the alternate set.
4DBE
POP DE D1
Restore Register Pair DE from the stack: the program's DE (+0CH).
4DBF
POP BC C1
Restore Register Pair BC from the stack: the program's BC (+0EH).
4DC0
POP HL E1
Restore Register Pair HL from the stack: the program's HL (+10H).
4DC1
POP AF F1
Restore Register Pair AF from the stack: the program's AF (+12H). The Stack Pointer now points to the saved PC.
4DC2
LD SP,0000H 31 00 00
Load the Stack Pointer with the program's stack (0000H in the file). Self-Modifying Code
The operand at 4DC3H is stored at 4D1FH, or by the R command for SP.
4DC5
PUSH HL E5
Save Register Pair HL (the program's) onto the program's stack.
4DC6
LD HL,0000H 21 00 00
Load Register Pair HL with the resume PC (0000H in the file). Self-Modifying Code
The operand at 4DC7H is stored at 4D18H, 4D3CH and 4D86H, or by the R command for PC.
4DC9
EX (SP),HL E3
Exchange Register Pair HL with the word at the top of the stack (Stack Pointer): Register Pair HL = the program's HL again, and the resume PC is on the program's stack.
4DCA
JUMP to 4BC5H (SYS0/SYS), which clears bit 6 of 4289H and RETurns to the resume PC on the stack.

4DCDH - R Command: Change a Register

Form: Rrr,value, for example RHL,1234 or RAF',0044. The register name is looked up in the table at 50DBH (AF, BC, DE, HL, AF', BC', DE', HL', PC, SP, IX, IY); a name of two letters must be followed directly by the comma. The value is hexadecimal and the line must end after it.

4DCD
CP 52H FE 52
Compare Register A (the command letter) against 52H (R). 4D7CH comes here.
4DCF
If the NZ FLAG is set (not R), JUMP to 4E03H.
4DD1
LD DE,50DBH 11 DB 50
Point Register Pair DE to 50DBH, the register name table.

Name Loop
Register Pair DE = the next table entry.

4DD4
LD B,03H 06 03
Load Register B with 03H: three characters per name.
4DD6
PUSH HL E5
Save Register Pair HL (the command letter) onto the stack.
4DD7
INC HL 23
INCrement Register Pair HL to the next character typed. 4DECH comes here.
4DD8
LD A,(DE) 1A
Fetch the next character of the table name at Register Pair DE into Register A.
4DD9
CP (HL) BE
Compare Register A (the table character) against the character typed at Register Pair HL.
4DDA
INC DE 13
INCrement Register Pair DE to the next table byte. INC DE does not change the flags.
4DDB
If the Z FLAG is set (they match), JUMP to 4DECH.
4DDD
CP 20H FE 20
They differ: compare Register A (the table character) against 20H, the space that pads a two-letter name.
4DDF
If the Z FLAG is set (the end of a two-letter name), JUMP to 4DF0H: the name matched if a comma was typed here.

Skip Loop

4DE1
INC DE 13
INCrement Register Pair DE to the next table byte. 4DF3H comes here.
4DE2
DECrement Register B and LOOP BACK to 4DE1H until Register Pair DE is past this entry's offset byte.
4DE4
POP HL E1
Restore Register Pair HL from the stack: the command letter.
4DE5
LD A,(DE) 1A
Fetch the first byte of the next entry at Register Pair DE into Register A.
4DE6
OR A B7
OR Register A with itself: the Z FLAG for the 00H that ends the table.
4DE7
If the NZ FLAG is set (another entry), LOOP BACK to 4DD4H to try its name.
4DE9
No name matched: JUMP to 50B9H to display Error. 4D99H comes here for a breakpoint below 5200H.
4DEC
DECrement Register B (the characters left) and LOOP BACK to 4DD7H for the next character of the name.
4DEE
INC HL 23
All three characters matched: INCrement Register Pair HL to the character after them.
4DEF
INC B 04
INCrement Register B to 1, so that the loop at 4DE1H steps Register Pair DE past the offset byte only, if the comma is missing.
4DF0
LD A,(HL) 7E
Fetch the character after the name at Register Pair HL into Register A. 4DDFH comes here.
4DF1
CP 2CH FE 2C
Compare Register A (the character after the name) against 2CH (a comma).
4DF3
If the NZ FLAG is set (no comma), JUMP to 4DE1H to try the next name.
4DF5
POP AF F1
Drop the saved command pointer from the stack into Register Pair AF.
4DF6
LD A,(DE) 1A
Fetch the register's offset in the save area at Register Pair DE into Register A.
4DF7
PUSH AF F5
Save Register Pair AF (Register A = the offset) onto the stack.
4DF8
GOSUB to 50B2H to move Register Pair HL past the comma, read the hexadecimal value into Register Pair DE and check the end of the line.
4DFB
POP AF F1
Restore Register Pair AF from the stack: Register A = the offset.
4DFC
GOSUB to 50C9H with Register A = the offset: Register Pair HL returns the address where the register is kept.
4DFF
LD (HL),E 73
Store Register E (the low byte of the new value) at Register Pair HL.
4E00
INC HL 23
INCrement Register Pair HL to the high byte of the saved register.
4E01
LD (HL),D 72
Store Register D (the high byte of the new value) at Register Pair HL.
4E02
RET C9
RETurn to the command loop at 4D43H, which displays the new value.

4E03H - F Command: Find Bytes

Form: Faddr,b1,b2,... searches memory from addr for the byte string b1, b2... (hexadecimal; the string is kept at 51E8H). F alone continues the last search from the byte after the last address found. The search stops at the first match or at FFFFH. The address found is kept at 4E08H, and the first window is set to 20H bytes before it so that the match is on the third line; the display is switched to the X form. When nothing is found the window is at FFE0H. 51E8H-51FFH is also the input buffer (51ECH up), so a new command line overwrites the fifth and later bytes of the string.

4E03
CP 46H FE 46
Compare Register A (the command letter) against 46H (F). 4DCFH comes here.
4E05
If the NZ FLAG is set (not F), JUMP to 4E59H.
4E07
LD DE,0000H 11 00 00
Load Register Pair DE with the address of the last match (0000H in the file). Self-Modifying Code
The operand at 4E08H is stored at 4E4BH.
4E0A
INC DE 13
INCrement Register Pair DE: the search goes on from the byte after the last match.
4E0B
LD B,00H 06 00
Load Register B with the length of the byte string (00H in the file). Self-Modifying Code
The operand at 4E0CH is stored at 4E2FH.
4E0D
INC HL 23
INCrement Register Pair HL to the character after the F.
4E0E
LD A,(HL) 7E
Fetch the character at Register Pair HL into Register A.
4E0F
CP 0DH FE 0D
Compare Register A against 0DH, the end of the line.
4E11
If the Z FLAG is set (F alone), JUMP to 4E32H to repeat the last search with Register Pair DE and Register B from above.
4E13
GOSUB to 5079H to read the hexadecimal start address at Register Pair HL into Register Pair DE.
4E16
PUSH DE D5
Save Register Pair DE (the start address) onto the stack.
4E17
LD B,00H 06 00
Load Register B with 00H: Register B counts the bytes of the string.
4E19
LD DE,51E8H 11 E8 51
Point Register Pair DE to 51E8H, the string buffer.

String Loop
Register Pair DE = the next place in the buffer, Register B = the bytes so far.

4E1C
PUSH DE D5
Save Register Pair DE (the buffer pointer) onto the stack.
4E1D
GOSUB to 50AEH: the character at Register Pair HL must be a comma, otherwise Error.
4E20
GOSUB to 5078H to move Register Pair HL past the comma and read a hexadecimal byte value into Register Pair DE.
4E23
LD A,E 7B
Copy Register E (the low byte of the value) into Register A.
4E24
POP DE D1
Restore Register Pair DE from the stack: the buffer pointer.
4E25
INC B 04
INCrement Register B, the bytes in the string.
4E26
LD (DE),A 12
Store Register A (the byte) at Register Pair DE in the buffer.
4E27
INC DE 13
INCrement Register Pair DE to the next place in the buffer.
4E28
LD A,(HL) 7E
Fetch the next character at Register Pair HL into Register A.
4E29
CP 0DH FE 0D
Compare Register A against 0DH, the end of the line.
4E2B
If the NZ FLAG is set (more bytes), LOOP BACK to 4E1CH.
4E2D
POP DE D1
Restore Register Pair DE from the stack: the start address, saved at 4E16H.
4E2E
LD A,B 78
Copy Register B (the length of the string) into Register A.
4E2F
LD (4E0CH),A 32 0C 4E
Store Register A (the length) at 4E0CH, the operand of the LD B,nn at 4E0BH, for F without parameters.
4E32
LD HL,51E8H 21 E8 51
Point Register Pair HL to 51E8H, the string buffer. 4E11H comes here.
4E35
EX DE,HL EB
Exchange Register Pairs DE and HL: Register Pair DE = the string, Register Pair HL = the address to start at.

Search Loop
Register Pair HL = the memory address being tried.

4E36
PUSH BC C5
Save Register Pair BC (Register B = the length) onto the stack.
4E37
PUSH DE D5
Save Register Pair DE (the string) onto the stack.
4E38
PUSH HL E5
Save Register Pair HL (the memory address) onto the stack.

Compare Loop

4E39
LD A,(DE) 1A
Fetch the next string byte at Register Pair DE into Register A.
4E3A
CP (HL) BE
Compare Register A against the memory byte at Register Pair HL.
4E3B
INC DE 13
INCrement Register Pair DE to the next string byte. INC DE does not change the flags.
4E3C
INC HL 23
INCrement Register Pair HL to the next memory byte. INC HL does not change the flags.
4E3D
If the NZ FLAG is set (they differ), JUMP to 4E41H.
4E3F
DECrement Register B and LOOP BACK to 4E39H until the whole string has been compared.
4E41
POP HL E1
Restore Register Pair HL from the stack: the memory address. 4E3DH comes here.
4E42
POP DE D1
Restore Register Pair DE from the stack: the string.
4E43
POP BC C1
Restore Register Pair BC from the stack: Register B = the length. POP does not change the flags, which are those of the last compare.
4E44
If the Z FLAG is set (the whole string matched), JUMP to 4E4BH.
4E46
INC HL 23
INCrement Register Pair HL to the next address to try.
4E47
LD A,H 7C
Copy Register H (the high byte of the address) into Register A.
4E48
OR L B5
OR Register L into Register A: the Z FLAG when Register Pair HL has wrapped to 0000H.
4E49
If the NZ FLAG is set (the search has not passed FFFFH), LOOP BACK to 4E36H.
4E4B
LD (4E08H),HL 22 08 4E
Store Register Pair HL (the address found, or 0000H) at 4E08H, the last match. 4E44H comes here.
4E4E
LD DE,FFE0H 11 E0 FF
Load Register Pair DE with FFE0H, minus 20H, two lines of the display.
4E51
ADD HL,DE 19
ADD Register Pair DE to Register Pair HL: 20H bytes before the match.
4E52
LD (404CH),HL 22 4C 40
Store Register Pair HL at 404CH, the address of the first window.
4E55
LD A,58H 3E 58
Load Register A with 58H (X), the letter of the X form command.
4E57
JUMP to 4ECFH with Register A = X, which switches the display to the X form.

4E59H - L Command: Read a Sector

Form: Ld,sector: reads the sector (a decimal number counted from the start of the diskette) of drive d into the buffer at 4300H and shows the buffer in the full screen form. Not allowed when passwords are checked (option AA). A sector with the directory mark (error 06H) is accepted.

4E59
CP 4CH FE 4C
Compare Register A (the command letter) against 4CH (L). 4E05H comes here.
4E5B
If the NZ FLAG is set (not L), JUMP to 4E6BH.
4E5D
GOSUB to 4E87H to read the drive and sector numbers, select the drive and set the display. Register Pair DE returns the sector, Register Pair HL 4300H.
4E60
XOR A AF
Set Register A to 0 with XOR, which sets the Z FLAG so that the read below is done.
4E61
If the Z FLAG is set, GOSUB to 45DBH (SYS0/SYS) to read sector Register Pair DE into the buffer at Register Pair HL. Register A returns the error code. 4E85H comes here after a W command to read the sector back.
4E64
RET Z C8
If the Z FLAG is set (read without error), RETurn to the command loop.
4E65
CP 06H FE 06
Compare Register A (the error code) against 06H: the sector has the directory mark.
4E67
RET Z C8
If the Z FLAG is set (the directory mark, not an error here), RETurn to the command loop.
4E68
JUMP to 50B9H to display Error. 4E73H, 4E8BH, 4E96H and 4EAEH come here too.

4E6BH - W Command: Write a Sector

Form: WRd,sector: writes the 256 bytes at 4300H to the sector. The sector is first read with verify only (SYS0/SYS 45DFH) to find its data mark: a normal sector is written with the normal mark (45EBH), a directory sector with the directory mark (45E7H). Then it is read back into 4300H. Not allowed when passwords are checked.

4E6B
CP 57H FE 57
Compare Register A (the command letter) against 57H (W). 4E5BH comes here.
4E6D
If the NZ FLAG is set (not W), JUMP to 4EB5H.
4E6F
INC HL 23
INCrement Register Pair HL to the character after the W.
4E70
LD A,(HL) 7E
Fetch the character at Register Pair HL into Register A.
4E71
CP 52H FE 52
Compare Register A against 52H (R): the command is WR.
4E73
If the NZ FLAG is set (not WR), JUMP to 4E68H to display Error.
4E75
GOSUB to 4E87H to read the drive and sector numbers, select the drive and set the display. Register Pair DE returns the sector, Register Pair HL 4300H.
4E78
GOSUB to 45DFH (SYS0/SYS) to read sector Register Pair DE with verify only, to learn its data mark. Register A returns 06H for the directory mark.
4E7B
If the Z FLAG is set (a normal sector read without error), GOSUB to 45EBH (SYS0/SYS) to write the buffer at Register Pair HL to sector Register Pair DE with the normal data mark.
4E7E
If the Z FLAG is set (written), JUMP to 4E85H to read it back.
4E80
CP 06H FE 06
Compare Register A (the error code) against 06H: the sector has the directory mark.
4E82
If the Z FLAG is set (a directory sector), GOSUB to 45E7H (SYS0/SYS) to write the buffer with the directory mark.
4E85
JUMP to 4E61H: if the write worked (the Z FLAG) the sector is read back into 4300H; any error left goes to Error. 4E7EH comes here.

4E87H - L and W: Read the Drive and Sector

Refuses the command when bit 7 of 428CH (option AA, passwords checked) is set. Reads the drive number (hexadecimal, below 100H) and, after the comma, the sector number (decimal), which must end the line; selects the drive; sets the full screen display and puts the first window at 4300H. Returns Register Pair DE = the sector and Register Pair HL = 4300H.

4E87
LD A,(428CH) 3A 8C 42
Fetch the option flags at 428CH into Register A. 4E5DH and 4E75H call here.
4E8A
RLCA 07
Rotate Register A left: bit 7, option AA (passwords are checked), goes into the CARRY FLAG.
4E8B
If the CARRY FLAG is set (passwords are checked), JUMP to 4E68H to display Error.
4E8D
GOSUB to 50ABH to move Register Pair HL past the letter, read the drive number into Register Pair DE and require a comma.
4E90
LD A,D 7A
Copy Register D (the high byte of the drive number) into Register A.
4E91
OR A B7
OR Register A with itself: the Z FLAG when the drive number is below 100H.
4E92
LD A,E 7B
Copy Register E (the drive number) into Register A. LD does not change the flags.
4E93
If the Z FLAG is set (below 100H), GOSUB to 4723H (SYS0/SYS) to select the drive in Register A. The NZ FLAG returns if the drive does not exist or is not available.
4E96
If the NZ FLAG is set (the drive number is too big, or the drive was not selected), JUMP to 4E68H to display Error.
4E98
INC HL 23
INCrement Register Pair HL past the comma after the drive number.
4E99
LD A,0AH 3E 0A
Load Register A with 0AH: base 10 for the sector number.
4E9B
GOSUB to 507BH to read the decimal sector number at Register Pair HL into Register Pair DE.
4E9E
GOSUB to 50B5H: the line at Register Pair HL must end here, otherwise Error.
4EA1
XOR A AF
Set Register A to 0 with XOR: the S form (full screen).
4EA2
LD (42C4H),A 32 C4 42
Store Register A (00H) at 42C4H, the display form byte.
4EA5
LD HL,4300H 21 00 43
Point Register Pair HL to 4300H, the sector buffer.
4EA8
LD (404CH),HL 22 4C 40
Store Register Pair HL (4300H) at 404CH, the address of the first window.
4EAB
RET C9
RETurn with Register Pair DE = the sector and Register Pair HL = 4300H.

4EACH - Q Command: Leave DEBUG

Reached from 4EFEH when the letter is not ; or -. Q abandons the program and goes to DOS READY: SYS1/SYS function 7 sub-function 0CH (the MDBORT exit) clears the MINI-DOS and DOS-CALL flags and shows the DOS READY prompt. The RST 28H does not return.

4EAC
CP 51H FE 51
Compare Register A (the command letter) against 51H (Q). 4EFEH comes here.
4EAE
If the NZ FLAG is set (an unknown command), JUMP to 4E68H to display Error.
4EB0
LD A,E3H 3E E3
Load Register A with E3H, the RST 28H code of SYS1/SYS function 7.
4EB2
LD C,0CH 0E 0C
Load Register C with 0CH, sub-function 0CH (the MDBORT exit).
4EB4
RST 28H EF
RST 28H with Register A = E3H and Register C = 0CH: SYS1/SYS is loaded over SYS5/SYS, ends the program and shows DOS READY. It does not come back.

4EB5H - D Command: Set a Window Address

Form: Daddr, or 2Daddr / 3Daddr: sets the address of the memory window chosen at 4D5BH. Also the end of the ; and - commands (4F08H).

4EB5
CP 44H FE 44
Compare Register A (the command letter) against 44H (D). 4E6DH comes here.
4EB7
If the NZ FLAG is set (not D), JUMP to 4EC3H.
4EB9
GOSUB to 50B2H to move Register Pair HL past the D, read the hexadecimal address into Register Pair DE and check the end of the line.
4EBC
LD HL,0000H 21 00 00
Load Register Pair HL with where the window address is kept: 404CH, 404EH or 4050H (0000H in the file). Self-Modifying Code
The operand at 4EBDH is stored at 4D6AH. 4F08H comes here.
4EBF
LD (HL),E 73
Store Register E (the low byte of the new window address) at Register Pair HL.
4EC0
INC HL 23
INCrement Register Pair HL to the high byte of the window address.
4EC1
LD (HL),D 72
Store Register D (the high byte of the new window address) at Register Pair HL.
4EC2
RET C9
RETurn to the command loop at 4D43H, which displays the window.

4EC3H - M Command and One-Letter Commands

M goes to 4F0AH. Every other letter must be alone on the line; it is passed to 4ECFH in Register A.

4EC3
CP 4DH FE 4D
Compare Register A (the command letter) against 4DH (M). 4EB7H comes here.
4EC5
If the Z FLAG is set (M), JUMP to 4F0AH for the memory change command.
4EC7
INC HL 23
INCrement Register Pair HL to the character after the letter.
4EC8
LD C,A 4F
Copy Register A (the letter) into Register C.
4EC9
GOSUB to 50B5H: nothing may follow the letter at Register Pair HL, otherwise Error.
4ECC
LD A,C 79
Copy Register C (the letter) back into Register A.
4ECD
LD B,00H 06 00
Load Register B with 00H, the value for the I command.

4ECFH - I, C, X, S, ; and -

I steps one instruction; C steps one instruction but runs a CALL (or RST) to its end. Both go to 5140H with Register Pair HL pointing to the byte after the opcode at the program's PC and Register C = the opcode. X selects the display with registers and three 4-line memory windows (42C4H = 01H), S the full screen display of 256 bytes (42C4H = 00H). ; and - move the chosen window forward or back by 40H bytes in the X form, 100H bytes in the S form. Anything else goes to Q or Error (4EACH).

4ECF
LD HL,(4DC7H) 2A C7 4D
Load Register Pair HL with the program's PC from 4DC7H, the operand of the LD HL,nnnn at 4DC6H. 4E57H comes here with Register A = X.
4ED2
LD C,(HL) 4E
Fetch the opcode at the PC (Register Pair HL) into Register C.
4ED3
INC HL 23
INCrement Register Pair HL to the byte after the opcode.
4ED4
CP 49H FE 49
Compare Register A (the letter) against 49H (I).
4ED6
If the Z FLAG is set (I, or C from 4EDCH), JUMP to 5140H to set the breakpoints for one step, with Register B = 00H for I or 01H for C.
4ED9
INC B 04
INCrement Register B to 01H, the value for the C command.
4EDA
CP 43H FE 43
Compare Register A (the letter) against 43H (C).
4EDC
If the Z FLAG is set (C), JUMP to 4ED6H with Register B = 01H.
4EDE
LD HL,(4EBDH) 2A BD 4E
Load Register Pair HL with where the window address is kept, from 4EBDH.
4EE1
LD E,(HL) 5E
Fetch the low byte of the window address at Register Pair HL into Register E.
4EE2
INC HL 23
INCrement Register Pair HL to the high byte of the window address.
4EE3
LD D,(HL) 56
Fetch the high byte at Register Pair HL into Register D: Register Pair DE = the window address.
4EE4
LD HL,42C4H 21 C4 42
Point Register Pair HL to 42C4H, the display form byte.
4EE7
LD B,(HL) 46
Fetch the display form at Register Pair HL into Register B, kept in case it must be put back.
4EE8
LD (HL),01H 36 01
Store 01H (the X form) at Register Pair HL (42C4H).
4EEA
CP 58H FE 58
Compare Register A (the letter) against 58H (X).
4EEC
RET Z C8
If the Z FLAG is set (X), RETurn to the command loop: the X form is set.
4EED
DEC (HL) 35
DECrement the byte at Register Pair HL (42C4H) to 00H, the S form.
4EEE
CP 53H FE 53
Compare Register A (the letter) against 53H (S).
4EF0
RET Z C8
If the Z FLAG is set (S), RETurn to the command loop: the S form is set.
4EF1
LD (HL),B 70
Neither: store Register B (the old form) back at Register Pair HL (42C4H).
4EF2
LD HL,0040H 21 40 00
Load Register Pair HL with 0040H: a step of 40H forward.
4EF5
CP 3BH FE 3B
Compare Register A (the letter) against 3BH (;).
4EF7
If the Z FLAG is set (;), JUMP to 4F00H to move the window forward.
4EF9
LD HL,FFC0H 21 C0 FF
Load Register Pair HL with FFC0H: a step of 40H back.
4EFC
CP 2DH FE 2D
Compare Register A (the letter) against 2DH (-).
4EFE
If the NZ FLAG is set (not -), JUMP to 4EACH for Q or Error.
4F00
LD A,B 78
Copy Register B (the display form) into Register A. 4EF7H comes here.
4F01
OR A B7
OR Register A with itself: the NZ FLAG for the X form.
4F02
If the NZ FLAG is set (the X form), JUMP to 4F06H to move by 40H.
4F04
ADD HL,HL 29
The S form: ADD Register Pair HL to itself, doubling the step.
4F05
ADD HL,HL 29
ADD Register Pair HL to itself again: the step is 100H forward or back.
4F06
ADD HL,DE 19
ADD Register Pair DE (the window address) to Register Pair HL (the step). 4F02H comes here.
4F07
EX DE,HL EB
Exchange Register Pairs DE and HL: Register Pair DE = the new window address.
4F08
JUMP to 4EBCH to store Register Pair DE as the window address.

4F0AH - M Command: Change Memory

Form: Maddr. The 256 bytes around addr are shown in the S form with a blinking block (BFH) on the hexadecimal digit being changed. A hexadecimal key replaces the digit and moves right; the space bar or right arrow moves right one digit, left arrow left one digit, shift-right arrow (19H) and shift-left arrow (18H) two bytes, down arrow (0AH) and up arrow (5BH) 16 bytes. ENTER ends the command; any other key displays Error. The cursor stays inside the 256-byte page (moving past its ends stops at the first or last digit), and changing the last digit of the last byte of the page ends the command.

4F0A
GOSUB to 50B2H to move Register Pair HL past the M, read the hexadecimal address into Register Pair DE and check the end of the line. 4EC5H comes here.
4F0D
EX DE,HL EB
Exchange Register Pairs DE and HL: Register Pair HL = the address to change.
4F0E
LD B,00H 06 00
Load Register B with 00H: the cursor is on the high digit (Register B = 01H for the low digit).

Change Loop
Register Pair HL = the byte being changed, Register B = the digit (0 high, 1 low).

4F10
LD (404CH),HL 22 4C 40
Store Register Pair HL (the address) at 404CH, the address of the first window, so that its page is shown. 4F69H comes here.
4F13
PUSH HL E5
Save Register Pair HL (the address) onto the stack.
4F14
LD C,L 4D
Copy Register L (the position inside the page) into Register C.
4F15
XOR A AF
Set Register A to 0 with XOR: the S form, the full screen of 256 bytes.
4F16
LD (42C4H),A 32 C4 42
Store Register A (00H) at 42C4H, the display form byte.
4F19
GOSUB to 4FC7H to display the screen again with the changed page.
4F1C
LD H,00H 26 00
Load Register H with 00H, for the screen position worked out below.
4F1E
LD D,H 54
Copy Register H (00H) into Register D, the high byte of the column offset.
4F1F
LD E,H 5C
Copy Register H (00H) into Register E, which collects the odd byte flag.
4F20
LD A,C 79
Copy Register C (the position inside the page) into Register A.
4F21
RRA 1F
Rotate Register A right through the CARRY FLAG: bit 0, an odd byte, goes into the CARRY FLAG.
4F22
RL E CB 13
Rotate Register E left through the CARRY FLAG: Register E = 1 for an odd byte, 0 for an even one.
4F24
AND 07H E6 07
AND Register A with 07H: bits 1-3 of the position, the 2-byte group within the line (0-7).
4F26
LD L,A 6F
Copy Register A (the 2-byte group) into Register L for the add at 4F2AH.
4F27
ADD A,A 87
ADD Register A (the group) to itself: the group times 2.
4F28
ADD A,E 83
ADD Register E (the odd byte flag) to Register A.
4F29
ADD A,A 87
ADD Register A to itself: (group times 2 plus odd) times 2.
4F2A
ADD A,L 85
ADD Register L (the group) to Register A: the group times 5 plus odd times 2, since each group is shown as four digits and a space.
4F2B
ADD A,B 80
ADD Register B (the digit, 0 or 1) to Register A: the column of the digit.
4F2C
LD E,A 5F
Copy Register A into Register E: Register Pair DE = the column offset.
4F2D
LD A,C 79
Copy Register C (the position inside the page) into Register A again.
4F2E
AND F0H E6 F0
AND Register A with F0H, keeping bits 4-7: the line number times 16.
4F30
LD L,A 6F
Copy Register A into Register L: Register Pair HL = the line times 16.
4F31
ADD HL,HL 29
ADD Register Pair HL to itself: the line times 32.
4F32
ADD HL,HL 29
ADD Register Pair HL to itself: the line times 64, the screen offset of the line.
4F33
ADD HL,DE 19
ADD Register Pair DE (the column offset) to Register Pair HL.
4F34
LD DE,3C08H 11 08 3C
Load Register Pair DE with 3C08H: the digits start at column 8 of the top screen line.
4F37
ADD HL,DE 19
ADD Register Pair DE to Register Pair HL: Register Pair HL = the screen address of the digit.
4F38
LD C,(HL) 4E
Fetch the character shown at Register Pair HL into Register C.

Blink Loop

4F39
LD (HL),BFH 36 BF
Store BFH (a full graphics block) at Register Pair HL on the screen in place of the digit.
4F3B
GOSUB to 4FB7H to wait a while for a key: the Z FLAG if none was pressed, otherwise the key in Register A.
4F3E
LD (HL),C 71
Store Register C (the digit) back at Register Pair HL on the screen. LD does not change the flags.
4F3F
If the Z FLAG is set (no key yet), GOSUB to 4FB7H to wait again with the digit shown.
4F42
If the Z FLAG is set (still no key), LOOP BACK to 4F39H: the digit blinks.
4F44
POP HL E1
Restore Register Pair HL from the stack: the address being changed.
4F45
CP 0DH FE 0D
Compare Register A (the key) against 0DH (ENTER).
4F47
LD C,A 4F
Copy Register A (the key) into Register C. LD does not change the flags.
4F48
RET Z C8
If the Z FLAG is set (ENTER), RETurn to the command loop.
4F49
GOSUB to 509DH to test the key in Register A: the CARRY FLAG for a hexadecimal digit, with its value in Register A.
4F4C
If the NO CARRY FLAG is set (not a digit), JUMP to 4F6BH for the cursor keys.
4F4E
LD E,F0H 1E F0
Load Register E with F0H, the mask that keeps the high digit of the byte.
4F50
BIT 0,B CB 40
Test bit 0 of Register B: set when the cursor is on the low digit.
4F52
If the NZ FLAG is set (the low digit), JUMP to 4F5AH with the mask F0H and the new digit in the low four bits.
4F54
LD E,0FH 1E 0F
The high digit: load Register E with 0FH, the mask that keeps the low digit.
4F56
RLCA 07
Rotate Register A (the new digit) left (the first of four RLCAs).
4F57
RLCA 07
Rotate Register A left (the second of four RLCAs).
4F58
RLCA 07
Rotate Register A left (the third of four RLCAs).
4F59
RLCA 07
Rotate Register A left (the fourth): the new digit is in the high four bits.
4F5A
LD C,A 4F
Copy Register A (the new digit in place) into Register C. 4F52H comes here.
4F5B
LD A,(HL) 7E
Fetch the byte being changed at Register Pair HL into Register A.
4F5C
AND E A3
AND Register A with Register E (the mask), keeping the other digit.
4F5D
OR C B1
OR Register C (the new digit) into Register A.
4F5E
LD (HL),A 77
Store Register A (the new byte) at Register Pair HL.
4F5F
BIT 0,B CB 40
Test bit 0 of Register B: set when the cursor was on the low digit.
4F61
If the Z FLAG is set (the high digit was changed), JUMP to 4F65H to move to the low digit.
4F63
INC L 2C
The low digit was changed: INCrement Register L to the next byte.
4F64
RET Z C8
If the Z FLAG is set (Register L wrapped to 00H, past the end of the page), RETurn to the command loop: the command ends.
4F65
LD A,B 78
Copy Register B (the digit) into Register A. 4F61H, 4F76H, 4F79H, 4F83H and 4F8AH come here.
4F66
XOR 01H EE 01
XOR Register A with 01H: the other digit of the byte.
4F68
LD B,A 47
Copy Register A (the new digit, 0 or 1) into Register B.
4F69
LOOP BACK to 4F10H to display the screen with the cursor at the new place. 4F87H, 4F95H, 4F9BH, 4FB0H and 4FB5H come here.

4F6BH - M Command: Cursor Keys

Register C holds the key. Right moves (space, right arrow) and left moves stay inside the 256-byte page.

4F6B
LD A,C 79
Copy Register C (the key) into Register A. 4F4CH comes here.
4F6C
CP 20H FE 20
Compare Register A against 20H (the space bar).
4F6E
If the Z FLAG is set (space), JUMP to 4F74H to move right one digit.
4F70
CP 09H FE 09
Compare Register A against 09H (the right arrow).
4F72
If the NZ FLAG is set (not the right arrow), JUMP to 4F7DH.
4F74
BIT 0,B CB 40
Space or right arrow: test bit 0 of Register B (the digit). 4F6EH comes here.
4F76
If the Z FLAG is set (on the high digit), JUMP to 4F65H to move to the low digit.
4F78
INC L 2C
On the low digit: INCrement Register L to the next byte.
4F79
If the NZ FLAG is set (still in the page), JUMP to 4F65H to move to the high digit of the next byte.
4F7B
Past the end of the page: JUMP to 4F97H to stay on the last digit.
4F7D
CP 08H FE 08
Compare Register A (the key) against 08H (the left arrow). 4F72H comes here.
4F7F
If the NZ FLAG is set (not the left arrow), JUMP to 4F8CH.
4F81
BIT 0,B CB 40
Test bit 0 of Register B (the digit): set for the low digit.
4F83
If the NZ FLAG is set (on the low digit), JUMP to 4F65H to move to the high digit.
4F85
INC L 2C
On the high digit: INCrement Register L, the first of two steps that test it for 00H.
4F86
DEC L 2D
DECrement Register L back: the Z FLAG if this is the first byte of the page.
4F87
If the Z FLAG is set (the first byte), JUMP to 4F69H to stay where it is.
4F89
DEC L 2D
DECrement Register L to the previous byte of the page.
4F8A
JUMP to 4F65H to move to the low digit of the previous byte.
4F8C
LD E,02H 1E 02
Load Register E with 02H: the step of the shifted arrows. 4F7FH comes here.
4F8E
CP 19H FE 19
Compare Register A (the key) against 19H (shift-right arrow).
4F90
If the NZ FLAG is set (not shift-right), JUMP to 4F9DH.
4F92
LD A,L 7D
Forward: copy Register L (the position) into Register A. 4FA5H comes here with a step of 10H.
4F93
ADD A,E 83
ADD Register E (the step) to Register A (the position).
4F94
LD L,A 6F
Copy Register A into Register L: the new position.
4F95
If the NO CARRY FLAG is set (still in the page), JUMP to 4F69H.
4F97
LD B,01H 06 01
Past the end: load Register B with 01H, the low digit. 4F7BH comes here.
4F99
LD L,FFH 2E FF
Load Register L with FFH, the last byte of the page.
4F9B
JUMP to 4F69H to display the cursor on the last digit of the page.
4F9D
CP 18H FE 18
Compare Register A (the key) against 18H (shift-left arrow). 4F90H comes here.
4F9F
If the Z FLAG is set (shift-left), JUMP to 4FADH with a step of 2.
4FA1
LD E,10H 1E 10
Load Register E with 10H: the step of the up and down arrows, one line of 16 bytes.
4FA3
CP 0AH FE 0A
Compare Register A (the key) against 0AH (the down arrow).
4FA5
If the Z FLAG is set (down), JUMP to 4F92H to move forward 16 bytes.
4FA7
LD C,L 4D
Copy Register L (the position) into Register C; 4F14H loads Register C again, so the copy is not used.
4FA8
CP 5BH FE 5B
Compare Register A (the key) against 5BH (the up arrow).
4FAA
If the NZ FLAG is set (any other key), JUMP to 50B9H to display Error.
4FAD
LD A,L 7D
Back: copy Register L (the position) into Register A. 4F9FH comes here.
4FAE
SUB E 93
SUBtract Register E (the step) from Register A.
4FAF
LD L,A 6F
Copy Register A into Register L: the new position.
4FB0
If the NO CARRY FLAG is set (still in the page), JUMP to 4F69H.
4FB2
LD B,00H 06 00
Before the start: load Register B with 00H, the high digit.
4FB4
LD L,B 68
Copy Register B (00H) into Register L: the first byte of the page.
4FB5
JUMP to 4F69H to display the cursor on the first digit of the page.

4FB7H - Wait a While for a Key

Scans the keyboard up to 256 times. Returns the NZ FLAG with the key (in upper case) in Register A, or the Z FLAG with Register A = 00H if none was pressed. The M command uses it to blink the cursor.

4FB7
LD D,00H 16 00
Load Register D with 00H: 256 tries. 4F3BH and 4F3FH call here.

Scan Loop

4FB9
PUSH DE D5
Save Register Pair DE (Register D = the tries left) onto the stack.
4FBA
GOSUB to 002BH (ROM) to scan the keyboard: Register A returns the key or 00H.
4FBD
POP DE D1
Restore Register Pair DE from the stack: Register D = the tries left.
4FBE
GOSUB to 4548H (SYS0/SYS) to change Register A to upper case if it is a lower case letter.
4FC1
OR A B7
OR Register A with itself: the NZ FLAG if a key was pressed.
4FC2
RET NZ C0
If the NZ FLAG is set (a key), RETurn with it in Register A.
4FC3
DEC D 15
DECrement Register D (the tries left of the 256).
4FC4
If the NZ FLAG is set (more tries), LOOP BACK to 4FB9H.
4FC6
RET C9
RETurn with Register A = 00H and the Z FLAG: no key.

4FC7H - Display the Screen

Clears the screen. In the S form (42C4H = 00H) 16 lines of 16 bytes are shown from the 256-byte page holding the first window's address (5034H). In the X form each of the three windows (404CH, 404EH, 4050H) is shown as 4 lines of 16 bytes from its address, followed by a line of four registers: AF, BC, DE, HL; then AF', BC', DE', HL'; then PC, SP, IX, IY. Each register is shown as its name, = and its value in hexadecimal; after AF and AF' the flags follow as the letters SZ1H1PNC, with - for a clear bit. The 16th line is left for the command.

4FC7
LD HL,51D8H 21 D8 51
Point Register Pair HL to 51D8H: 1CH (cursor home), 1FH (clear to the end of the screen) and 03H. 4D4AH and 4F19H call here.
4FCA
GOSUB to 4467H (SYS0/SYS) to display the message at Register Pair HL: the screen is cleared.
4FCD
LD HL,3C00H 21 00 3C
Point Register Pair HL to 3C00H, the top of the screen.
4FD0
LD A,(42C4H) 3A C4 42
Fetch the display form from 42C4H into Register A.
4FD3
OR A B7
OR Register A with itself: the Z FLAG for the S form.
4FD4
If the Z FLAG is set (the S form), JUMP to 5034H.
4FD6
LD DE,404CH 11 4C 40
The X form: point Register Pair DE to 404CH, where the first window's address is kept.
4FD9
LD C,03H 0E 03
Load Register C with 03H: three windows, each with a register line.
4FDB
PUSH DE D5
Save Register Pair DE (the window pointer) onto the stack.
4FDC
LD DE,50DBH 11 DB 50
Point Register Pair DE to 50DBH, the register name table.

Window Loop
Register Pair HL = the screen address, the window pointer on the stack, Register Pair DE = the register table.

4FDF
EX (SP),HL E3
Exchange Register Pair HL with the word at the top of the stack (Stack Pointer): Register Pair HL = the window pointer, the screen address on the stack. 5030H comes here.
4FE0
PUSH DE D5
Save Register Pair DE (the register table pointer) onto the stack.
4FE1
LD E,(HL) 5E
Fetch the low byte of the window's address at Register Pair HL into Register E.
4FE2
INC HL 23
INCrement Register Pair HL to the high byte of the window address.
4FE3
LD D,(HL) 56
Fetch the high byte at Register Pair HL into Register D: Register Pair DE = the window's address.
4FE4
INC HL 23
INCrement Register Pair HL to the next window pointer.
4FE5
POP AF F1
Restore Register Pair AF from the stack: it holds the register table pointer for now.
4FE6
EX (SP),HL E3
Exchange Register Pair HL with the word at the top of the stack (Stack Pointer): Register Pair HL = the screen address, the next window pointer on the stack.
4FE7
PUSH AF F5
Save Register Pair AF (the register table pointer) onto the stack.
4FE8
LD A,04H 3E 04
Load Register A with 04H: four lines of memory for this window.
4FEA
GOSUB to 503BH to display Register A lines of memory from Register Pair DE at the screen address Register Pair HL.
4FED
POP DE D1
Restore Register Pair DE from the stack: the register table pointer.
4FEE
LD B,04H 06 04
Load Register B with 04H: four registers on the line.
4FF0
XOR A AF
Set Register A to 0 with XOR, which sets the Z FLAG: it marks the first register of the line, the only one after which flags can be shown.

Register Loop
Register Pair DE = the table entry, Register Pair HL = the screen address, Register B = the registers left.

4FF1
LD A,(DE) 1A
Fetch the first letter of the register name at Register Pair DE into Register A.
4FF2
EX AF,AF' 08
Exchange Register Pair AF with the alternate AF': the letter and the flags (the Z FLAG only for the first register) are kept there.
4FF3
EX DE,HL EB
Exchange Register Pairs DE and HL: Register Pair DE = the screen address, Register Pair HL = the table entry.
4FF4
PUSH BC C5
Save Register Pair BC (the counters) onto the stack.
4FF5
LD BC,0003H 01 03 00
Load Register Pair BC with 0003H: the three characters of the name.
4FF8
LDIR ED B0
Copy Register Pair BC (3) bytes from Register Pair HL (the name) to Register Pair DE (the screen). Register Pair HL ends at the offset byte.
4FFA
LD A,(HL) 7E
Fetch the offset of the register in the save area at Register Pair HL into Register A.
4FFB
PUSH HL E5
Save Register Pair HL (the table pointer at the offset byte) onto the stack.
4FFC
GOSUB to 50C9H with Register A = the offset: Register Pair HL returns where the register is kept.
4FFF
LD A,(HL) 7E
Fetch the low byte of the register at Register Pair HL into Register A.
5000
INC HL 23
INCrement Register Pair HL to the high byte of the saved register.
5001
LD H,(HL) 66
Fetch the high byte at Register Pair HL into Register H.
5002
LD L,A 6F
Copy Register A (the low byte) into Register L: Register Pair HL = the value of the register.
5003
EX DE,HL EB
Exchange Register Pairs DE and HL: Register Pair HL = the screen address, Register Pair DE = the value.
5004
INC HL 23
INCrement Register Pair HL past one column after the name.
5005
LD (HL),3DH 36 3D
Store 3DH (=) at Register Pair HL on the screen.
5007
INC HL 23
INCrement Register Pair HL (the first of two columns).
5008
INC HL 23
INCrement Register Pair HL (the second): one column after the =.
5009
GOSUB to 44D2H (SYS0/SYS) to display Register Pair DE as four hexadecimal digits at Register Pair HL.
500C
INC L 2C
INCrement Register L past one column after the four digits.
500D
EX AF,AF' 08
Exchange Register Pair AF with the alternate AF': Register A = the first letter of the name, the flags as set at 4FF0H or by the INC L at 5027H.
500E
If the NZ FLAG is set (not the first register of the line), JUMP to 5027H.
5010
CP 41H FE 41
Compare Register A (the first letter) against 41H (A): the Z FLAG for AF and AF'. The line that starts with PC has no flags.
5012
LD A,E 7B
Copy Register E (the low byte of the value, the flag byte) into Register A. LD does not change the flags.
5013
LD B,08H 06 08
Load Register B with 08H: eight flag bits, from S down to C.
5015
LD DE,51DBH 11 DB 51
Point Register Pair DE to 51DBH, the flag letters.

Flag Loop
The Z FLAG from 5010H stays through the loop: RLCA, INC HL, INC DE and DJNZ do not change it.

5018
If the NZ FLAG is set (PC, not AF or AF'), JUMP to 5023H: the eight columns are passed over and nothing is shown.
501A
LD (HL),2DH 36 2D
Store 2DH (-) at Register Pair HL on the screen, for a clear flag.
501C
RLCA 07
Rotate Register A (the flag byte) left: the next flag bit, from bit 7 down, goes into the CARRY FLAG.
501D
If the NO CARRY FLAG is set (the flag is clear), JUMP to 5023H, leaving the -.
501F
EX AF,AF' 08
The flag is set: exchange Register Pair AF with the alternate AF' to free Register A.
5020
LD A,(DE) 1A
Fetch the flag letter at Register Pair DE into Register A.
5021
LD (HL),A 77
Store Register A (the letter) at Register Pair HL on the screen in place of the -.
5022
EX AF,AF' 08
Exchange Register Pair AF with the alternate AF' again: Register A = the flag byte.
5023
INC HL 23
INCrement Register Pair HL to the next screen column. 5018H and 501DH come here.
5024
INC DE 13
INCrement Register Pair DE to the next flag letter.
5025
DECrement Register B and LOOP BACK to 5018H for all eight flags.
5027
INC L 2C
INCrement Register L past one column; this also leaves the NZ FLAG for the next register. 500EH comes here.
5028
INC HL 23
INCrement Register Pair HL (the first of two more columns).
5029
INC HL 23
INCrement Register Pair HL (the second): the place of the next register.
502A
POP DE D1
Restore Register Pair DE from the stack: the table pointer at the offset byte.
502B
POP BC C1
Restore Register Pair BC from the stack: Register B = the registers left, Register C = the windows left.
502C
INC DE 13
INCrement Register Pair DE to the next table entry.
502D
DECrement Register B and LOOP BACK to 4FF1H for the four registers of this line.
502F
DEC C 0D
DECrement Register C (the windows left), setting the Z FLAG at 0.
5030
If the NZ FLAG is set (more windows), LOOP BACK to 4FDFH.
5032
POP AF F1
Drop the window pointer from the stack into Register Pair AF.
5033
RET C9
RETurn to the caller with the whole X form screen drawn.

5034H - S Form: 16 Lines From the Page Start

The first window's address is rounded down to a multiple of 100H.

5034
LD DE,(404CH) ED 5B 4C 40
Fetch the address of the first window from 404CH into Register Pair DE. 4FD4H comes here.
5038
LD E,L 5D
Copy Register L (00H, since Register Pair HL = 3C00H) into Register E: Register Pair DE = the start of the page.
5039
LD A,10H 3E 10
Load Register A with 10H: 16 lines, then go on into 503BH.

503BH - Display Lines of Memory

Register A = the number of lines, Register Pair DE = the address, Register Pair HL = the screen address. Each line: two spaces, the address, two spaces, eight groups of two bytes as four hexadecimal digits and a space, and the 16 bytes as characters. Characters 21H-5FH are shown as they are (21H-7FH when bit 4 of 428CH is set, which the SYS0/SYS reset does every time, its 4E7FH); everything else, space included, is shown as a period. Returns with Register Pair DE after the last byte and Register Pair HL at the next line.

503B
PUSH BC C5
Save Register Pair BC (the caller's counters) onto the stack. 4FEAH calls here; 5039H goes on into it.

Line Loop
Register A = the lines left, Register Pair DE = the address, Register Pair HL = the screen address.

503C
EX AF,AF' 08
Exchange Register Pair AF with the alternate AF': the line counter in Register A is kept there. 5074H comes here.
503D
INC L 2C
INCrement Register L past the first of two spaces.
503E
INC L 2C
INCrement Register L past the second space before the address.
503F
GOSUB to 44D2H (SYS0/SYS) to display Register Pair DE (the address) as four hexadecimal digits at Register Pair HL, which moves on past them.
5042
LD C,08H 0E 08
Load Register C with 08H: eight groups of two bytes.
5044
INC L 2C
INCrement Register L past the first of two spaces.
5045
INC L 2C
INCrement Register L past the second space: Register Pair HL = the place of the first digit.
5046
PUSH HL E5
Save Register Pair HL (the place of the digits) onto the stack.
5047
LD A,L 7D
Copy Register L (the low byte of the digit place) into Register A.
5048
ADD A,28H C6 28
ADD 28H to Register A: the characters start 40 columns to the right (eight groups of five).
504A
LD L,A 6F
Copy Register A into Register L: Register Pair HL = the place of the first character.
504B
EX (SP),HL E3
Exchange Register Pair HL with the word at the top of the stack (Stack Pointer): the place of the characters goes onto the stack, Register Pair HL = the place of the digits again.

Group Loop
Register C = the groups left.

504C
LD B,02H 06 02
Load Register B with 02H: two bytes per group. 506FH comes here.

Byte Loop

504E
LD A,(DE) 1A
Fetch the byte at Register Pair DE into Register A.
504F
GOSUB to 44D7H (SYS0/SYS) to display Register A as two hexadecimal digits at Register Pair HL, which moves on past them.
5052
LD A,(428CH) 3A 8C 42
Fetch the option flags at 428CH into Register A.
5055
AND 10H E6 10
AND Register A with 10H, keeping bit 4, which the SYS0/SYS reset sets every time (its 4E7FH): codes 60H-7FH are displayed as well.
5057
RLCA 07
Rotate Register A left: 20H if bit 4 is set, 00H if not.
5058
PUSH BC C5
Save Register Pair BC (the counters) onto the stack.
5059
ADD A,3FH C6 3F
ADD 3FH to Register A: 3FH, or 5FH with bit 4 set, the number of codes from 21H that are shown as they are.
505B
LD C,A 4F
Copy Register A (3FH or 5FH, the codes shown) into Register C.
505C
LD A,(DE) 1A
Fetch the byte at Register Pair DE into Register A again.
505D
SUB 21H D6 21
SUBtract 21H from Register A: the codes are counted from 21H, and 00H-20H become large.
505F
CP C B9
Compare Register A against Register C: the CARRY FLAG if the byte can be shown as it is.
5060
POP BC C1
Restore Register Pair BC from the stack: the counters. POP does not change the flags.
5061
LD A,(DE) 1A
Fetch the byte at Register Pair DE into Register A again.
5062
INC DE 13
INCrement Register Pair DE to the next byte. INC DE does not change the flags.
5063
If the CARRY FLAG is set (the byte can be shown), JUMP to 5067H.
5065
LD A,2EH 3E 2E
Load Register A with 2EH, a period, in its place.
5067
EX (SP),HL E3
Exchange Register Pair HL with the word at the top of the stack (Stack Pointer): Register Pair HL = the place of the next character. 5063H comes here.
5068
LD (HL),A 77
Store Register A (the character) at Register Pair HL on the screen.
5069
INC HL 23
INCrement Register Pair HL to the place of the next character.
506A
EX (SP),HL E3
Exchange Register Pair HL with the word at the top of the stack (Stack Pointer) again: Register Pair HL = the place of the next digits.
506B
DECrement Register B and LOOP BACK to 504EH for the second byte of the group.
506D
INC HL 23
INCrement Register Pair HL past the space after the group.
506E
DEC C 0D
DECrement Register C (the groups left), setting the Z FLAG at 0.
506F
If the NZ FLAG is set (more groups), LOOP BACK to 504CH.
5071
POP HL E1
Restore Register Pair HL from the stack: the place after the 16th character, the start of the next screen line.
5072
EX AF,AF' 08
Exchange Register Pair AF with the alternate AF': Register A = the lines left.
5073
DEC A 3D
DECrement Register A (the lines left), setting the Z FLAG at 0.
5074
If the NZ FLAG is set (more lines), LOOP BACK to 503CH.
5076
POP BC C1
Restore Register Pair BC from the stack: the caller's counters.
5077
RET C9
RETurn with Register Pair DE after the last byte and Register Pair HL at the next line.

5078H - Read a Number

5078H moves Register Pair HL past one character first. 5079H reads a hexadecimal number, 507BH a number in the base in Register A (0AH from 4E99H). The first character must be a digit (0-9 or A-F; A-F are accepted in base 10 too, with the values 10-15). Reading stops at the first other character, left at Register Pair HL. Returns Register Pair DE = the value; a value over FFFFH, or no digit, goes to Error.

5078
INC HL 23
INCrement Register Pair HL past the letter or separator. 4D93H, 4E20H, 50ABH and 50B2H call here.
5079
LD A,10H 3E 10
Load Register A with 10H: base 16. 4D83H and 4E13H call here.
507B
PUSH BC C5
Save Register Pair BC (the caller's) onto the stack. 4E9BH calls here with Register A = 0AH.
507C
LD C,A 4F
Copy Register A (the base, 10H or 0AH) into Register C.
507D
LD DE,0000H 11 00 00
Load Register Pair DE with 0000H: the value so far.
5080
GOSUB to 509CH to test the character at Register Pair HL: the CARRY FLAG and its value in Register A for a digit.
5083
If the NO CARRY FLAG is set (no digit), JUMP to 50B9H to display Error.

Digit Loop
Register A = the value of the digit, Register Pair DE = the number so far, Register C = the base.

5085
PUSH HL E5
Save Register Pair HL (the text pointer) onto the stack. 5097H comes here.
5086
EX DE,HL EB
Exchange Register Pairs DE and HL: Register Pair HL = the number so far.
5087
LD E,A 5F
Copy Register A (the value of the digit) into Register E.
5088
LD D,00H 16 00
Load Register D with 00H: Register Pair DE = the digit.
508A
LD A,C 79
Copy Register C (the base) into Register A for the multiply.
508B
GOSUB to 4C39H (SYS0/SYS) to multiply Register Pair HL by Register A: the 24-bit result in Register A (high), Register H and Register L.
508E
ADD HL,DE 19
ADD Register Pair DE (the digit) to Register Pair HL.
508F
EX DE,HL EB
Exchange Register Pairs DE and HL: Register Pair DE = the new number.
5090
ADC A,A 8F
ADD Register A (the high byte of the product) to itself with the CARRY FLAG: not 0 if the number no longer fits in 16 bits.
5091
If the NZ FLAG is set (over FFFFH), JUMP to 50B9H to display Error.
5093
POP HL E1
Restore Register Pair HL from the stack: the text pointer.
5094
GOSUB to 509BH to move Register Pair HL to the next character and test it: the CARRY FLAG and its value in Register A for a digit.
5097
If the CARRY FLAG is set (another digit), LOOP BACK to 5085H.
5099
POP BC C1
Restore Register Pair BC from the stack: the caller's.
509A
RET C9
RETurn with the number in Register Pair DE and Register Pair HL at the character after it.

509BH - Test for a Hexadecimal Digit

509BH moves Register Pair HL to the next character, 509CH tests the character at Register Pair HL, 509DH the character in Register A. Returns the CARRY FLAG and Register A = 00H-0FH for 0-9 and A-F; otherwise the NO CARRY FLAG.

509B
INC HL 23
INCrement Register Pair HL to the next character. 4D7EH and 5094H call here.
509C
LD A,(HL) 7E
Fetch the character at Register Pair HL into Register A. 5080H calls here.
509D
SUB 30H D6 30
SUBtract 30H (the character 0) from Register A. 4F49H calls here with a key in Register A.
509F
CP 0AH FE 0A
Compare Register A against 0AH: the CARRY FLAG for 0-9.
50A1
RET C D8
If the CARRY FLAG is set (0-9), RETurn with the value in Register A.
50A2
SUB 11H D6 11
SUBtract 11H more from Register A: the letter A becomes 00H.
50A4
CP 06H FE 06
Compare Register A against 06H: the CARRY FLAG for A-F.
50A6
RET NC D0
If the NO CARRY FLAG is set (not a digit), RETurn with the NO CARRY FLAG.
50A7
ADD A,0AH C6 0A
ADD 0AH to Register A: the values 10-15 for A-F.
50A9
SCF 37
Set the CARRY FLAG: the character was a hexadecimal digit.
50AA
RET C9
RETurn with the CARRY FLAG and the value in Register A.

50ABH - Read a Number, Then Expect a Comma or the End

50ABH: 5078H, then the character must be a comma. 50AEH: only the comma test. 50B2H: 5078H, then the line must end (0DH). 50B5H: only the end test. Anything else goes to Error.

50AB
GOSUB to 5078H to move Register Pair HL past one character and read a hexadecimal number into Register Pair DE. 4E8DH calls here.
50AE
LD A,2CH 3E 2C
Load Register A with 2CH: a comma is expected. 4E1DH calls here.
50B0
JUMP to 50B7H to compare the comma with the character.
50B2
GOSUB to 5078H to move Register Pair HL past one character and read a hexadecimal number into Register Pair DE. 4DF8H, 4EB9H and 4F0AH call here.
50B5
LD A,0DH 3E 0D
Load Register A with 0DH: the end of the line is expected. 4D9EH, 4E9EH and 4EC9H call here.
50B7
CP (HL) BE
Compare Register A (the character expected) against the character at Register Pair HL. 50B0H comes here.
50B8
RET Z C8
If the Z FLAG is set (it is there), RETurn to the caller; otherwise go on into 50B9H.

50B9H - Display Error

Every command error ends here. Error is shown after the command on the bottom line; DEBUG waits for ENTER and goes back to the command loop.

50B9
LD HL,51D2H 21 D2 51
Point Register Pair HL to 51D2H, the message Error. 4DE9H, 4E68H, 4FAAH, 5083H, 5091H and 51C5H come here.
50BC
GOSUB to 4467H (SYS0/SYS) to display the message at Register Pair HL after the command.

ENTER Loop

50BF
GOSUB to 0049H (ROM) to wait for a key; Register A returns it.
50C2
CP 0DH FE 0D
Compare Register A (the key) against 0DH (ENTER).
50C4
If the NZ FLAG is set (another key), LOOP BACK to 50BFH.
50C6
JUMP to 4D43H, the command loop, which also resets the Stack Pointer.

50C9H - Address of a Saved Register

Register A = the register's offset from the table at 50DBH. Returns Register Pair HL = the save area address (base + offset) for offsets below 14H, 4DC7H (the resume PC) for 14H and 4DC3H (the program's Stack Pointer) for 16H. Register Pair BC is changed.

50C9
LD HL,(4D44H) 2A 44 4D
Fetch the base of the save area from 4D44H, the operand of the LD SP,nnnn at 4D43H, into Register Pair HL. 4DFCH and 4FFCH call here.
50CC
LD C,A 4F
Copy Register A (the offset) into Register C.
50CD
LD B,00H 06 00
Load Register B with 00H: Register Pair BC = the offset.
50CF
ADD HL,BC 09
ADD Register Pair BC to Register Pair HL: the base plus the offset.
50D0
CP 14H FE 14
Compare Register A (the offset) against 14H: the CARRY FLAG for a register kept in the save area.
50D2
RET C D8
If the CARRY FLAG is set (below 14H), RETurn with Register Pair HL in the save area.
50D3
LD HL,4DC7H 21 C7 4D
Point Register Pair HL to 4DC7H, where the PC is kept (the operand of the LD HL,nnnn at 4DC6H). LD does not change the flags.
50D6
RET Z C8
If the Z FLAG is set (offset 14H, PC), RETurn with Register Pair HL = 4DC7H.
50D7
LD HL,4DC3H 21 C3 4D
Point Register Pair HL to 4DC3H, where the Stack Pointer is kept (the operand of the LD SP,nnnn at 4DC2H).
50DA
RET C9
RETurn with Register Pair HL = 4DC3H (offset 16H, SP).

50DBH - Register Name Table (Data)

Used by the R command (4DD1H) and the X form display (4FDCH): four bytes per register, the name padded to three characters and its offset in the save area (see 4D00H and 50C9H). The order is the display order. Ends with 00H.

50DB-50DE
DEFM "AF ", 12H 41 46 20 12
AF: the name and offset 12H in the save area (4D00H pushed it from 45D4H's PUSH AF). First in the X form's first register line.
50DF-50E2
DEFM "BC ", 0EH 42 43 20 0E
BC: the name and offset 0EH in the save area, pushed at 4D01H.
50E3-50E6
DEFM "DE ", 0CH 44 45 20 0C
DE: the name and offset 0CH in the save area, pushed at 4D02H.
50E7-50EA
DEFM "HL ", 10H 48 4C 20 10
HL: the name and offset 10H in the save area, put there by the EX (SP),HL at 4D00H.
50EB-50EE
DEFM "AF'", 0AH 41 46 27 0A
AF': the name and offset 0AH in the save area, pushed at 4D05H. First in the second register line, so its flags are shown too.
50EF-50F2
DEFM "BC'", 08H 42 43 27 08
BC': the name and offset 08H in the save area, pushed at 4D06H.
50F3-50F6
DEFM "DE'", 06H 44 45 27 06
DE': the name and offset 06H in the save area, pushed at 4D07H.
50F7-50FA
DEFM "HL'", 04H 48 4C 27 04
HL': the name and offset 04H in the save area, pushed at 4D08H.
50FB-50FE
DEFM "PC ", 14H 50 43 20 14
PC: the name and offset 14H, which 50C9H turns into 4DC7H, the operand that holds the resume PC.
50FF-5102
DEFM "SP ", 16H 53 50 20 16
SP: the name and offset 16H, which 50C9H turns into 4DC3H, the operand that holds the program's Stack Pointer.
5103-5106
DEFM "IX ", 02H 49 58 20 02
IX: the name and offset 02H in the save area, pushed at 4D09H.
5107-510A
DEFM "IY ", 00H 49 59 20 00
IY: the name and offset 00H in the save area, pushed at 4D0BH.
510B
DEFB 00H 00
The end of the table, tested by the R command at 4DE6H.

510CH - Opcode Table for Single Steps (Data)

Used by 5156H: pairs of an opcode and the low byte of its handler in page 51H. Opcodes not in the table (and not handled before 5156H) are one byte long and the step stops at the next instruction. Ends with 00H.

510C-510D
DEFB 10H, 81H 10 81
DJNZ: handled at 5181H, a branch that may or may not be taken (bit 0 of 10H is clear).
510E-510F
DEFB 18H, 80H 18 80
JR: handled at 5180H, whose INC C makes Register C = 19H, a branch that is always taken.
5110-5111
DEFB C3H, 96H C3 96
JP nnnn: handled at 5196H, which reads the target from the instruction.
5112-5113
DEFB C9H, C8H C9 C8
RET: handled at 51C8H, which reads the return address from the program's stack.
5114-5115
DEFB CBH, ABH CB AB
The CB prefix: handled at 51ABH, a two-byte instruction.
5116-5117
DEFB CDH, B8H CD B8
CALL nnnn: handled at 51B8H, which reads the target from the instruction.
5118-5119
DEFB D3H, ABH D3 AB
OUT (n),A: handled at 51ABH, a two-byte instruction.
511A-511B
DEFB DBH, ABH DB AB
IN A,(n): handled at 51ABH, a two-byte instruction.
511C-511D
DEFB DDH, 25H DD 25
The DD prefix (IX): handled at 5125H with Register E = 02H.
511E-511F
DEFB E9H, 8EH E9 8E
JP (HL): handled at 518EH, which reads the target from the saved HL.
5120-5121
DEFB EDH, 9EH ED 9E
The ED prefix: handled at 519EH, which counts two or four bytes.
5122-5123
DEFB FDH, 29H FD 29
The FD prefix (IY): handled at 5129H with Register E = 00H.
5124
DEFB 00H 00
The end of the table, tested by the OR A at 515AH.

5125H - Single Step: DD and FD Prefixes

Register E = the offset of IX (02H) or IY (00H) in the save area, used for JP (IX) / JP (IY). Register Pair HL points to the byte after the prefix. Instructions that do not need special handling go on to 5140H with Register C = the second opcode and the prefix already counted in Register Pair HL.

5125
LD E,02H 1E 02
DD: load Register E with 02H, the offset of the saved IX.
5127
JUMP to 512BH to fetch the opcode after the prefix.
5129
LD E,00H 1E 00
FD: load Register E with 00H, the offset of the saved IY.
512B
LD C,(HL) 4E
Fetch the opcode after the prefix at Register Pair HL into Register C. 5127H comes here.
512C
LD A,C 79
Copy Register C (the second opcode) into Register A.
512D
CP E9H FE E9
Compare Register A against E9H: JP (IX) or JP (IY).
512F
INC HL 23
INCrement Register Pair HL past the second opcode. INC HL does not change the flags.
5130
If the Z FLAG is set (JP (IX) or JP (IY)), JUMP to 5190H: the next instruction is at the value of the saved register at offset Register E.
5132
CP CBH FE CB
Compare Register A against CBH: DD CB d op or FD CB d op, four bytes.
5134
If the Z FLAG is set (CB), JUMP to 51AAH to count two more bytes.
5136
SUB 34H D6 34
SUBtract 34H from Register A (the second opcode).
5138
CP 02H FE 02
Compare Register A against 02H: the opcode was 36H, LD (IX+d),n or LD (IY+d),n, four bytes.
513A
If the Z FLAG is set (36H), JUMP to 51AAH to count two more bytes.
513C
CP 8CH FE 8C
Compare Register A against 8CH: the CARRY FLAG for second opcodes 34H-BFH, which have a displacement byte (three bytes in all). 39H (ADD IX,SP, two bytes) is in this range too and is counted one byte too long.
513E
If the CARRY FLAG is set (34H-BFH), JUMP to 51ABH to count one more byte. Any other second opcode goes on into 5140H.

5140H - Single Step: Find the Next Instruction

Entered from 4ED6H for I and C with Register C = the opcode, Register Pair HL = PC + 1 and Register B = 00H (I) or 01H (C); and from 513EH for an instruction after a DD or FD prefix, which is handled like the same opcode without the prefix (for example 21H LD IX,nnnn, E1H POP IX) with the prefix already counted in Register Pair HL. The step is done by setting breakpoints at the instruction or instructions that can run next and resuming the program (4DA1H). At 51AEH Register Pair HL holds the address that follows in memory or the branch target that is always taken, and Register Pair DE the other possible address (Register D = 00H if there is none). Both must be 5200H or higher, otherwise Error. Opcodes C0H-FFH are sorted by their low three bits: 0 RET cc, 2 JP cc, 4 CALL cc, 6 immediate operations; the rest through the table at 510CH. RST is not in the table, so it counts as one byte and runs to its end.

5140
LD A,C 79
Copy Register C (the opcode) into Register A. 4ED6H comes here.
5141
CP C0H FE C0
Compare Register A (the opcode) against C0H: the CARRY FLAG below C0H.
5143
If the CARRY FLAG is set (below C0H), JUMP to 5168H.
5145
AND 07H E6 07
AND Register A with 07H, keeping the low three bits of the opcode.
5147
If the Z FLAG is set (low bits 0, RET cc), JUMP to 51C8H.
5149
CP 02H FE 02
Compare Register A (the low bits) against 02H: JP cc,nnnn.
514B
If the Z FLAG is set (JP cc,nnnn), JUMP to 5196H with Register Pair HL at the operand.
514D
CP 04H FE 04
Compare Register A against 04H: CALL cc,nnnn.
514F
If the Z FLAG is set (CALL cc,nnnn), JUMP to 51B8H.
5152
CP 06H FE 06
Compare Register A against 06H: an operation with an immediate byte (ADD A,n and the like), or LD r,n when 5176H or 517DH comes here.
5154
If the Z FLAG is set (low bits 6), JUMP to 51ABH: two bytes.
5156
LD DE,510CH 11 0C 51
Point Register Pair DE to 510CH, the opcode table.

Table Loop

5159
LD A,(DE) 1A
Fetch the table opcode at Register Pair DE into Register A.
515A
OR A B7
OR Register A with itself: the Z FLAG for the 00H that ends the table.
515B
INC DE 13
INCrement Register Pair DE to the handler byte. INC DE does not change the flags.
515C
If the Z FLAG is set (the end of the table), JUMP to 51ACH: the instruction is one byte long.
515E
CP C B9
Compare Register A (the table opcode) against Register C (the opcode).
515F
LD A,(DE) 1A
Fetch the handler byte at Register Pair DE into Register A. LD does not change the flags.
5160
INC DE 13
INCrement Register Pair DE to the next entry. INC DE does not change the flags.
5161
If the NZ FLAG is set (another opcode), LOOP BACK to 5159H.
5163
LD E,A 5F
Found: copy Register A (the handler's low byte) into Register E.
5164
LD D,51H 16 51
Load Register D with 51H: Register Pair DE = the handler in page 51H.
5166
PUSH DE D5
Save Register Pair DE (the handler) onto the stack.
5167
RET C9
RETurn: the RET jumps to the handler on the stack.

5168H - Single Step: Opcodes Below C0H

40H-BFH (LD r,r and arithmetic on registers) are one byte. Below 40H: xxx1H (LD rr,nnnn) three bytes; in 00H-1FH LD r,n (x6H/xEH) two bytes and DJNZ/JR through the table; in 20H-3FH 22H/2AH/32H/3AH three bytes, 26H/2EH/36H/3EH two bytes, and 20H/28H/30H/38H (JR cc) go to 517FH.

5168
CP 40H FE 40
Compare Register A (the opcode) against 40H. 5143H comes here.
516A
If the NO CARRY FLAG is set (40H-BFH), JUMP to 51ACH: one byte.
516C
AND 0FH E6 0F
AND Register A with 0FH, keeping the low four bits.
516E
CP 01H FE 01
Compare Register A against 01H: xxx1H, LD rr,nnnn.
5170
If the Z FLAG is set (LD rr,nnnn), JUMP to 51AAH: three bytes.
5172
AND 07H E6 07
AND Register A with 07H, keeping the low three bits.
5174
BIT 5,C CB 69
Test bit 5 of Register C (the opcode): clear for 00H-1FH.
5176
If the Z FLAG is set (00H-1FH), JUMP to 5152H: LD r,n is two bytes, DJNZ and JR go through the table, the rest is one byte.
5178
CP 02H FE 02
20H-3FH: compare Register A against 02H, the LD (nnnn),HL / LD HL,(nnnn) / LD (nnnn),A / LD A,(nnnn) forms.
517A
If the Z FLAG is set (x2H or xAH), JUMP to 51AAH: three bytes.
517C
OR A B7
OR Register A with itself: the Z FLAG for low bits 0, JR cc.
517D
If the NZ FLAG is set (not JR cc), JUMP to 5152H.

517FH - Single Step: JR and DJNZ

JR cc (20H, 28H, 30H, 38H) and DJNZ (10H, table entry 5181H) can go on at either the target or the next instruction. For JR (18H) the table entry is 5180H, whose INC C makes bit 0 of Register C set (19H), which 51BCH treats as a branch that is always taken.

517F
DEC C 0D
JR cc: DECrement Register C (the opcode), undone by the INC C below.
5180
INC C 0C
INCrement Register C: unchanged for JR cc; JR (18H) enters here from the table and becomes 19H, a branch that is always taken.
5181
LD A,(HL) 7E
Fetch the displacement at Register Pair HL into Register A. DJNZ enters here from the table.
5182
LD E,A 5F
Copy Register A (the displacement) into Register E.
5183
LD D,00H 16 00
Load Register D with 00H: Register Pair DE = a positive displacement.
5185
INC HL 23
INCrement Register Pair HL to the next instruction.
5186
RLCA 07
Rotate Register A left: bit 7, the sign of the displacement, goes into the CARRY FLAG.
5187
If the NO CARRY FLAG is set (a positive displacement), JUMP to 518AH.
5189
DEC D 15
A negative displacement: DECrement Register D to FFH.
518A
EX DE,HL EB
Exchange Register Pairs DE and HL: Register Pair HL = the displacement, Register Pair DE = the next instruction. 5187H comes here.
518B
ADD HL,DE 19
ADD Register Pair DE (the next instruction) to Register Pair HL: Register Pair HL = the target.
518C
JUMP to 519BH with Register Pair HL = the target of the jump.

518EH - Single Step: JP (HL), JP (IX), JP (IY) and JP nnnn

Reads the target from the register save area (JP (HL), offset 10H; JP (IX)/JP (IY) with Register E from 5125H/5129H) or, for JP nnnn and JP cc,nnnn (5196H), from the instruction.

518E
LD E,10H 1E 10
JP (HL): load Register E with 10H, the offset of the saved HL.
5190
LD D,00H 16 00
Load Register D with 00H: Register Pair DE = the offset. 5130H comes here for JP (IX) and JP (IY).
5192
LD HL,(4D44H) 2A 44 4D
Fetch the base of the save area from 4D44H into Register Pair HL.
5195
ADD HL,DE 19
ADD Register Pair DE (the offset) to Register Pair HL: Register Pair HL = the saved register.
5196
LD E,(HL) 5E
Fetch the low byte of the target at Register Pair HL into Register E. JP cc,nnnn (514BH) and JP nnnn (the table) enter here with Register Pair HL at the operand.
5197
INC HL 23
INCrement Register Pair HL to the high byte of the target.
5198
LD D,(HL) 56
Fetch the high byte at Register Pair HL into Register D: Register Pair DE = the target.
5199
INC HL 23
INCrement Register Pair HL past it: for JP cc, the next instruction.
519A
EX DE,HL EB
Exchange Register Pairs DE and HL: Register Pair HL = the target, Register Pair DE = the next instruction.
519B
LD B,C 41
Copy Register C (the opcode) into Register B: bit 0 is set for a branch that is always taken (C3H, C9H, E9H, 19H, EDH), clear for one that depends on a condition. 518CH and 51D0H come here.
519C
JUMP to 51BCH to test bit 0 of Register B (always taken or not).

519EH - Single Step: ED Prefix

ED x5H (RETN, RETI) go to 51C8H, ED x3H (LD (nnnn),rr and LD rr,(nnnn)) are four bytes; every other ED instruction is two bytes. OUTI, OUTD, OTIR and OTDR (ED A3H, ABH, B3H, BBH) also end in 3 and are counted as four bytes, two too many.

519E
LD A,(HL) 7E
Fetch the byte after ED at Register Pair HL into Register A.
519F
AND 07H E6 07
AND Register A with 07H, keeping the low three bits.
51A1
CP 05H FE 05
Compare Register A against 05H: RETN or RETI.
51A3
INC HL 23
INCrement Register Pair HL past the second byte. INC HL does not change the flags.
51A4
If the Z FLAG is set (RETN or RETI), JUMP to 51C8H.
51A6
CP 03H FE 03
Compare Register A against 03H: the four-byte LD forms.
51A8
If the NZ FLAG is set (anything else), JUMP to 51ACH: two bytes.
51AA
INC HL 23
INCrement Register Pair HL past an operand byte (the first of two). 5134H, 513AH, 5170H and 517AH come here.
51AB
INC HL 23
INCrement Register Pair HL past one more byte. 513EH and 5154H come here.

51ACH - Single Step: Set the Breakpoints

Register Pair HL = the next instruction (or the target of a branch that is always taken), Register Pair DE = the other address (Register D = 00H: none).

51AC
LD D,00H 16 00
Load Register D with 00H: no second breakpoint (an address in the ROM). 515CH, 516AH, 51A8H and 51BEH come here.
51AE
LD A,H 7C
Copy Register H (the high byte of the first address) into Register A. 51C3H comes here.
51AF
CP 52H FE 52
Compare Register A against 52H: the CARRY FLAG for an address below 5200H.
51B1
If the CARRY FLAG is set (below 5200H), JUMP to 51C5H to display Error.
51B3
PUSH HL E5
Save Register Pair HL (the first address) onto the stack.
51B4
PUSH DE D5
Save Register Pair DE (the second address) onto the stack.
51B5
JUMP to 4DA1H to set the two breakpoints and resume the program.

51B8H - Single Step: CALL

CALL nnnn and CALL cc,nnnn. For C (Register B = 01H) the call runs to its end: only the return address gets a breakpoint. For I both the return address and the target do; a target below 5200H displays Error.

51B8
LD E,(HL) 5E
Fetch the low byte of the target at Register Pair HL into Register E. 514FH and the table come here.
51B9
INC HL 23
INCrement Register Pair HL to the high byte of the target.
51BA
LD D,(HL) 56
Fetch the high byte at Register Pair HL into Register D: Register Pair DE = the target.
51BB
INC HL 23
INCrement Register Pair HL to the return address, the instruction after the CALL.
51BC
BIT 0,B CB 40
Test bit 0 of Register B: set for the C command here, or for a branch that is always taken when 519CH comes here.
51BE
If the NZ FLAG is set, JUMP to 51ACH: only the address in Register Pair HL gets a breakpoint.
51C0
LD A,D 7A
Copy Register D (the high byte of the second address) into Register A.
51C1
CP 52H FE 52
Compare Register A against 52H: the NO CARRY FLAG for 5200H or higher.
51C3
If the NO CARRY FLAG is set (5200H or higher), JUMP to 51AEH: both addresses get breakpoints.
51C5
JUMP to 50B9H to display Error. 51B1H comes here.

51C8H - Single Step: RET

RET, RET cc, RETN and RETI. The return address is read from the program's stack (4DC3H); for RET cc the next instruction is the other possibility.

51C8
EX DE,HL EB
Exchange Register Pairs DE and HL: Register Pair DE = the next instruction. 5147H and 51A4H come here.
51C9
LD HL,(4DC3H) 2A C3 4D
Fetch the program's Stack Pointer from 4DC3H into Register Pair HL.
51CC
LD A,(HL) 7E
Fetch the low byte of the return address at Register Pair HL into Register A.
51CD
INC HL 23
INCrement Register Pair HL to the high byte of the return address.
51CE
LD H,(HL) 66
Fetch the high byte at Register Pair HL into Register H.
51CF
LD L,A 6F
Copy Register A (the low byte) into Register L: Register Pair HL = the return address.
51D0
JUMP to 519BH: bit 0 of the opcode decides; C9H and EDH are always taken, RET cc is not.

51D2H - Messages and Flag Letters (Data)

The Error message, the clear-screen string and the flag letters, followed by five unused bytes.

51D2-51D7
DEFM "Error", 03H 45 72 72 6F 72 03
The error message displayed by 50B9H after the command, ended by 03H.
51D8-51DA
DEFB 1CH, 1FH, 03H 1C 1F 03
Displayed by 4FC7H to clear the screen: 1CH cursor home, 1FH clear to the end of the screen, 03H the end.
51DB-51E2
DEFM "SZ1H1PNC" 53 5A 31 48 31 50 4E 43
The flag letters for bits 7-0 of F, read by 5020H. Bits 5 and 3 have no name and show as 1 when they are set.
51E3-51E7
NOP x 5 00 x 5
Five bytes of 00H to the end of the file (51E7H). Nothing uses them; 51E8H-51FFH, after the file, is the F string (51E8H) and the input buffer (51ECH).