TRS-80 DOS - NEWDOS/80 v2.0 for the Model I - SYS19/SYS Disassembled
Page Customization
Page Index
SYS19/SYS
Other Navigation
Introduction/Summary
NEWDOS/80 v2.0 SYS19/SYS Disassembly - BASIC LOAD, RUN, MERGE, SAVE and CMD"F",DELETE (Model I)
SYS19/SYS moves BASIC programs between memory and the diskette: LOAD and RUN with a file name (with the R and V options), MERGE, SAVE (as memory image or, with A, as text) and CMD"F",DELETE. It is one of the three BASIC overlays that load at 5200H, here 5200H-56E7H (1,256 bytes in five load records, transfer address 5200H); 5651H-56E7H are unused zero bytes. BASIC loads it with RST 28H code 35H (function 1 of directory slot 15H) through its overlay loader at 576CH, after opening the file in its work area at 5700H (the FCB at 570DH, the sector buffer at 4200H).
The page shows every byte of the file once, in address order. Calls into BASIC/CMD are linked only where the BASIC page has a row with the right bytes at that address.
Entry Points
| Address | From BASIC | Statement |
|---|---|---|
| 5202H | 574FH | LOAD "file"[,R | ,V] (vector 4188H) and RUN "file"[,R | ,V] (link 41C7H) (5202H). |
| 5334H | 5731H | MERGE "file" (vector 418BH) (5334H). |
| 559CH | 5736H | CMD"F",DELETE range (559CH). |
| 55C5H | 5741H | SAVE "file"[,A] (vector 41A0H) (55C5H). |
Variables
Locations inside SYS19 whose contents change while it runs (operands written by the code itself; 0000H or 00H in the file):
| Address Range | Purpose |
|---|---|
| 5255H 1 byte | Opcode written at 5228H: 18H (JR 526BH, clear the program and variables) or 3EH (LD A,nn, option V keeps them). |
| 5315H 1 byte | Mode after the load: 0 LOAD or MERGE as a command, 1 RUN, 2 MERGE in a program (operand of 5314H; written at 5220H and 5355H). |
| 53DCH-53DDH 2 bytes | Address of the next old line not yet merged (operand of 53DBH; written at 52B2H, 53EEH and 54C8H). |
| 5429H-542AH 2 bytes | The address the next old line had before the program was moved up; the start of the range of string pointers still to move (operand of 5428H; written at 52C3H, 5437H and 54CEH). |
| 5442H-5443H 2 bytes | The program pointer, where the next line of the new program goes (operand of 5441H; written at 52E6H, 535FH, 5408H and 54D2H). |
| 5459H-545AH 2 bytes | Size of the simple variables (operand of 5458H; written at 54AEH). |
| 5466H-5467H 2 bytes | Size of the arrays (operand of 5465H; written at 549FH). |
| 547FH-5480H 2 bytes | The program pointer when the last old line was placed (operand of 547EH; written at 52C6H, 5404H and 54CBH). |
| 5488H-5489H 2 bytes | Start of the simple variables before the move, the end of the range of string pointers to move (operand of 5487H; written at 54A7H). |
| 54F0H-54F1H 2 bytes | Return address of 54DFH, kept while STKINI resets the stack (operand of the JP at 54EFH; written at 54E6H). |
| 5565H-5566H 2 bytes | End of the range 54F2H works on (operand of 5564H; written at 54F8H). |
| 556CH-556DH 2 bytes | Start of that range (operand of 556BH; written at 54F5H). |
| 5574H 1 byte | 54F2H's mode: 0 copy the strings into the string space, other values move them by 557AH (operand of 5573H; written at 54F2H). |
| 5576H 1 byte | Length of the string being fixed, 0 for a DEF FN pointer (operand of 5575H; written at 5560H). |
| 557AH-557BH 2 bytes | Distance the old lines not yet copied have moved since the last old line was placed (operand of 5579H; written at 5484H). |
| 5642H-5643H 2 bytes | Offset: the total distance applied so far, added to both ends of the range (operand of 5641H; written at 5623H, 5632H and 563AH). |
Locations outside SYS19 that it reads or writes:
| Address Range | Purpose |
|---|---|
| 40A2H-40A3H 2 bytes | The ROM's current line number (FFFFH for a direct command), read by MERGE (5334H). |
| 40A4H-40A5H 2 bytes | The ROM's pointer to the start of the program, where the new program is built. |
| 40A7H-40A8H 2 bytes | The ROM's pointer to the input buffer, where a text file's lines are collected (5368H). |
| 40F0H-40F1H 2 bytes | The ROM's ON ERROR GOTO address, cleared at 54E2H. |
| 40F9H-40FEH 6 bytes | The ROM's pointers to the start of the simple variables, the start of the arrays and the end of the arrays; moved and rewritten by the load. |
| 4200H-42FFH 256 bytes | The FCB's sector buffer, from which a tokenized file is read. |
| 4312H 1 byte | Opcode of SYS0's BREAK hook: C9H (RET, BREAK enabled) or C3H (JP 45B0H, BREAK disabled), written at 5252H. |
| 4369H 1 byte | SYS0's system state; bit 6 set at 5277H (an overlay function is running). |
| 436CH 1 byte | SYS0's SYSTEM options; bit 6 = AB (RUN ONLY), read at 5234H. |
| 570DH-572DH 33 bytes | The FCB of the file (in BASIC's work area at 5700H, Index Register IX = 5700H): +1 access level (570EH), +3/+4 buffer address (5710H-5711H), +5 byte position (5712H), NEXT (5717H). |
| 57B8H-57B9H 2 bytes | Number of the line after the statement, stored by BASIC 5D9FH and read at 5322H. |
| 5FCFH 1 byte | First instruction of BASIC's close-all-files routine: C8H (RET Z) normally, C9H (RET) for R and V, written at 5224H. |
| 6421H 1 byte | BASIC's RUN ONLY flag, written at 524EH. |
| 644EH-644FH 2 bytes | Operand of the CALL at BASIC 644DH in the statement-end clean-up: 543EH during the load (52DAH), 64BDH again after it (BASIC 64BEH). |
How a Program Is Loaded
The program in memory and its variables are first moved up to just below the stack (160 bytes of room are kept). The file's lines, tokenized (the file starts with FFH) or text (tokenized by the ROM's CRUNCH as they are read), are then built up from the program's start, and the old lines are copied in among them by line number (53B4H): for LOAD and RUN the old program has been cleared first (NEW), so only MERGE and the V option keep old lines or variables. At the end the rest of the old lines and the variables are moved down behind the new program and the line links are rebuilt (543EH). String variables whose text lies in a program line are kept valid (54F2H): copied to the string space when their line is deleted, moved when the line moves. If an error stops the load, BASIC's end of statement (6445H) calls 543EH so that memory is put back in order.
R also leaves the open files open (BASIC 5FCFH made a RET). A program with the access level EXEC can be RUN but not LOADed; RUNning it sets BASIC to RUN ONLY and disables BREAK. MERGE in a running program may not replace existing lines (ILLEGAL FUNCTION CALL) and continues with the line after the statement, as CMD"F",DELETE does.
Disassembly
5200H - Load Entry
BASIC/CMD loads SYS19 through its overlay loader at 576CH with RST 28H code 35H (function 1 of directory slot 15H) into 5200H-56E7H. After loading, the SYS0 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 609AH; Index Register IX = 5700H, the FCB at 570DH, its sector buffer at 4200H) 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 4200H.
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 644DH back (64BEH). Also reached from BASIC's clean-up at 6445H 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 4200H (called when Register L wraps to 00H, so Register Pair HL is 4200H 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.
5651H - Unused Bytes
5651H-56E7H fill the last load record; nothing reads or executes them.