TRS-80 DOS - NEWDOS/80 v2.0 for the Model III - SYS19/SYS Disassembled
Page Customization
Page Index
SYS19/SYS
Other Navigation
Introduction/Summary
NEWDOS/80 v2.0 SYS19/SYS Disassembly - LOAD, RUN, MERGE, SAVE and CMD"F",DELETE (Model III)
SYS19/SYS carries out the Disk BASIC statements that read or write a whole program. It loads 5200H-56E7H in five load records (transfer address 5200H); the code ends at 5650H and 5651H-56E7H are 151 bytes of 00H. It is one of the BASIC overlays that BASIC/CMD loads at 5200H through its loader at 576CH (RST 28H code 35H). 5200H itself only returns with the Z FLAG set; BASIC/CMD then jumps to the entry it put in Register Pair BC. BASIC/CMD has already opened the file in its work area 5700H-572DH (Index Register IX = 5700H, the FCB at 570DH, the sector buffer at 4300H). There are four entries:
- 5202H, LOAD and RUN with a file name (from BASIC/CMD 574FH; LOAD through the ROM vector 4188H, RUN through the link 41C7H).
- 5334H, MERGE (from BASIC/CMD 5731H, the ROM vector 418BH).
- 559CH, CMD"F",DELETE (from BASIC/CMD 5736H, the CMD letter dispatch at 57CEH).
- 55C5H, SAVE (from BASIC/CMD 5741H, the ROM vector 41A0H).
The page shows every byte of the file once, in address order.
Commands
| Statement | What SYS19/SYS does |
|---|---|
| LOAD "file" | Clears the program and the variables (ROM 1B4DH), reads the file and ends at READY. The open files are closed as usual. |
| RUN "file" | As LOAD, then starts the program at its first line (ROM NEWSTT at 1D1EH). |
| LOAD "file",R and RUN "file",R | Load and run; the open files stay open (C9H is put at BASIC/CMD 5FA8H, so the close-all-files loop at 5F8FH closes nothing). |
| LOAD "file",V and RUN "file",V | Load and run, keeping the open files and the variables: trace is switched off, the old program is deleted with 54C8H (strings whose text lies in it are copied to the string space first) and the new program is read in its place. |
| MERGE "file" | Puts the file's lines in among the program's lines by line number; a line of the file replaces an old line with the same number. Typed as a command it ends at READY. In a running program the statement must be the last on its line (BASIC/CMD 5D78H), no old line may be replaced (ILLEGAL FUNCTION CALL) and the program goes on with the next line. |
| SAVE "file" | Writes FFH and the program as it is in memory, 256 bytes a sector straight from memory, then reads the whole file back to check it. |
| SAVE "file",A | Writes the program as text through the ROM's LIST (2B2EH), with a sector buffer 384 bytes below the stack. |
| CMD"F",DELETE range | In a running program: deletes the lines of the range (written as for the ROM's DELETE) without losing the variables and goes on with the line after the statement, which must be the last on its line. |
A file that starts with FFH is a tokenized program, read line by line from the sector buffer. Any other file is BASIC text: each line (at most 240 characters, ended by a carriage return) must start with a line number (else DIRECT STATEMENT IN FILE) and is tokenized by the ROM's CRUNCH. A line 65535 in the file gives SEQ # OVERFLOW.
While the file is read the program in memory and its variables are moved up to 160 bytes below the stack, and the old lines are copied in among the new ones as the new lines arrive (53B4H). The pointers of string variables and DEF FN functions whose text lies in the old lines are moved with them (5478H). BASIC/CMD's statement-end CALL at 6426H is pointed at 543EH for the length of the load, so an error during the load still puts the program and the variables back together.
A file with access level EXEC can be RUN (or MERGEd by a running program) but not LOADed: SYS19/SYS lowers the level in the FCB to READ, sets BASIC/CMD's RUN ONLY flag at 63FAH and makes the BREAK hook at 4478H a jump to 4546H, so BREAK is ignored. A file with access level LOCK gives FILE ACCESS DENIED. When the SYSTEM option AB (RUN ONLY) is on, the RUN ONLY and BREAK settings are left as they are.
Variables
ROM Addresses
| Address Size | Contents |
|---|---|
| 40A2H-40A3H 2 bytes | Current Line Number FFFFH while a direct command runs (5334H). |
| 40A4H-40A5H 2 bytes | TXTTAB The start of the program (525AH, 5290H, 52C0H, 531AH, 55E6H). |
| 40A7H-40A8H 2 bytes | Input Buffer Where a text line is collected (5368H). |
| 40F0H-40F1H 2 bytes | ON ERROR GOTO Set to 0000H at 54E2H. |
| 40F9H-40FAH 2 bytes | VARTAB The start of the simple variables, just past the program (525EH, 52B8H, 5448H, 5454H, 54A4H, 54FCH, 55D8H, 55F1H). |
| 40FBH-40FCH 2 bytes | ARYTAB The start of the arrays (52BDH, 5461H, 5498H, 54FFH). |
| 40FDH-40FEH 2 bytes | STREND The end of the arrays (52A0H, 52AAH, 546EH, 5495H, 5527H). |
DOS Addresses
| Address Size | Contents |
|---|---|
| 4289H 1 byte | System State Bit 6 is set at 5277H: an overlay function runs. |
| 428CH 1 byte | SYSTEM Options Bit 6, the option AB (RUN ONLY), is tested at 5237H. |
| 4300H-43FFH 256 bytes | Sector Buffer The FCB's buffer while a file is loaded (52DDH). |
| 4478H 1 byte | BREAK Hook C9H (BREAK passed on) or C3H (JP 4546H, BREAK ignored), stored at 5252H. |
BASIC/CMD Addresses
| Address Size | Contents |
|---|---|
| 570DH-572DH 33 bytes | FCB The open file (5279H, 54B3H, 55FFH). 570EH: the access level in bits 0-2 (522BH, 5248H, 5340H, 5349H); 5710H-5711H: the buffer address (55D5H, 55EDH, 5613H); 5712H: the end byte (55FBH); 5717H: the NEXT position (535BH). |
| 57B8H-57B9H 2 bytes | Next Line Number Stored by BASIC/CMD 5D78H, read at 5322H. |
| 5FA8H 1 byte | Close-All Loop C8H (RET Z) or C9H (RET), stored at 5224H. |
| 63FAH 1 byte | Run-Only Flag 00H allows direct commands; stored at 524EH. |
| 6427H-6428H 2 bytes | Statement-End CALL The operand of BASIC/CMD's CALL at 6426H: 543EH during the load (52DAH), 6496H again afterwards (6497H). |
Operands Changed at Run Time
| Address Size | Contents |
|---|---|
| 5255H 1 byte | LOAD or V 18H (JR 526BH) or 3EH (LD A,nn) for V, stored at 5228H. |
| 5315H 1 byte | Mode Operand of 5314H: 0 LOAD or MERGE as a command, 1 RUN, 2 MERGE in a program (5220H, 5355H; read at 5242H, 53D3H). |
| 53DCH-53DDH 2 bytes | Next Old Line Operand of 53DBH (52B2H, 53EEH, 54C8H; read at 53FEH, 5444H, 54BEH). |
| 5429H-542AH 2 bytes | Old Lines Start Operand of 5428H (52C3H, 5437H, 54CEH; read at 548AH). |
| 5442H-5443H 2 bytes | Program Pointer Operand of 5441H (52E6H, 535FH, 5408H, 54D2H; read at 547BH). |
| 5459H-545AH 2 bytes | Simple Variables Size Operand of 5458H (54AEH). |
| 5466H-5467H 2 bytes | Arrays Size Operand of 5465H (549FH). |
| 547FH-5480H 2 bytes | Last Placed Operand of 547EH (52C6H, 5404H, 54CBH). |
| 5488H-5489H 2 bytes | Old Lines End Operand of 5487H (54A7H). |
| 54F0H-54F1H 2 bytes | Return Address Operand of the JP at 54EFH (54E6H). |
| 5565H-5566H 2 bytes | Range End Operand of 5564H (54F8H). |
| 556CH-556DH 2 bytes | Range Start Operand of 556BH (54F5H). |
| 5574H 1 byte | Fix Mode Operand of 5573H (54F2H). |
| 5576H 1 byte | String Length Operand of 5575H (5560H). |
| 557AH-557BH 2 bytes | Move Distance Operand of 5579H (5484H; read at 562DH). |
| 5642H-5643H 2 bytes | Offset Operand of 5641H (5623H, 5632H, 563AH; read at 562AH). |
Outside Routines
| Where | Addresses |
|---|---|
| ROM | 0BAAH (multiply), 197AH (OMERR), 1997H (SNERR), 1A19H (READY), 1AF8H (LINKER), 1B10H (SCNLIN), 1B2CH (FNDLIN), 1B4DH (NEW), 1B8FH (STKINI), 1BC0H (CRUNCH), 1D1EH (NEWSTT), 1DF8H (TROFF), 1E4AH (FCERR), 1E5AH (LINGET), 2169H (FINPRT), 28BFH (GETSPA), 2B2EH (LIST); RST 08H, RST 10H, RST 18H. |
| SYS0/SYS | 4436H (read a sector), 4439H (write a sector). |
| BASIC/CMD | 5D78H (next line), 5DB8H (error 84H), 5DBBH (error 8CH), 5DEFH (DOS error), 60F2H (read a byte), 6240H (rewind), 6368H (comma or end), 6370H (read a sector), 6386H and 6392H (file statement flag 6382H), 6497H (statement-end CALL back). |
Disassembly
5200H - Load Entry
BASIC/CMD loads SYS19/SYS through its overlay loader at 576CH with RST 28H code 35H (function 1 of directory slot 15H) into 5200H-56E7H. After loading, the SYS0/SYS dispatcher calls 5200H, which must return with the Z FLAG set (no error); BASIC/CMD then jumps to the entry address it put in Register Pair BC (5202H, 5334H, 559CH or 55C5H).
5202H - LOAD and RUN with a File Name
Entered from BASIC 574FH for LOAD "file" (BASIC 574AH, the ROM vector 4188H, Register A = 0) and RUN "file" (BASIC 5746H, the ROM link 41C7H, Register A = 1). BASIC has opened the file in its work area 5700H-572DH (BASIC 6073H; Index Register IX = 5700H, the FCB at 570DH, its sector buffer at 4300H) and pushed Register Pair AF. Options after the name: R (run it, and leave the open files open) and V (run it and keep the variables). A program whose access level is EXEC can be RUN but not LOADed: it is read at level READ, BREAK is disabled and BASIC is set to RUN ONLY. Register Pair HL is BASIC's text pointer after the file name.
Store Register A (the mode) at 5315H, the operand of the LD A,00H at 5314H, which chooses what happens after the load.
Store Register A at 5255H, the opcode of the instruction there: JR 526BH (18H) clears the program and variables; LD A,14H (3EH) goes on at 5257H for V.
This opcode is written at 5228H: JR 526BH (18H) for LOAD, RUN and R, a JUMP to the code that clears the program and variables; or LD A,14H (3EH) for V, which takes the offset byte as its operand and goes on at 5257H. The file holds 28H, JR Z,526BH, which is never executed.
5289H - Make Room and Read a Tokenized File
The program in memory (for MERGE and V) and its variables are moved up to just below the stack, keeping 160 bytes free; the new program is then built from the program's start (40A4H), and the old lines are copied in among the new ones by line number (53B4H). While this runs, BASIC's statement-end clean-up calls 543EH, so an error during the load still puts memory back in order. A file starting with FFH is a tokenized program, read line by line straight from the sector buffer at 4300H.
Store Register Pair DE (the first old line) at 53DCH, the operand of the LD HL,0000H at 53DBH: the next old line to put in.
Store Register Pair HL at 5429H, the operand of the LD BC,0000H at 5428H, the start of the range whose string pointers 5478H moves.
Store Register Pair HL at 547FH, the operand of the LD DE,0000H at 547EH: the program pointer when the current run of old lines began.
TOKENIZED LINE LOOP
Register Pair HL = the position in the sector buffer (Register L wraps to 00H at the end of a sector, when 54B2H reads the next one), Register Pair DE = the program pointer.
Store Register Pair DE (the program pointer) at 5442H, the operand of the LD DE,0000H at 5441H, so 543EH and 5478H know how far the new program reaches.
COPY THE LINE'S TEXT
Register Pair HL = the sector buffer, Register Pair DE = the program pointer.
Load Register A with the mode; the operand 5315H holds 0 (LOAD, or MERGE typed as a command), 1 (RUN) or 2 (MERGE in a running program), stored at 5220H or 5355H.
5334H - MERGE
Entered from BASIC 5731H for MERGE "file" (BASIC 572EH, the ROM vector 418BH), with the file open in the work area as for LOAD. The file's lines are put in among the program's lines. Typed as a command, MERGE ends at READY; in a running program its lines may not replace existing ones (ILLEGAL FUNCTION CALL) and the program goes on with the line after the MERGE statement. Register Pair HL is BASIC's text pointer after the file name.
Store Register A (the mode: 00H for a command, 02H in a program) at 5315H, the operand of the LD A,00H at 5314H.
535BH - Load a Text File
A file that does not start with FFH is BASIC text. Each line (ended by a carriage return, at most 240 characters, 00H bytes and a line feed at the start skipped) is read into BASIC's input buffer, must start with a line number (else error 84H DIRECT STATEMENT IN FILE), and is tokenized by the ROM's CRUNCH; then it is put in like a tokenized line. Register Pair DE is the program pointer.
TEXT LINE LOOP
Register Pair DE (saved on the stack while reading) = the program pointer.
Store Register Pair DE (the program pointer) at 5442H, the operand of the LD DE,0000H at 5441H.
CHARACTER LOOP
Register Pair HL = where the next character goes, Register E = the characters still allowed.
COPY THE TOKENIZED LINE
Register Pair HL = the tokenized line, Register Pair DE = the program pointer.
53B4H - Put In a Line
Called with Register Pair BC = the new line's number and Register Pair DE = the program pointer; the next old line's number lies on the stack below the return address. Old lines with smaller numbers are copied in first (53FEH); an old line with the same number is dropped, the new one replacing it (not allowed in mode 2); then the new line's header (a non-zero dummy link and the number) is stored. The real links are made at the end by the ROM's LINKER (543EH). Register Pair HL (the caller's position in the file data) is kept on the stack meanwhile.
NUMBER COMPARE
Register Pair HL = the next old line's number, Register Pair BC = the new line's number.
Load Register Pair HL with the address of the next old line; the operand 53DCH (0000H in the file) was stored at 52B2H or 53EEH.
Store Register Pair HL (the next old line's address) at 53DCH, the operand of 53DBH.
COPY THE OLD LINES THAT COME FIRST
Register Pair HL = the old line, Register Pair DE = the program pointer, Register Pair BC = the new line's number.
Store Register Pair DE (the program pointer) at 547FH, the operand of 547EH: the program pointer when this old line is placed.
Store Register Pair DE (the program pointer) at 5442H, the operand of 5441H.
Load Register Pair BC with the address the old line had before the move, in the operand 5429H (0000H in the file; stored at 52C3H, 54CEH and 5437H); it grows by the length of every old line copied.
COPY THE OLD LINE'S TEXT
Register Pair HL = the old line, Register Pair DE = the program pointer, Register Pair BC = the old address counter.
Store Register Pair BC (the old address of the next old line) at 5429H, the operand of 5428H.
543EH - Close Up
Moves the old lines that are left (from 53DCH) down behind the new program, then the simple variables and the arrays; stores the new pointers at 40F9H, 40FBH and 40FDH; rebuilds the line links with the ROM's LINKER; and puts BASIC's statement-end CALL at 6426H back (6497H). Also reached from BASIC's clean-up at 6423H if an error ends the load (the CALL was pointed here at 52DAH).
Load Register Pair DE with the program pointer, the end of the new program so far; the operand 5442H (0000H in the file) was stored at 52E6H, 535FH, 5408H or 54D2H.
Load Register Pair BC with the size of the simple variables; the operand 5459H (0000H in the file) was stored at 54AEH.
Load Register Pair BC with the size of the arrays; the operand 5466H (0000H in the file) was stored at 549FH.
5478H - Move the String Pointers into the Old Lines
Called before each run of old lines is copied and before the close-up. The new bytes put in since the last old line was placed (the program pointer 5442H minus 547FH) push the old lines not yet copied further along; every string or DEF FN pointer of a variable that points into them (the range from 5429H to 5488H, in the addresses they had before the move, corrected by the offset 5642H) is moved by that distance, which is then added to the offset. Register Pairs HL, DE and BC are kept.
Load Register Pair DE with the program pointer when the last old line was placed; the operand 547FH (0000H in the file) was stored at 52C6H, 5404H or 54CBH.
Store Register Pair HL (the distance) at 557AH, the operand of the LD HL,0000H at 5579H, which 54F2H adds to each pointer it moves.
Load Register Pair DE with the end of the range, the start of the simple variables before the move; the operand 5488H (0000H in the file) was stored at 54A7H.
Store Register Pair HL (the arrays' size) at 5466H, the operand of the LD BC,0000H at 5465H.
Store Register Pair HL (the start of the simple variables) at 5488H, the operand of the LD DE,0000H at 5487H.
Store Register Pair HL (the simple variables' size) at 5459H, the operand of the LD BC,0000H at 5458H.
54B2H - Read the Next Sector, Check the Room
54B2H reads the next sector of the file into 4300H (called when Register L wraps to 00H, so Register Pair HL is 4300H again afterwards). 54BDH checks that the new program (Register Pair DE) is still at least 256 bytes below the next old line, else OUT OF MEMORY.
54C8H - Delete Lines, Keeping the Variables
Called with Register Pair HL = the last byte and Register Pair DE = the first line of the part of the program to delete (from 5263H for V, from 55BCH for CMD"F",DELETE). Strings of variables whose text lies in that part are copied to the string space first (54F2H with mode 0); then 543EH closes the program up, treating the rest of the program as the old lines left.
Store Register Pair HL (the end of the part to delete) at 53DCH, the operand of 53DBH: the rest of the program counts as the next old line.
Store Register Pair HL at 547FH, the operand of 547EH.
Store Register Pair HL at 5429H, the operand of 5428H.
Store Register Pair HL (the first line to delete) at 5442H, the operand of 5441H: the close-up moves the rest of the program down to here.
Store Register Pair HL (the return address) at 54F0H, the operand of the JP 0000H at 54EFH.
JUMP back to the caller; the operand 54F0H (0000H in the file) was stored at 54E6H.
54F2H - Fix the String Pointers of the Variables
Walks the simple variables (from 40F9H to 40FBH) and the arrays (to 40FDH). Every string, and every DEF FN pointer (bit 7 of the name's first character), whose text lies after the start and up to the end of the range (both corrected by the offset at 5642H) is either copied into the string space (mode 0, used when lines are deleted; a DEF FN pointer becomes 0000H) or moved by the distance at 557AH (any other mode). Called with Register A = the mode, Register Pair HL = the start and Register Pair DE = the end of the range.
Store Register A (the mode) at 5574H, the operand of the OR 00H at 5573H.
Store Register Pair HL (the start of the range) at 556CH, the operand of the LD HL,0000H at 556BH.
Store Register Pair DE (the end of the range) at 5565H, the operand of the LD HL,0000H at 5564H.
SIMPLE VARIABLE LOOP
Register Pair HL = the variable entry (type byte, second name character, first name character, value).
ARRAY LOOP
Register Pair HL = the array entry (type, name, 2-byte length, dimension count, dimensions, elements).
COUNT THE ELEMENTS
Register A = the dimensions left, Register Pair DE = the product so far.
ELEMENT LOOP
Register Pair HL = the element's descriptor, Register Pair DE (on the stack) = the elements left.
Store Register A (the string's length, 0 for a DEF FN pointer) at 5576H, the operand of the LD A,00H at 5575H.
Load Register Pair HL with the end of the range; the operand 5565H (0000H in the file) was stored at 54F8H.
Load Register Pair HL with the start of the range; the operand 556CH (0000H in the file) was stored at 54F5H.
OR Register A with the mode, the operand 5574H stored at 54F2H: the Z FLAG is set for mode 0 (copy into the string space).
Load Register A with the string's length, the operand 5576H stored at 5560H. LD does not change the flags.
Load Register Pair HL with the distance the old lines move; the operand 557AH (0000H in the file) was stored at 5484H.
559CH - CMD"F",DELETE
Entered from BASIC 5736H for CMD"F" (from the CMD letter dispatch at BASIC 57CEH). CMD"F",DELETE range in a running program deletes the lines of the range (written as for the ROM's LIST and DELETE) without losing the variables (their strings in those lines are copied to the string space) and goes on with the line after the statement. Register Pair HL is BASIC's text pointer after the CMD string, Register A its next character.
55C5H - SAVE
Entered from BASIC 5741H for SAVE (BASIC 573BH, the ROM vector 41A0H) with the file opened new in BASIC's work area (Index Register IX = 5700H, the FCB at 570DH). SAVE "file" writes the program as it is in memory, after an FFH byte, 256 bytes a sector straight from memory, then reads the file back to check it. SAVE "file",A writes it as text through the ROM's LIST. Register Pair HL is BASIC's text pointer after the file name.
SECTOR WRITE LOOP
Register Pair HL = the 256 bytes of memory written as the next sector, Register C = their first byte (put back after the write).
READ-BACK CHECK
Every sector is read again; a read error other than the end of the file stops SAVE with a BASIC error.
5620H - Small Helpers
5620H clears the offset at 5642H and returns Register Pair HL = 543EH. 562AH adds the last distance (557AH) to the offset and finishes 5478H. 5638H clears the offset and runs 54F2H. 5641H and 5649H are the two range tests used at 5568H and 556FH; when a string is out of range they abandon it by jumping to 5599H.
Store Register Pair HL (the total offset) at 5642H, the operand of 5641H.
Store Register Pair BC (0000H) at 5642H, the offset operand of 5641H.
Load Register Pair BC with the offset, the operand 5642H (0000H in the file), stored at 5623H, 5632H and 563AH.