TRS-80 DOS - VTOS 4.0.2 for the Model I - SYS9/SYS Disassembled

Page Customization

Introduction/Summary

VTOS 4.0.2 SYS9/SYS Disassembly - The Extended DEBUG Commands (Model I)

SYS9/SYS adds commands to the DEBUG monitor of SYS5/SYS. DEBUG (EXT) (SYS6/SYS member 6, 523EH) issues request 8BH; the request handler loads SYS9/SYS at 4E00H (directory entry code 23H) and calls it. It copies its command reader (4E27H-51F3H, 973 bytes) to the top of memory, lowers the top of memory 4049H below it and puts the copy's address at 4310H, where every request below 80H goes. SYS5/SYS hands each key that is not one of its own commands to RST 28H (its 4E97H), so the copy gets the key and runs the extended command, using SYS5/SYS's routines for keys, hex numbers and hex output and its cells for the addresses. The manual: "An extended DEBUG facility may be loaded into high memory by setting the 'EXT' flag."

The file starts with a record of type 05H (the name SYS9), a record of type 1FH holding the copyright notice of Randolph Cook (1980) and four load blocks that fill 4E00H-51F3H, 1012 bytes; the last record gives the transfer address 4E00H, and one byte 03H follows it, which the loader never reads. The file carries no patch. The rows show the command reader at its file addresses; it runs from the copy, and its relative jumps land on the rows of this page. Its calls to 518AH, 51A3H, 51D0H, 51D4H, 51D9H and 51F2H go to SYS5/SYS, which is in memory whenever the copy is entered from DEBUG, not to this file's rows at those addresses.

The Installation

RST 28H with Register A = 40H (4E26H) asks whatever 4310H points at; the copied reader answers 40H with 00H, SYS0/SYS's default 4C2FH returns Register A unchanged. Only when the answer is not 00H is the reader copied (4E07H): the old contents of 4310H go into the operand of JP NZ at 5134H first, so that keys the reader does not know go on to them.

The Commands

Numbers are hex, typed with SYS5/SYS's 51A3H: ended by a space, a comma or ENTER, only the last four digits counting, and a key that is not a hex digit ends the command. Where a field may be left empty, SYS9/SYS shows the value it takes instead.

KeysWhat the Code Does
B source,dest,countBlock move with LDIR, low addresses first (defaults: the display address 4063H, the M address 4060H, 0100H) (4E38H).
E addressEnter bytes in hex from the address (default the M address); a space or a comma with no digits keeps a byte, ENTER ends (4E84H).
F start,end,byteFill from the start to the end, the end included; an end of FFFFH never stops (4EB7H).
JThe saved program counter 407BH plus 1 (4ED7H).
L address,byteLocate the next byte (defaults: the M address plus 1, the last byte, 4062H); always found, at 4062H when nowhere else (4EE3H).
N addressNext block: the address (default the M address) plus the byte after it plus 2, a byte 00H counting 256 (4F2AH).
OO and ENTER: VTOS READY (402DH) (4E2DH).
P start,endPrint memory in hex and characters, 16 bytes a line; an end of FFF1H-FFFFH never stops (5132H).
Q port or Q port,valueRead a port and show it, or write a value to it (4F4AH).
T addressType characters into memory (4F6EH).
V first,second,countCompare two blocks up to the first difference (4FADH).
W address,wordSearch for a word, low byte first (defaults: the M address plus 2, the last word in 4062H and 405FH) (5008H).
0-7,cyl,sec,o,addr,countMove sectors between a drive and memory: R read, W write, an asterisk write with the directory's data mark (505EH).

Points to Note

SYS9/SYS keeps its values in SYS5/SYS's cells: the M address 4060H-4061H, the display address 4063H-4064H, 4062H (the byte of L, the low byte of W, the sector count) and 405FH (the high byte of W, the sectors of a cylinder). 4062H and 405FH are the saved bytes of SYS5/SYS's breakpoint slots: an entry into DEBUG clears only the slot addresses (405DH-405EH, 4060H-4061H), so these values stay, and a G with breakpoints puts the replaced bytes there, which then become the defaults of L and W.

W leaves the M address on the byte before the word found, the opcode when the word is the operand of a three byte instruction (5052H); the next W starts after the word's low byte.

L and W show the low byte of a typed start, or the start itself, as the value searched for when that value is not typed; the search uses the last value, 4062H and 405FH (4F0EH, 503CH). L never fails: 4062H holds the byte searched for, so CPIR over all 65536 addresses finds it there at worst.

F with a start equal to or above the end stores nothing; otherwise the end is included, since every compare after the first subtracts the carry of the one before (4ECFH). With an end of FFFFH the address wraps to 0000H, still below the end, and F fills all memory, SYS5/SYS and the copy itself included.

N takes the byte after the address as an unsigned length, so on a JR with a jump back it moves forward (4F37H).

P goes on while the next line's address is below the end, so an end that is the first byte of a line is not printed, although the manual says the end is printed (51E4H); an end of FFF1H-FFFFH wraps and never stops, and no key is tested.

In the disk command a failed sector shows its error code between two asterisks and, after any key, the next sector is done (5119H); BREAK does not stop it. R takes the code 06H as a good read, which covers the data marks FAH and F8H. The separators after the drive and the operation take any key, so a digit typed there is lost. An address field left empty takes the last number read; with nothing typed in any field it is the value Register Pair HL held before, Register H being the sectors of a track (for instance 0A4BH): a read there goes into the ROM, a write sends the ROM's bytes to the disk.

The test at 5134H sends every request below 80H that is not one of the reader's codes to the address 4310H held before; the ROM's keyboard routine passes BREAK (01H) this way, so the copy runs outside DEBUG too. Requests with the codes of its commands reach the reader whoever makes them, and its calls into SYS5/SYS are only good while SYS5/SYS is in memory.

Lowering the top of memory once, SYS9/SYS leaves 03CDH bytes in use for good; DEBUG (EXT) again finds the reader there and copies nothing.

Memory Map

Load Areas

Addresses
Size
Contents
4E00H-4E26H
39 bytes
Installation
The test through 4310H, the copy to the top of memory, 4310H pointed at it.
4E27H-4E2CH
6 bytes
@
The answer 00H to the test.
4E2DH-4E37H
11 bytes
O
VTOS READY after ENTER.
4E38H-4E83H
76 bytes
B
Block move.
4E84H-4EB6H
51 bytes
E
Enter bytes.
4EB7H-4ED6H
32 bytes
F
Fill.
4ED7H-4EE2H
12 bytes
J
The program counter plus 1.
4EE3H-4F29H
71 bytes
L
Locate a byte.
4F2AH-4F49H
32 bytes
N
Next block.
4F4AH-4F6DH
36 bytes
Q
Read or write a port.
4F6EH-4FACH
63 bytes
T
Type characters.
4FADH-5007H
91 bytes
V
Compare two blocks.
5008H-505DH
86 bytes
W
Search for a word.
505EH-5131H
212 bytes
0-7
Sectors to or from a drive.
5132H-51F3H
194 bytes
P
Print memory; other keys to the old hook.

Variables

SYS9/SYS Cells

Address
Size
Contents
5135H-5136H
2 bytes
Old Hook
Operand of JP NZ,0000H at 5134H: 0000H in the file; the contents of 4310H before the installation (4E0AH), normally 4C2FH.

Memory Outside the File

Address
Size
Contents
4049H-404AH
2 bytes
Top of Memory
Lowered by 03CDH (4E14H); the copy lies just above the new value.
4310H-4311H
2 bytes
Low Request Hook
Read at 4E07H, set to the copy at 4E22H: requests below 80H go to the copy.
405EH
1 byte
SYS5/SYS Screen Mode
53H (S) stored after a sector read (50FEH).
405FH
1 byte
SYS5/SYS Slot 2 Byte
The high byte of the word of W (5037H) and the sectors of a cylinder of the disk command (5088H).
4060H-4061H
2 bytes
M Address
Default and result of B, E, L, N, T, V, W; the start of the page of the address after a sector read.
4062H
1 byte
SYS5/SYS Slot 1 Byte
The byte of L (4F09H), the low byte of W (5033H), the count of sectors (50ABH, 50C6H).
4063H-4064H
2 bytes
Display Address
The source of B, the first block of V, the 64 byte block of the M address after L, N, W; the start of the page of the address after a sector read.
407BH-407CH
2 bytes
Saved Program Counter
Plus 1 for J (4EDBH).

Outside Routines

AddressContents
518AHSYS5/SYS: wait for a key and show it, ENTER not shown and other keys below 20H ignored (ENTER: Z and C; space or comma: Z).
51A3HSYS5/SYS: read a hex number into Register Pair HL (NZ digits typed, C ENTER; a key that is not a hex digit, a space, a comma or ENTER ends the command).
51D0HSYS5/SYS: show the byte at Register Pair HL in hex, Register Pair HL plus 1.
51D4HSYS5/SYS: show Register Pair HL as four hex digits.
51D9HSYS5/SYS: show Register A as two hex digits.
51F2HSYS5/SYS: show a space.
478FHSYS0/SYS: Index Register IY = the drive code table of drive Register C.
4763H, 4768H, 4777HSYS0/SYS: driver functions 0DH (write), 0EH (write with FAH), 09H (read).
0033H, 003BHROM: send Register A to the display, to the printer.

Disassembly

4E00H - Entry: Install the Extended Commands

SYS9/SYS is loaded at 4E00H by the request handler of SYS0/SYS (4C31H) for a request code whose bits 3-0 are BH (directory entry code 23H); DEBUG with EXT (SYS6/SYS member 6, its 523EH) issues 8BH. The code does not look at the request code. It first asks whether the extended commands are already in memory: RST 28H with Register A = 40H (a request below 80H) goes to the routine whose address is at 4310H, and the copied command reader answers 40H with Register A = 00H, while SYS0/SYS's default 4C2FH returns Register A unchanged. When they are not there, the top of memory 4049H is lowered by 03CDH bytes, the command reader 4E27H-51F3H is copied just above the new top, and 4310H is pointed at the copy; the old contents of 4310H are kept as the operand at 5135H, where the copy sends every key it does not know.

4E00
LD A,40H 3E 40
Load Register A with 40H, the code the copied command reader answers with 00H.
4E02
GOSUB to 4E26H to issue RST 28H with Register A = 40H; it returns here with Register A = 00H when the extended commands are in memory, and with another value (40H from SYS0/SYS's 4C2FH) when they are not.
4E05
OR A B7
OR Register A with itself: the Z FLAG is set for 00H.
4E06
RET Z C8
If the Z FLAG is set (already in memory), RETURN to the request handler: nothing to do.
4E07
LD HL,(4310H) 2A 10 43
Fetch the address held at 4310H-4311H (where requests below 80H go: SYS0/SYS's 4C2FH unless something else has set it) into Register Pair HL.
4E0A
LD (5135H),HL 22 35 51
Store Register Pair HL to 5135H-5136H, the operand of JP NZ,0000H at 5134H, before the copy: keys that are not commands of SYS9/SYS go on there.
4E0D
LD HL,(4049H) 2A 49 40
Fetch the top of memory from 4049H-404AH into Register Pair HL.
4E10
LD BC,03CDH 01 CD 03
Load Register Pair BC with 03CDH, the 973 bytes of the command reader 4E27H-51F3H.
4E13
XOR A AF
Set Register A to 00H and clear the CARRY FLAG (XOR A) for the subtraction.
4E14
SBC HL,BC ED 42
Subtract Register Pair BC (03CDH) from Register Pair HL: the new top of memory.
4E16
LD (4049H),HL 22 49 40
Store Register Pair HL (the new top of memory) to 4049H-404AH: the copy lies above it, out of the way of programs.
4E19
INC HL 23
Increment Register Pair HL to the first byte above the new top, where the copy goes.
4E1A
PUSH HL E5
Save Register Pair HL (the address of the copy) to the stack.
4E1B
EX DE,HL EB
Exchange Register Pairs DE and HL: Register Pair DE = the address of the copy, the destination.
4E1C
LD HL,4E27H 21 27 4E
Point Register Pair HL to 4E27H, the start of the command reader in this file.
4E1F
LDIR ED B0
Copy Register Pair BC (03CDH) bytes from Register Pair HL to Register Pair DE (LDIR): 4E27H-51F3H go to the top of memory. The reader uses only relative jumps inside itself, so it runs at the new address; its absolute calls go to SYS5/SYS, SYS0/SYS and the ROM.
4E21
POP HL E1
Restore Register Pair HL from the stack: the address of the copy.
4E22
LD (4310H),HL 22 10 43
Store Register Pair HL (the address of the copy) to 4310H-4311H: from now on every request below 80H, the unknown keys of SYS5/SYS's DEBUG among them, goes to the copy.
4E25
RET C9
RETURN to the request handler and from there to DEBUG (SYS6/SYS member 6).
4E26
RST 28H EF
RST 28H to 400CH, the request handler, with Register A = 40H: a code below 80H goes on through 4310H (4C28H) with the return address of RST 28H dropped, so the routine there returns to 4E05H, the return address of the CALL at 4E02H.

4E27H - The Command Reader

Copied to the top of memory by 4E1FH and run there; the rows show it at its file addresses, and its relative jumps land on the rows of this page. SYS5/SYS's command loop sends every key that is not one of its own commands to RST 28H (its 4E97H) with 4E4BH, its command loop, pushed as the return address; for a key below 80H the request handler jumps through 4310H to here with Register A = the key. Each command ends with RET to SYS5/SYS's 4E4BH, which shows the display again. The calls to 518AH (a key), 51A3H (a hex number), 51D0H, 51D4H and 51D9H (hex digits) and 51F2H (a space) are SYS5/SYS's routines, which are in memory at 4E00H whenever the copy is entered from DEBUG. Numbers are hex, ended by a space, a comma or ENTER. Some fields have a default when no digits are typed, which most commands show in its place (V not after ENTER; F, P, Q and the disk command have none).

4E27
CP 40H FE 40
Compare Register A (the key) against 40H, the code of the test at 4E00H (the key @).
4E29
If the NZ FLAG is set (another key), JUMP to 4E2DH.
4E2B
XOR A AF
Set Register A to 00H (XOR A): the answer that the extended commands are in memory.
4E2C
RET C9
RETURN with Register A = 00H to the caller of RST 28H: 4E05H at the test of the installation, SYS5/SYS's command loop 4E4BH when the key @ is typed in DEBUG.

4E2DH - O: Return to VTOS

O followed by ENTER leaves DEBUG for VTOS READY; any other key after O goes back to the monitor.

4E2D
CP 4FH FE 4F
Compare Register A (the key) against 4FH, the letter O.
4E2F
If the NZ FLAG is set (not O), JUMP to 4E38H.
4E31
GOSUB to SYS5/SYS's 518AH to wait for a key and show it: the Z FLAG and the CARRY FLAG for ENTER.
4E34
RET NC D0
If the NC FLAG is set (not ENTER), RETURN to the monitor.
4E35
JUMP to 402DH, the normal exit: VTOS READY. The program being debugged is left.

4E38H - B: Block Move

B source,destination,count: copies count bytes (default 0100H; 0000H moves 65536) from the source (default the display address 4063H) to the destination (default the M address 4060H) with LDIR, low addresses first; a destination above the source and inside the block repeats its first bytes. The M address is left just past the destination block. ENTER right after the source drops the command.

4E38
CP 42H FE 42
Compare Register A (the key) against 42H, the letter B.
4E3A
If the NZ FLAG is set (not B), JUMP to 4E84H.
4E3C
LD HL,(4063H) 2A 63 40
Fetch the display address from 4063H-4064H into Register Pair HL, the default source.
4E3F
GOSUB to SYS5/SYS's 51A3H to read a hex number into Register Pair HL: the NZ FLAG when digits were typed, the CARRY FLAG when ENTER ended it.
4E42
RET C D8
If the C FLAG is set (ENTER after the source), RETURN to the monitor: the command is dropped.
4E43
LD (4063H),HL 22 63 40
Store Register Pair HL (the source) to 4063H-4064H, the display address.
4E46
If the NZ FLAG is set (the source was typed), JUMP to 4E50H.
4E48
GOSUB to SYS5/SYS's 51D4H to show Register Pair HL (the default source) as four hex digits.
4E4B
LD A,2CH 3E 2C
Load Register A with 2CH, a comma, to follow the value shown.
4E4D
GOSUB to the ROM's 0033H to show the comma in Register A.
4E50
LD HL,(4060H) 2A 60 40
Fetch the M address from 4060H-4061H into Register Pair HL, the default destination.
4E53
GOSUB to SYS5/SYS's 51A3H to read the destination into Register Pair HL.
4E56
LD (4060H),HL 22 60 40
Store Register Pair HL (the destination) to 4060H-4061H, the M address.
4E59
If the NZ FLAG is set (the destination was typed), JUMP to 4E65H.
4E5B
PUSH AF F5
Save Register Pair AF (the CARRY FLAG of ENTER) to the stack.
4E5C
GOSUB to SYS5/SYS's 51D4H to show Register Pair HL (the default destination).
4E5F
LD A,2CH 3E 2C
Load Register A with 2CH, a comma, to follow the value shown.
4E61
GOSUB to the ROM's 0033H to show the comma in Register A.
4E64
POP AF F1
Restore Register Pair AF (the flags of 51A3H) from the stack.
4E65
LD HL,0100H 21 00 01
Load Register Pair HL with 0100H, the default count. LD does not change the flags.
4E68
If the C FLAG is set (ENTER after the destination), JUMP to 4E6FH with the default count.
4E6A
GOSUB to SYS5/SYS's 51A3H to read the count into Register Pair HL.
4E6D
If the NZ FLAG is set (the count was typed), JUMP to 4E74H.
4E6F
PUSH HL E5
Save Register Pair HL (the count) to the stack.
4E70
GOSUB to SYS5/SYS's 51D4H to show Register Pair HL (the default count).
4E73
POP HL E1
Restore Register Pair HL (the count) from the stack.
4E74
LD B,H 44
Copy Register H (high byte of the count) into Register B.
4E75
LD C,L 4D
Copy Register L (low byte of the count) into Register C: Register Pair BC = the count.
4E76
LD HL,(4063H) 2A 63 40
Fetch the source from 4063H-4064H into Register Pair HL.
4E79
LD DE,(4060H) ED 5B 60 40
Fetch the destination from 4060H-4061H into Register Pair DE.
4E7D
LDIR ED B0
Copy Register Pair BC bytes from Register Pair HL to Register Pair DE (LDIR), low addresses first.
4E7F
LD (4060H),DE ED 53 60 40
Store Register Pair DE (just past the destination block) to 4060H-4061H, the M address.
4E83
RET C9
RETURN to SYS5/SYS's command loop 4E4BH, which shows the display again.

4E84H - E: Enter Bytes

E address: shows each byte from the address (default the M address 4060H) followed by a minus sign; a hex number typed replaces it (its low byte), a space or comma with no digits keeps it; ENTER ends the command after its byte. The M address follows the byte being changed.

4E84
CP 45H FE 45
Compare Register A (the key) against 45H, the letter E.
4E86
If the NZ FLAG is set (not E), JUMP to 4EB7H.
4E88
LD HL,(4060H) 2A 60 40
Fetch the M address from 4060H-4061H into Register Pair HL, the default address.
4E8B
GOSUB to SYS5/SYS's 51A3H to read the address into Register Pair HL.
4E8E
LD (4060H),HL 22 60 40
Store Register Pair HL (the address) to 4060H-4061H, the M address.
4E91
RET C D8
If the C FLAG is set (ENTER after the address), RETURN to the monitor with the M address set.
4E92
If the NZ FLAG is set (the address was typed), JUMP to 4E9AH.
4E94
GOSUB to SYS5/SYS's 51D4H to show Register Pair HL (the default address).
4E97
GOSUB to SYS5/SYS's 51F2H to show a space after the address.
4E9A
LD A,1EH 3E 1E
Load Register A with 1EH, the code that clears the rest of the line.
4E9C
GOSUB to the ROM's 0033H to clear the rest of the line with Register A (1EH).
4E9F
GOSUB to SYS5/SYS's 51D0H to show the byte at Register Pair HL as two hex digits; Register Pair HL ends one higher.
4EA2
DEC HL 2B
Decrement Register Pair HL back to the byte shown.
4EA3
LD A,2DH 3E 2D
Load Register A with 2DH, a minus sign, after the byte shown.
4EA5
GOSUB to the ROM's 0033H to show the minus sign in Register A.
4EA8
EX DE,HL EB
Exchange Register Pairs DE and HL: Register Pair DE = the address of the byte.
4EA9
GOSUB to SYS5/SYS's 51A3H to read a hex number into Register Pair HL: the NZ FLAG when digits were typed.
4EAC
EX DE,HL EB
Exchange Register Pairs DE and HL: Register Pair HL = the address, Register E = the low byte of the number typed.
4EAD
If the Z FLAG is set (no digits), JUMP to 4EB0H and keep the byte.
4EAF
LD (HL),E 73
Store Register E (the new byte) at Register Pair HL.
4EB0
RET C D8
If the C FLAG is set (ENTER), RETURN to the monitor.
4EB1
INC HL 23
Increment Register Pair HL to the next byte of memory.
4EB2
LD (4060H),HL 22 60 40
Store Register Pair HL to 4060H-4061H, the M address.
4EB5
LOOP BACK to 4E9FH to show the next byte at Register Pair HL.

4EB7H - F: Fill

F start,end,byte: stores the byte at every address from the start to the end, the end included; a start equal to or above the end stores nothing, and an end of FFFFH never stops (4ED5H). Each field must be typed: a field with no digits drops the command.

4EB7
CP 46H FE 46
Compare Register A (the key) against 46H, the letter F.
4EB9
If the NZ FLAG is set (not F), JUMP to 4ED7H.
4EBB
GOSUB to SYS5/SYS's 51A3H to read the start into Register Pair HL.
4EBE
RET Z C8
If the Z FLAG is set (no digits), RETURN to the monitor.
4EBF
PUSH HL E5
Save Register Pair HL (the start) to the stack.
4EC0
GOSUB to SYS5/SYS's 51A3H to read the end into Register Pair HL.
4EC3
EX (SP),HL E3
Exchange Register Pair HL with the word at the Stack Pointer: Register Pair HL = the start, the stack holds the end.
4EC4
POP BC C1
Restore Register Pair BC from the stack: the end.
4EC5
RET Z C8
If the Z FLAG is set (no end typed), RETURN to the monitor.
4EC6
PUSH HL E5
Save Register Pair HL (the start) to the stack.
4EC7
GOSUB to SYS5/SYS's 51A3H to read the byte into Register Pair HL.
4ECA
LD E,L 5D
Copy Register L (the low byte of the number: the byte to store) into Register E.
4ECB
POP HL E1
Restore Register Pair HL from the stack: the start.
4ECC
RET Z C8
If the Z FLAG is set (no byte typed), RETURN to the monitor.
4ECD
XOR A AF
Set Register A to 00H and clear the CARRY FLAG (XOR A) for the first compare only.
4ECE
PUSH HL E5
Save Register Pair HL (the address) to the stack.
4ECF
SBC HL,BC ED 42
Subtract Register Pair BC (the end) and the CARRY FLAG from Register Pair HL: the first pass compares the start with the end; later passes come from 4ED5H with the CARRY FLAG set by the last compare, so they stop only past the end.
4ED1
POP HL E1
Restore Register Pair HL (the address) from the stack.
4ED2
RET NC D0
If the NC FLAG is set (the start reached the end on the first pass, or the address passed the end), RETURN to the monitor.
4ED3
LD (HL),E 73
Store Register E (the byte) at Register Pair HL.
4ED4
INC HL 23
Increment Register Pair HL to the next address. INC does not change the CARRY FLAG.
4ED5
LOOP BACK to 4ECEH, past the XOR A, so the CARRY FLAG of the compare stays in the next SBC. With an end of FFFFH the address wraps to 0000H, which is still below the end: the loop then fills all memory, this code and SYS5/SYS included.

4ED7H - J: Jump Over a Byte

Adds 1 to the saved program counter 407BH: the program will go on one byte further.

4ED7
CP 4AH FE 4A
Compare Register A (the key) against 4AH, the letter J.
4ED9
If the NZ FLAG is set (not J), JUMP to 4EE3H.
4EDB
LD HL,(407BH) 2A 7B 40
Fetch the program counter saved by SYS5/SYS from 407BH-407CH into Register Pair HL.
4EDE
INC HL 23
Increment Register Pair HL: one byte further.
4EDF
LD (407BH),HL 22 7B 40
Store Register Pair HL to 407BH-407CH, the program counter the program goes on at.
4EE2
RET C9
RETURN to SYS5/SYS's command loop 4E4BH, which shows the display again.

4EE3H - L: Locate a Byte

L address,byte: searches memory for the byte (default the last byte searched, at 4062H) from the address (default the M address plus 1, so that L alone finds the next one) through all 65536 addresses; since 4062H holds the byte, it is always found, at 4062H when nowhere else. The M address 4060H is then the byte and the display address 4063H the start of its 64 byte block, the four memory lines of SYS5/SYS's display. When an address is typed and the byte is not, the value shown as the byte is the low byte of the address, while the search uses 4062H.

4EE3
CP 4CH FE 4C
Compare Register A (the key) against 4CH, the letter L.
4EE5
If the NZ FLAG is set (not L), JUMP to 4F2AH.
4EE7
LD HL,(4060H) 2A 60 40
Fetch the M address from 4060H-4061H into Register Pair HL.
4EEA
INC HL 23
Increment Register Pair HL: the default start is the byte after the M address.
4EEB
GOSUB to SYS5/SYS's 51A3H to read the start into Register Pair HL.
4EEE
LD (4060H),HL 22 60 40
Store Register Pair HL (the start) to 4060H-4061H.
4EF1
If the NZ FLAG is set (the start was typed), JUMP to 4F01H with Register L its low byte.
4EF3
PUSH AF F5
Save Register Pair AF (the CARRY FLAG of ENTER) to the stack.
4EF4
GOSUB to SYS5/SYS's 51D4H to show Register Pair HL (the default start).
4EF7
LD A,2CH 3E 2C
Load Register A with 2CH, a comma, to follow the value shown.
4EF9
GOSUB to the ROM's 0033H to show the comma in Register A.
4EFC
POP AF F1
Restore Register Pair AF (the flags of 51A3H) from the stack.
4EFD
LD A,(4062H) 3A 62 40
Fetch the last byte searched from 4062H into Register A. LD does not change the flags.
4F00
LD L,A 6F
Copy Register A (the default byte) into Register L.
4F01
If the C FLAG is set (ENTER after the start), JUMP to 4F0EH to show Register L as the byte.
4F03
GOSUB to SYS5/SYS's 51A3H to read the byte into Register Pair HL.
4F06
If the Z FLAG is set (no byte typed), JUMP to 4F0EH to show Register L as the byte.
4F08
LD A,L 7D
Copy Register L (the byte typed) into Register A.
4F09
LD (4062H),A 32 62 40
Store Register A (the byte) to 4062H, the byte searched for.
4F0C
JUMP to 4F12H to search with the byte stored at 4062H.
4F0E
LD A,L 7D
Copy Register L into Register A: the default byte, or the low byte of the start when the start was typed.
4F0F
GOSUB to SYS5/SYS's 51D9H to show Register A as two hex digits.
4F12
LD HL,(4060H) 2A 60 40
Fetch the start from 4060H-4061H into Register Pair HL.
4F15
LD A,(4062H) 3A 62 40
Fetch the byte to search for from 4062H into Register A.
4F18
LD BC,0000H 01 00 00
Load Register Pair BC with 0000H: CPIR then compares up to 65536 bytes.
4F1B
CPIR ED B1
Compare Register A with the byte at Register Pair HL, increment Register Pair HL and decrement Register Pair BC until a byte is equal or Register Pair BC is 0000H (CPIR).
4F1D
RET NZ C0
If the NZ FLAG is set, RETURN to the monitor. CPIR looks at all 65536 addresses and 4062H itself holds the byte, so the search always finds it: at worst at 4062H.
4F1E
DEC HL 2B
Decrement Register Pair HL back to the byte found.
4F1F
LD (4060H),HL 22 60 40
Store Register Pair HL (the byte found) to 4060H-4061H, the M address.
4F22
LD A,L 7D
Copy Register L (low byte of the address found) into Register A.
4F23
AND C0H E6 C0
Mask Register A with C0H: the start of the 64 byte block that holds the byte.
4F25
LD L,A 6F
Copy Register A (the masked low byte) into Register L.
4F26
LD (4063H),HL 22 63 40
Store Register Pair HL (the start of that block) to 4063H-4064H, the display address.
4F29
RET C9
RETURN to SYS5/SYS's command loop 4E4BH, which shows the display again.

4F2AH - N: Next Block

N address: takes the byte after the address (default the M address 4060H) as a length and moves the M address past it: the new M address is the address plus the length plus 2, with a length 00H taken as 256. On a record of a load module (type, length) this is the next record. The length is not taken as signed, so on a JR with a jump back it moves forward. The display address goes to the start of the 64 byte block of the new M address.

4F2A
CP 4EH FE 4E
Compare Register A (the key) against 4EH, the letter N.
4F2C
If the NZ FLAG is set (not N), JUMP to 4F4AH.
4F2E
LD HL,(4060H) 2A 60 40
Fetch the M address from 4060H-4061H into Register Pair HL.
4F31
GOSUB to SYS5/SYS's 51A3H to read an address into Register Pair HL (kept when none is typed).
4F34
INC HL 23
Increment Register Pair HL to the length byte.
4F35
LD D,00H 16 00
Load Register D with 00H, the high byte of the length.
4F37
LD E,(HL) 5E
Fetch the length byte from Register Pair HL into Register E: Register Pair DE = the length.
4F38
LD A,E 7B
Copy Register E (the length) into Register A.
4F39
OR A B7
OR Register A with itself: the Z FLAG is set for a length 00H.
4F3A
If the NZ FLAG is set (not 00H), JUMP to 4F3DH.
4F3C
INC D 14
Increment Register D: a length 00H is 0100H, 256.
4F3D
INC DE 13
Increment Register Pair DE: the length plus one, for the length byte itself.
4F3E
ADD HL,DE 19
Add Register Pair DE to Register Pair HL: the byte after the block.
4F3F
LD (4060H),HL 22 60 40
Store Register Pair HL to 4060H-4061H, the M address.
4F42
LD A,L 7D
Copy Register L (low byte of the new M address) into Register A.
4F43
AND C0H E6 C0
Mask Register A with C0H: the start of the 64 byte block that holds the new M address.
4F45
LD L,A 6F
Copy Register A (the masked low byte) into Register L.
4F46
LD (4063H),HL 22 63 40
Store Register Pair HL (the start of that block) to 4063H-4064H, the display address.
4F49
RET C9
RETURN to SYS5/SYS's command loop 4E4BH, which shows the display again.

4F4AH - Q: Query or Set a Port

Q port ENTER: reads the port with IN and shows = and the value, then waits for a key. Q port,value: writes the low byte of the value to the port with OUT. A field with no digits drops the command.

4F4A
CP 51H FE 51
Compare Register A (the key) against 51H, the letter Q.
4F4C
If the NZ FLAG is set (not Q), JUMP to 4F6EH.
4F4E
LD A,1EH 3E 1E
Load Register A with 1EH, the code that clears the rest of the line.
4F50
GOSUB to the ROM's 0033H to clear the rest of the line with Register A (1EH).
4F53
GOSUB to SYS5/SYS's 51A3H to read the port into Register Pair HL.
4F56
RET Z C8
If the Z FLAG is set (no port typed), RETURN to the monitor.
4F57
LD C,L 4D
Copy Register L (the port) into Register C. LD does not change the flags.
4F58
If the C FLAG is set (ENTER after the port), JUMP to 4F61H to read it.
4F5A
GOSUB to SYS5/SYS's 51A3H to read the value into Register Pair HL.
4F5D
RET Z C8
If the Z FLAG is set (no value typed), RETURN to the monitor.
4F5E
OUT (C),L ED 69
Output Register L (the value) to the port in Register C (Register B, whatever the code before left in it, on the upper address lines).
4F60
RET C9
RETURN to SYS5/SYS's command loop 4E4BH, which shows the display again.
4F61
LD A,3DH 3E 3D
Load Register A with 3DH, an equals sign, before the value read.
4F63
GOSUB to the ROM's 0033H to show the equals sign in Register A.
4F66
IN A,(C) ED 78
Input from the port in Register C into Register A.
4F68
GOSUB to SYS5/SYS's 51D9H to show Register A (the value read) as two hex digits.
4F6B
JUMP to SYS5/SYS's 518AH to wait for a key, so the value stays on the screen; its RET goes back to the monitor.

4F6EH - T: Type Text Into Memory

T address: shows each byte from the address (default the M address 4060H) as a character (bit 7 cleared, then a period for codes below 20H) after a space, then a minus sign, and waits for a key: a space keeps the byte, ENTER ends the command, any other key (a comma too) is stored as it is. The M address follows the byte.

4F6E
CP 54H FE 54
Compare Register A (the key) against 54H, the letter T.
4F70
If the NZ FLAG is set (not T), JUMP to 4FADH.
4F72
LD HL,(4060H) 2A 60 40
Fetch the M address from 4060H-4061H into Register Pair HL, the default address.
4F75
GOSUB to SYS5/SYS's 51A3H to read the address into Register Pair HL.
4F78
LD (4060H),HL 22 60 40
Store Register Pair HL (the address) to 4060H-4061H, the M address.
4F7B
RET C D8
If the C FLAG is set (ENTER after the address), RETURN to the monitor with the M address set.
4F7C
If the NZ FLAG is set (the address was typed), JUMP to 4F81H.
4F7E
GOSUB to SYS5/SYS's 51D4H to show Register Pair HL (the default address).
4F81
LD A,1EH 3E 1E
Load Register A with 1EH, the code that clears the rest of the line.
4F83
GOSUB to the ROM's 0033H to clear the rest of the line with Register A (1EH).
4F86
GOSUB to SYS5/SYS's 51F2H to show a space before the character.
4F89
LD A,(HL) 7E
Fetch the byte at Register Pair HL into Register A.
4F8A
AND 7FH E6 7F
Mask Register A to bits 6-0: a code of 80H up is shown as the code less 80H.
4F8C
CP 20H FE 20
Compare Register A (the character) against 20H, a space.
4F8E
If the C FLAG is set (a control code), JUMP to 4F94H to show a period.
4F90
CP C0H FE C0
Compare Register A against C0H. After the mask above Register A is below 80H, so the C FLAG is always set here.
4F92
If the C FLAG is set (always), JUMP to 4F96H to show the character.
4F94
LD A,2EH 3E 2E
Load Register A with 2EH, a period, for a control code.
4F96
GOSUB to the ROM's 0033H to show the character in Register A.
4F99
LD A,2DH 3E 2D
Load Register A with 2DH, a minus sign, after the character.
4F9B
GOSUB to the ROM's 0033H to show the minus sign in Register A.
4F9E
GOSUB to SYS5/SYS's 518AH to wait for a key and show it: the CARRY FLAG for ENTER.
4FA1
RET C D8
If the C FLAG is set (ENTER), RETURN to the monitor.
4FA2
CP 20H FE 20
Compare Register A (the key) against 20H, a space.
4FA4
If the Z FLAG is set (a space), JUMP to 4FA7H and keep the byte.
4FA6
LD (HL),A 77
Store Register A (the key) at Register Pair HL.
4FA7
INC HL 23
Increment Register Pair HL to the next byte of memory.
4FA8
LD (4060H),HL 22 60 40
Store Register Pair HL to 4060H-4061H, the M address.
4FAB
LOOP BACK to 4F86H for the next byte at Register Pair HL.

4FADH - V: Verify Two Blocks

V first,second,count: compares count bytes (default 0000H, 65536) at the first address (default the display address 4063H) with those at the second (default the M address 4060H), stopping at the first difference. 4063H and 4060H are left at the two bytes that differ, or just past the blocks when they are equal.

4FAD
CP 56H FE 56
Compare Register A (the key) against 56H, the letter V.
4FAF
If the NZ FLAG is set (not V), JUMP to 5008H.
4FB1
LD HL,(4063H) 2A 63 40
Fetch the display address from 4063H-4064H into Register Pair HL, the default first block.
4FB4
GOSUB to SYS5/SYS's 51A3H to read the first address into Register Pair HL.
4FB7
LD (4063H),HL 22 63 40
Store Register Pair HL (the first block) to 4063H-4064H.
4FBA
If the NZ FLAG is set (the address was typed), JUMP to 4FC6H.
4FBC
PUSH AF F5
Save Register Pair AF (the CARRY FLAG of ENTER) to the stack.
4FBD
GOSUB to SYS5/SYS's 51D4H to show Register Pair HL (the default first block).
4FC0
LD A,2CH 3E 2C
Load Register A with 2CH, a comma, to follow the value shown.
4FC2
GOSUB to the ROM's 0033H to show the comma in Register A.
4FC5
POP AF F1
Restore Register Pair AF (the flags of 51A3H) from the stack.
4FC6
If the C FLAG is set (ENTER after the first address), JUMP to 4FDDH with the defaults.
4FC8
LD HL,(4060H) 2A 60 40
Fetch the M address from 4060H-4061H into Register Pair HL, the default second block.
4FCB
GOSUB to SYS5/SYS's 51A3H to read the second address into Register Pair HL.
4FCE
LD (4060H),HL 22 60 40
Store Register Pair HL (the second block) to 4060H-4061H.
4FD1
If the NZ FLAG is set (the address was typed), JUMP to 4FDDH.
4FD3
PUSH AF F5
Save Register Pair AF (the CARRY FLAG of ENTER) to the stack.
4FD4
GOSUB to SYS5/SYS's 51D4H to show Register Pair HL (the default second block).
4FD7
LD A,2CH 3E 2C
Load Register A with 2CH, a comma, to follow the value shown.
4FD9
GOSUB to the ROM's 0033H to show the comma in Register A.
4FDC
POP AF F1
Restore Register Pair AF (the flags of 51A3H) from the stack.
4FDD
LD HL,0000H 21 00 00
Load Register Pair HL with 0000H, the default count (65536). LD does not change the flags.
4FE0
If the C FLAG is set (ENTER), JUMP to 4FECH with the default count.
4FE2
GOSUB to SYS5/SYS's 51A3H to read the count into Register Pair HL.
4FE5
If the NZ FLAG is set (the count was typed), JUMP to 4FECH.
4FE7
PUSH HL E5
Save Register Pair HL (the count) to the stack.
4FE8
GOSUB to SYS5/SYS's 51D4H to show Register Pair HL (the default count).
4FEB
POP HL E1
Restore Register Pair HL (the count) from the stack.
4FEC
LD B,H 44
Copy Register H (high byte of the count) into Register B.
4FED
LD C,L 4D
Copy Register L (low byte of the count) into Register C: Register Pair BC = the count.
4FEE
LD HL,(4063H) 2A 63 40
Fetch the first block from 4063H-4064H into Register Pair HL.
4FF1
LD DE,(4060H) ED 5B 60 40
Fetch the second block from 4060H-4061H into Register Pair DE.
4FF5
LD A,(DE) 1A
Fetch the byte of the second block at Register Pair DE into Register A.
4FF6
CP (HL) BE
Compare Register A against the byte of the first block at Register Pair HL.
4FF7
If the NZ FLAG is set (they differ), JUMP to 5000H with both addresses on the bytes that differ.
4FF9
INC DE 13
Increment Register Pair DE in the second block.
4FFA
INC HL 23
Increment Register Pair HL in the first block.
4FFB
DEC BC 0B
Decrement Register Pair BC, the bytes left to compare.
4FFC
LD A,B 78
Copy Register B (high byte of the bytes left) into Register A.
4FFD
OR C B1
OR Register C (the low byte) into Register A: the Z FLAG is set when no byte is left.
4FFE
If the NZ FLAG is set (bytes left), LOOP BACK to 4FF5H.
5000
LD (4060H),DE ED 53 60 40
Store Register Pair DE (in the second block) to 4060H-4061H, the M address.
5004
LD (4063H),HL 22 63 40
Store Register Pair HL (in the first block) to 4063H-4064H, the display address.
5007
RET C9
RETURN to SYS5/SYS's command loop 4E4BH, which shows the display again.

5008H - W: Search for a Word

W address,word: searches memory from the address (default the M address plus 2) for the word, low byte first (default the last word searched, kept at 4062H low and 405FH high); after a low byte whose high byte differs, CPIR goes on with the count it has left, so the search can run past 65536 bytes. Found: the M address 4060H is the byte before the word (the opcode when the word is the operand of a CALL, JP or LD) and the display address 4063H the start of its 64 byte block; the default start of the next W, the M address plus 2, is the byte after the word's low byte. When an address is typed and the word is not, the value shown as the word is the address, while the search uses 4062H and 405FH.

5008
CP 57H FE 57
Compare Register A (the key) against 57H, the letter W.
500A
If the NZ FLAG is set (not W), JUMP to 505EH.
500C
LD HL,(4060H) 2A 60 40
Fetch the M address from 4060H-4061H into Register Pair HL.
500F
INC HL 23
Increment Register Pair HL past the M address.
5010
INC HL 23
Increment Register Pair HL again: the default start is two bytes after the M address.
5011
GOSUB to SYS5/SYS's 51A3H to read the start into Register Pair HL.
5014
LD (4060H),HL 22 60 40
Store Register Pair HL (the start) to 4060H-4061H.
5017
If the NZ FLAG is set (the start was typed), JUMP to 502BH with Register Pair HL the start.
5019
PUSH AF F5
Save Register Pair AF (the CARRY FLAG of ENTER) to the stack.
501A
GOSUB to SYS5/SYS's 51D4H to show Register Pair HL (the default start).
501D
LD A,2CH 3E 2C
Load Register A with 2CH, a comma, to follow the value shown.
501F
GOSUB to the ROM's 0033H to show the comma in Register A.
5022
POP AF F1
Restore Register Pair AF (the flags of 51A3H) from the stack.
5023
LD A,(4062H) 3A 62 40
Fetch the low byte of the last word from 4062H into Register A. LD does not change the flags.
5026
LD L,A 6F
Copy Register A (the low byte of the last word) into Register L.
5027
LD A,(405FH) 3A 5F 40
Fetch the high byte of the last word from 405FH into Register A.
502A
LD H,A 67
Copy Register A into Register H: Register Pair HL = the default word.
502B
If the C FLAG is set (ENTER after the start), JUMP to 503CH to show Register Pair HL as the word.
502D
GOSUB to SYS5/SYS's 51A3H to read the word into Register Pair HL.
5030
If the Z FLAG is set (no word typed), JUMP to 503CH to show Register Pair HL as the word.
5032
LD A,L 7D
Copy Register L (the low byte of the word) into Register A.
5033
LD (4062H),A 32 62 40
Store Register A to 4062H, the low byte searched for.
5036
LD A,H 7C
Copy Register H (the high byte of the word) into Register A.
5037
LD (405FH),A 32 5F 40
Store Register A to 405FH, the high byte searched for.
503A
JUMP to 503FH to search with the word stored at 4062H and 405FH.
503C
GOSUB to SYS5/SYS's 51D4H to show Register Pair HL as the word: the default word, or the start when the start was typed.
503F
LD HL,(4060H) 2A 60 40
Fetch the start from 4060H-4061H into Register Pair HL.
5042
LD BC,0000H 01 00 00
Load Register Pair BC with 0000H: the search runs over 65536 bytes at most.
5045
LD A,(4062H) 3A 62 40
Fetch the low byte searched for from 4062H into Register A.
5048
CPIR ED B1
Compare Register A with the byte at Register Pair HL, increment Register Pair HL and decrement Register Pair BC until a byte is equal or Register Pair BC is 0000H (CPIR).
504A
RET NZ C0
If the NZ FLAG is set (not found), RETURN to the monitor.
504B
LD A,(405FH) 3A 5F 40
Fetch the high byte searched for from 405FH into Register A.
504E
CP (HL) BE
Compare Register A against the byte at Register Pair HL, the one after the low byte found.
504F
If the NZ FLAG is set (the high byte differs), LOOP BACK to 5045H to go on with the search; Register Pair BC goes on counting.
5051
DEC HL 2B
Decrement Register Pair HL back to the low byte found.
5052
DEC HL 2B
Decrement Register Pair HL again: one below the low byte, the byte before the word, which the M address names.
5053
LD (4060H),HL 22 60 40
Store Register Pair HL to 4060H-4061H, the M address.
5056
LD A,L 7D
Copy Register L (low byte of the new M address) into Register A.
5057
AND C0H E6 C0
Mask Register A with C0H: the start of the 64 byte block.
5059
LD L,A 6F
Copy Register A (the masked low byte) into Register L.
505A
LD (4063H),HL 22 63 40
Store Register Pair HL (the start of that block) to 4063H-4064H, the display address.
505D
RET C9
RETURN to SYS5/SYS's command loop 4E4BH, which shows the display again.

505EH - 0-7: Sectors to or From a Disk

d,cylinder,sector,o,address,count: d is the drive 0-7 (the key itself), o the operation: R reads, W writes with the ordinary data mark, an asterisk writes with the directory's data mark FAH; any other key (a space or a comma too) only counts the sectors. The cylinder defaults to the directory cylinder (drive code table +09H). With a sector, count sectors (default 1) are moved from that sector on; with no sector, a whole cylinder from sector 0 (the sectors of a cylinder, doubled for a drive with two sides). Each sector takes the next 256 bytes of memory from the address; after the last sector of a cylinder the next cylinder follows. A failed sector shows its error code between two asterisks and waits for a key, then the next sector is done. After R the display address and the M address are set to the start of the 256 byte page of the address and the full screen display is chosen. The count is kept in 4062H and the sectors of a cylinder in 405FH, SYS5/SYS's cells. ENTER after the drive, the cylinder or the sector drops the command; a key that is not a hex digit in a number field ends it in SYS5/SYS.

505E
CP 30H FE 30
Compare Register A (the key) against 30H, the digit 0.
5060
If the C FLAG is set (below 0), JUMP to 50CBH and on to 5132H.
5062
CP 38H FE 38
Compare Register A (the key) against 38H, the digit 8.
5064
If the NC FLAG is set (8 or above), JUMP to 50CBH and on to 5132H.
5066
SUB 30H D6 30
SUBtract 30H from Register A (the key): the drive 0-7.
5068
LD C,A 4F
Copy Register A (the drive 0-7) into Register C for 478FH and the driver.
5069
GOSUB to 478FH to point Index Register IY at the drive code table of drive Register C.
506C
LD A,(IY+07H) FD 7E 07
Fetch byte +07H of the drive code table at Index Register IY into Register A.
506F
AND E0H E6 E0
Mask Register A to bits 7-5: the count less one that multiplies the sectors of a track.
5071
RLCA 07
Rotate Register A left, the first of three, moving bits 7-5 round.
5072
RLCA 07
Rotate Register A left, the second of three, moving bits 7-5 round.
5073
RLCA 07
Rotate Register A left: bits 7-5 are now bits 2-0.
5074
INC A 3C
Increment Register A: the multiplier of the sectors of a track.
5075
LD B,A 47
Copy Register A (the multiplier) into Register B, the count of the loop below.
5076
LD A,(IY+07H) FD 7E 07
Fetch byte +07H of the drive code table at Index Register IY into Register A again.
5079
AND 1FH E6 1F
Mask Register A to bits 4-0: the highest sector number of a track.
507B
INC A 3C
Increment Register A: the sectors of a track.
507C
LD H,A 67
Copy Register A (the sectors of a track) into Register H.
507D
XOR A AF
Set Register A to 00H (XOR A), the start of the sum of the loop below.
507E
ADD A,H 84
Add Register H (the sectors of a track) to Register A.
507F
Decrement Register B and LOOP BACK to 507EH: Register A = the sectors of a track times the multiplier.
5081
BIT 5,(IY+04H) FD CB 04 6E
Test bit 5 of byte +04H of the drive code table at Index Register IY: set for a drive with two sides.
5085
If the Z FLAG is set (one side), JUMP to 5088H.
5087
RLCA 07
Rotate Register A left: the sectors of a cylinder doubled for two sides.
5088
LD (405FH),A 32 5F 40
Store Register A (the sectors of a cylinder) to 405FH, the saved byte of SYS5/SYS's second breakpoint slot.
508B
LD A,1EH 3E 1E
Load Register A with 1EH, the code that clears the rest of the line.
508D
GOSUB to the ROM's 0033H to clear the rest of the line with Register A (1EH).
5090
GOSUB to SYS5/SYS's 518AH to wait for any key (the comma after the drive; a digit typed there is lost); the CARRY FLAG for ENTER.
5093
RET C D8
If the C FLAG is set (ENTER), RETURN to the monitor.
5094
GOSUB to SYS5/SYS's 51A3H to read the cylinder into Register Pair HL: the NZ FLAG when digits were typed, the CARRY FLAG for ENTER.
5097
RET C D8
If the C FLAG is set (ENTER after the cylinder), RETURN to the monitor.
5098
LD D,L 55
Copy Register L (the cylinder typed) into Register D. LD does not change the flags.
5099
If the NZ FLAG is set (a cylinder was typed), JUMP to 509EH.
509B
LD D,(IY+09H) FD 56 09
Fetch the directory cylinder from byte +09H of the drive code table at Index Register IY into Register D.
509E
GOSUB to SYS5/SYS's 51A3H to read the sector into Register Pair HL.
50A1
LD E,L 5D
Copy Register L (the sector typed) into Register E.
50A2
LD A,01H 3E 01
Load Register A with 01H, the count of one sector. LD does not change the flags.
50A4
If the NZ FLAG is set (a sector was typed), JUMP to 50ABH.
50A6
LD E,00H 1E 00
Load Register E with 00H: no sector, the cylinder from sector 0.
50A8
LD A,(405FH) 3A 5F 40
Fetch the sectors of a cylinder from 405FH into Register A: the count for a whole cylinder.
50AB
LD (4062H),A 32 62 40
Store Register A (the count of sectors) to 4062H, the saved byte of SYS5/SYS's first breakpoint slot.
50AE
RET C D8
If the C FLAG is set (ENTER after the sector), RETURN to the monitor.
50AF
GOSUB to SYS5/SYS's 518AH to wait for the operation key and show it.
50B2
RET C D8
If the C FLAG is set (ENTER), RETURN to the monitor.
50B3
LD B,A 47
Copy Register A (the operation: R, W or an asterisk) into Register B.
50B4
GOSUB to SYS5/SYS's 518AH to wait for any key (the comma after the operation; a digit typed there is lost).
50B7
RET C D8
If the C FLAG is set (ENTER), RETURN to the monitor.
50B8
GOSUB to SYS5/SYS's 51A3H to read the address into Register Pair HL; with no digits Register Pair HL keeps what it held: the last number read, or with nothing typed at all the value left by the code before, with Register H the sectors of a track from 507CH.
50BB
PUSH HL E5
Save Register Pair HL (the address) to the stack, for 50EFH.
50BC
If the C FLAG is set (ENTER after the address), JUMP to 50CDH with the count in 4062H.
50BE
PUSH HL E5
Save Register Pair HL (the address) to the stack.
50BF
GOSUB to SYS5/SYS's 51A3H to read the count into Register Pair HL.
50C2
LD A,L 7D
Copy Register L (the count typed) into Register A.
50C3
POP HL E1
Restore Register Pair HL (the address) from the stack.
50C4
If the Z FLAG is set (no count typed), JUMP to 50CDH with the count in 4062H.
50C6
LD (4062H),A 32 62 40
Store Register A (the count) to 4062H; 00H counts 256 sectors.
50C9
JUMP to 50CDH to start with the count in 4062H.
50CB
JUMP to 5132H: the key in Register A is not a drive digit.
50CD
LD A,B 78
Copy Register B (the operation) into Register A.
50CE
CP 52H FE 52
Compare Register A against 52H, the letter R.
50D0
If the Z FLAG is set (R), JUMP to 5102H to read the sector.
50D2
CP 57H FE 57
Compare Register A against 57H, the letter W.
50D4
If the Z FLAG is set (W), JUMP to 510DH to write the sector.
50D6
CP 2AH FE 2A
Compare Register A (the operation) against 2AH, an asterisk.
50D8
If the Z FLAG is set (the asterisk), JUMP to 5114H to write the sector with the directory's data mark. Any other operation moves no sector.
50DA
INC H 24
Increment Register H: the next 256 bytes of memory.
50DB
INC E 1C
Increment Register E: the next sector of the cylinder.
50DC
LD A,(405FH) 3A 5F 40
Fetch the sectors of a cylinder from 405FH into Register A.
50DF
DEC A 3D
Decrement Register A: the last sector number of a cylinder.
50E0
CP E BB
Compare Register A against Register E (the next sector): the C FLAG is set when Register E is past the last.
50E1
If the NC FLAG is set (the sector is on this cylinder), JUMP to 50E6H.
50E3
LD E,00H 1E 00
Load Register E with 00H, the first sector of the next cylinder.
50E5
INC D 14
Increment Register D: the next cylinder, Register E its sector 0.
50E6
LD A,(4062H) 3A 62 40
Fetch the count of sectors left from 4062H into Register A.
50E9
DEC A 3D
Decrement Register A, the count of sectors left.
50EA
LD (4062H),A 32 62 40
Store Register A (the sectors left) to 4062H.
50ED
If the NZ FLAG is set (sectors left), LOOP BACK to 50CDH.
50EF
POP HL E1
Restore Register Pair HL from the stack: the address of the first sector.
50F0
LD A,B 78
Copy Register B (the operation) into Register A.
50F1
CP 52H FE 52
Compare Register A against 52H, the letter R.
50F3
RET NZ C0
If the NZ FLAG is set (not a read), RETURN to the monitor.
50F4
LD L,00H 2E 00
Load Register L with 00H: the start of the page of the address.
50F6
LD (4063H),HL 22 63 40
Store Register Pair HL to 4063H-4064H, the display address.
50F9
LD (4060H),HL 22 60 40
Store Register Pair HL to 4060H-4061H, the M address.
50FC
LD A,53H 3E 53
Load Register A with 53H, the letter S, the full screen mode of SYS5/SYS.
50FE
LD (405EH),A 32 5E 40
Store Register A (53H) to 405EH, SYS5/SYS's screen mode: the full screen display of the sectors read.
5101
RET C9
RETURN to SYS5/SYS's command loop 4E4BH, which shows the display again.
5102
GOSUB to 4777H to read cylinder Register D, sector Register E of drive Register C into the memory at Register Pair HL (driver function 09H); Register Pair BC is kept.
5105
If the Z FLAG is set (read), JUMP to 50DAH for the next sector.
5107
CP 06H FE 06
Compare Register A (the error code) against 06H: the driver gives 06H for status bit 5, the data mark FAH of the directory or F8H.
5109
If the Z FLAG is set (a directory sector, read), JUMP to 50DAH for the next sector.
510B
JUMP to 5119H to show the error code in Register A.
510D
GOSUB to 4763H to write cylinder Register D, sector Register E of drive Register C from the memory at Register Pair HL with the ordinary data mark (driver function 0DH).
5110
If the Z FLAG is set (written), JUMP to 50DAH for the next sector.
5112
JUMP to 5119H to show the error code in Register A.
5114
GOSUB to 4768H to write cylinder Register D, sector Register E of drive Register C from the memory at Register Pair HL with the data mark FAH (driver function 0EH).
5117
If the Z FLAG is set (written), JUMP to 50DAH for the next sector.
5119
PUSH DE D5
Save Register Pair DE (the cylinder and sector) to the stack.
511A
PUSH AF F5
Save Register Pair AF (the error code) to the stack.
511B
GOSUB to SYS5/SYS's 51F2H to show a space before the error code.
511E
LD A,2AH 3E 2A
Load Register A with 2AH, an asterisk, before the error code.
5120
GOSUB to the ROM's 0033H to show the asterisk in Register A.
5123
POP AF F1
Restore Register Pair AF (the error code) from the stack.
5124
GOSUB to SYS5/SYS's 51D9H to show Register A (the error code) as two hex digits.
5127
LD A,2AH 3E 2A
Load Register A with 2AH, an asterisk, after the error code.
5129
GOSUB to the ROM's 0033H to show the asterisk in Register A.
512C
GOSUB to SYS5/SYS's 518AH to wait for a key; whatever the key, the command goes on.
512F
POP DE D1
Restore Register Pair DE (the cylinder and sector) from the stack.
5130
JUMP to 50DAH for the next sector: the failed one is passed over.

5132H - P: Print Memory

P start,end: prints on the printer (ROM 003BH) lines of 16 bytes from the start rounded down to a multiple of 16: four hex digits of the address, two spaces, the 16 bytes in hex with a space after each and one more after the 4th, 8th and 12th, then one more space (two before the characters) and the 16 bytes as characters (a period for codes below 20H and from 80H up). Lines go on while the next line's address is below the end, so an end that is the first byte of a line is not printed. Two carriage returns come first and three after. An end of FFF1H-FFFFH never stops the listing (51E7H). Both fields must be typed. A key that is no command at all goes on at 5134H to the routine 4310H held before SYS9/SYS was put in, normally SYS0/SYS's 4C2FH, which returns to the monitor.

5132
CP 50H FE 50
Compare Register A (the key) against 50H, the letter P.
5134
JP NZ,0000H C2 00 00
Self-Modifying Code
If the NZ FLAG is set (no command of SYS9/SYS), JUMP to the address that 4310H held before (the operand 5135H-5136H, 0000H in the file, stored at 4E0AH).
5137
GOSUB to SYS5/SYS's 51A3H to read the start into Register Pair HL.
513A
RET Z C8
If the Z FLAG is set (no start typed), RETURN to the monitor.
513B
PUSH HL E5
Save Register Pair HL (the start) to the stack.
513C
GOSUB to SYS5/SYS's 51A3H to read the end into Register Pair HL.
513F
EX (SP),HL E3
Exchange Register Pair HL with the word at the Stack Pointer: Register Pair HL = the start, the stack holds the end.
5140
POP BC C1
Restore Register Pair BC from the stack: the end.
5141
RET Z C8
If the Z FLAG is set (no end typed), RETURN to the monitor.
5142
LD A,L 7D
Copy Register L (low byte of the start) into Register A.
5143
AND F0H E6 F0
Mask Register A with F0H: the start rounded down to a multiple of 16.
5145
LD L,A 6F
Copy Register A (the masked low byte) into Register L: the line start.
5146
LD A,0DH 3E 0D
Load Register A with 0DH, a carriage return, for the printer.
5148
GOSUB to the ROM's 003BH to print Register A (0DH).
514B
GOSUB to the ROM's 003BH to print Register A (0DH) a second time.
514E
PUSH HL E5
Save Register Pair HL (the address of the line) to the stack, for its characters at 51C8H.
514F
LD A,H 7C
Copy Register H (high byte of the address) into Register A.
5150
RRA 1F
Rotate Register A right through the carry, the first of four.
5151
RRA 1F
Rotate Register A right through the carry, the second of four.
5152
RRA 1F
Rotate Register A right through the carry, the third of four.
5153
RRA 1F
Rotate Register A right through the carry: bits 7-4 are now bits 3-0.
5154
AND 0FH E6 0F
Mask Register A to bits 3-0: the first hex digit of the address.
5156
ADD A,90H C6 90
Add 90H to Register A: 90H-99H for 0-9, 9AH-9FH for A-F.
5158
DAA 27
Decimal Adjust Register A: 0-9 become 90H-99H with no carry, A-F become 00H-05H with the CARRY FLAG.
5159
ADC A,40H CE 40
Add 40H and the CARRY FLAG to Register A: D0H-D9H, or 41H-46H.
515B
DAA 27
Decimal Adjust Register A: 30H-39H for 0-9, 41H-46H for A-F, the hex digit as a character.
515C
GOSUB to the ROM's 003BH to print Register A (the digit).
515F
LD A,H 7C
Copy Register H (high byte of the address) into Register A.
5160
AND 0FH E6 0F
Mask Register A to bits 3-0: the second hex digit.
5162
ADD A,90H C6 90
Add 90H to Register A, the first step of the digit conversion.
5164
DAA 27
Decimal Adjust Register A, the second step of the digit conversion.
5165
ADC A,40H CE 40
Add 40H and the CARRY FLAG to Register A, the third step.
5167
DAA 27
Decimal Adjust Register A: the hex digit as a character.
5168
GOSUB to the ROM's 003BH to print Register A (the digit).
516B
LD A,L 7D
Copy Register L (low byte of the address) into Register A.
516C
RRA 1F
Rotate Register A right through the carry, the first of four.
516D
RRA 1F
Rotate Register A right through the carry, the second of four.
516E
RRA 1F
Rotate Register A right through the carry, the third of four.
516F
RRA 1F
Rotate Register A right through the carry: bits 7-4 are now bits 3-0.
5170
AND 0FH E6 0F
Mask Register A to bits 3-0: the third hex digit.
5172
ADD A,90H C6 90
Add 90H to Register A, the first step of the digit conversion.
5174
DAA 27
Decimal Adjust Register A, the second step of the digit conversion.
5175
ADC A,40H CE 40
Add 40H and the CARRY FLAG to Register A, the third step.
5177
DAA 27
Decimal Adjust Register A: the hex digit as a character.
5178
GOSUB to the ROM's 003BH to print Register A (the digit).
517B
LD A,L 7D
Copy Register L (low byte of the address) into Register A.
517C
AND 0FH E6 0F
Mask Register A to bits 3-0: the fourth hex digit.
517E
ADD A,90H C6 90
Add 90H to Register A, the first step of the digit conversion.
5180
DAA 27
Decimal Adjust Register A, the second step of the digit conversion.
5181
ADC A,40H CE 40
Add 40H and the CARRY FLAG to Register A, the third step.
5183
DAA 27
Decimal Adjust Register A: the hex digit as a character.
5184
GOSUB to the ROM's 003BH to print Register A (the digit).
5187
LD A,20H 3E 20
Load Register A with 20H, a space, after the address.
5189
GOSUB to the ROM's 003BH to print Register A (a space).
518C
GOSUB to the ROM's 003BH to print Register A (a second space).
518F
JUMP to 5193H to print the bytes of the line.
5191
JUMP to 514EH for the next line (from 51E7H).
5193
LD A,(HL) 7E
Fetch the byte at Register Pair HL into Register A.
5194
RRA 1F
Rotate Register A right through the carry, the first of four.
5195
RRA 1F
Rotate Register A right through the carry, the second of four.
5196
RRA 1F
Rotate Register A right through the carry, the third of four.
5197
RRA 1F
Rotate Register A right through the carry: bits 7-4 are now bits 3-0.
5198
AND 0FH E6 0F
Mask Register A to bits 3-0: the first hex digit of the byte.
519A
ADD A,90H C6 90
Add 90H to Register A, the first step of the digit conversion.
519C
DAA 27
Decimal Adjust Register A, the second step of the digit conversion.
519D
ADC A,40H CE 40
Add 40H and the CARRY FLAG to Register A, the third step.
519F
DAA 27
Decimal Adjust Register A: the hex digit as a character.
51A0
GOSUB to the ROM's 003BH to print Register A (the digit).
51A3
LD A,(HL) 7E
Fetch the byte at Register Pair HL into Register A again.
51A4
AND 0FH E6 0F
Mask Register A to bits 3-0: the second hex digit of the byte.
51A6
ADD A,90H C6 90
Add 90H to Register A, the first step of the digit conversion.
51A8
DAA 27
Decimal Adjust Register A, the second step of the digit conversion.
51A9
ADC A,40H CE 40
Add 40H and the CARRY FLAG to Register A, the third step.
51AB
DAA 27
Decimal Adjust Register A: the hex digit as a character.
51AC
GOSUB to the ROM's 003BH to print Register A (the digit).
51AF
LD A,20H 3E 20
Load Register A with 20H, a space, after the two digits.
51B1
GOSUB to the ROM's 003BH to print Register A (the space after the byte).
51B4
INC HL 23
Increment Register Pair HL to the next byte of the line.
51B5
LD A,L 7D
Copy Register L (low byte of the address) into Register A.
51B6
AND 0FH E6 0F
Mask Register A to bits 3-0: the Z FLAG is set at a multiple of 16, the end of the line's bytes.
51B8
If the Z FLAG is set (16 bytes done), JUMP to 51C3H for the characters.
51BA
AND 03H E6 03
Mask Register A to bits 1-0: the Z FLAG is set after every fourth byte.
51BC
LD A,20H 3E 20
Load Register A with 20H, a space. LD does not change the flags.
51BE
If the Z FLAG is set (after a fourth byte), GOSUB to the ROM's 003BH to print Register A (one more space).
51C1
LOOP BACK to 5193H for the next byte at Register Pair HL.
51C3
LD A,20H 3E 20
Load Register A with 20H, a space, before the characters.
51C5
GOSUB to the ROM's 003BH to print Register A (the space before the characters).
51C8
POP HL E1
Restore Register Pair HL from the stack: the address of the line.
51C9
LD A,(HL) 7E
Fetch the byte at Register Pair HL into Register A.
51CA
CP 20H FE 20
Compare Register A (the byte) against 20H, a space.
51CC
If the C FLAG is set (a control code), JUMP to 51D2H to print a period.
51CE
CP 80H FE 80
Compare Register A (the byte) against 80H, the first code with bit 7 set.
51D0
If the C FLAG is set (20H-7FH), JUMP to 51D4H to print the character.
51D2
LD A,2EH 3E 2E
Load Register A with 2EH, a period, for a byte with no character.
51D4
GOSUB to the ROM's 003BH to print Register A (the character or the period).
51D7
INC HL 23
Increment Register Pair HL to the next byte of the line.
51D8
LD A,L 7D
Copy Register L (low byte of the address) into Register A.
51D9
AND 0FH E6 0F
Mask Register A to bits 3-0: the Z FLAG is set at the end of the line.
51DB
If the NZ FLAG is set (characters left), LOOP BACK to 51C9H.
51DD
LD A,0DH 3E 0D
Load Register A with 0DH, a carriage return, to end the line.
51DF
GOSUB to the ROM's 003BH to print Register A (the end of the line).
51E2
PUSH HL E5
Save Register Pair HL (the address of the next line) to the stack.
51E3
XOR A AF
Set Register A to 00H and clear the CARRY FLAG (XOR A) for the subtraction.
51E4
SBC HL,BC ED 42
Subtract Register Pair BC (the end) from Register Pair HL: the C FLAG is set while the next line starts below the end.
51E6
POP HL E1
Restore Register Pair HL (the address of the next line) from the stack.
51E7
If the C FLAG is set (more lines), JUMP to 5191H and on to 514EH. With an end of FFF1H-FFFFH the address wraps to 0000H, below the end, and the listing never stops; no key is tested.
51E9
LD A,0DH 3E 0D
Load Register A with 0DH, a carriage return, for the end of the listing.
51EB
GOSUB to the ROM's 003BH to print Register A (0DH).
51EE
GOSUB to the ROM's 003BH to print Register A (0DH) again.
51F1
JUMP to the ROM's 003BH to print Register A (0DH) a third time; its RET goes back to the monitor.