TRS-80 DOS - NEWDOS/80 v2.0 for the Model I - SYS20/SYS Disassembled
Page Customization
Page Index
SYS20/SYS
Other Navigation
Introduction/Summary
NEWDOS/80 v2.0 SYS20/SYS Disassembly - BASIC CMD, FN, INSTR, MID$=, &H, OPEN and LINE INPUT (Model I)
SYS20/SYS holds the BASIC statements and functions that are not needed often enough to stay in BASIC/CMD: CMD with a DOS command, CMD"S=" and CMD"F=" (with POPS, POPR and POPN), user functions (FN), INSTR, MID$ on the left side of an assignment, &H and &O constants, OPEN, the reading of INPUT# and READ items from a file, and LINE INPUT. It is one of the three BASIC overlays that load at 5200H, here 5200H-56E7H (1,256 bytes, transfer address 5200H); 56AEH-56E7H are unused zero bytes. BASIC loads it with RST 28H code 36H (function 1 of directory slot 16H) through its overlay loader at 576CH.
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 | 57A5H | CMD"command", CMD"S=command", CMD"F=function" (5202H). |
| 534AH | 577FH | FN (vector 4155H) (534AH). |
| 53F2H | 5786H | INSTR (vector 419DH) (53F2H). |
| 5462H | 578BH | MID$(...)= (link 41D9H) (5462H). |
| 54C5H | 5790H | &H and &O constants (vector 4194H) (54C5H). |
| 5504H | 5798H | OPEN (vector 4179H) (5504H). |
| 55D4H | 579AH | INPUT# and READ items (link 41DCH) (55D4H). |
| 55E8H | 579FH | LINE INPUT (vector 41A3H) (55E8H). |
Variables
Locations inside SYS20 whose contents change while it runs, or that are read as data:
| Address Range | Purpose |
|---|---|
| 5272H-5273H 2 bytes | Start of the saved copy of 5200H-70FFH below BASIC's stack (operand of 5271H). 0000H in the file; written at 5236H; used by the copy-back code running in the copy. |
| 5275H-5276H 2 bytes | 5200H, the start of the memory saved (operand of 5274H); also read as data at 5245H. |
| 5278H-5279H 2 bytes | 1F00H, the length of 5200H-70FFH (operand of 5277H); also read as data at 522FH. |
| 5290H-5291H 2 bytes | BASIC's Stack Pointer while a full DOS command runs (operand of 528FH). 0000H in the file; written at 5224H. |
| 52C9H-52CAH 2 bytes | Address of the 64-byte checksum window, 192 bytes below BASIC's stack (operand of 52C8H). 0000H in the file; written at 522CH; read at 529AH and 52A7H. |
| 5386H-5387H 2 bytes | FN: the DEF's text pointer while the parameters are assigned (written at 5366H), then the call's text pointer after the arguments (written at 53AAH, read at 53E9H). Operand of 5385H; 0000H in the file. |
Locations outside SYS20 that it reads or writes:
| Address Range | Purpose |
|---|---|
| 40A0H-40A1H 2 bytes | The ROM's pointer to the start of the string space; BASIC's stack lies just below it. POPS (531BH) and MID$ (546FH). |
| 40A7H-40A8H 2 bytes | The ROM's pointer to the input buffer, where file items are collected (5622H). |
| 40AFH 1 byte | The ROM's type flag of the current value (02H integer, 03H string, 04H single, 08H double), tested by RST 20H. |
| 40B1H-40B2H 2 bytes | The ROM's pointer to the top of BASIC's memory, where the checksum ends (52B5H). |
| 40B3H-40B4H 2 bytes | The ROM's pointer to the next free entry of the string temporary pool (53B0H, 53C8H). |
| 40D3H-40D5H 3 bytes | DSCTMP, the ROM's string descriptor work area (53C2H). |
| 40FDH-40FEH 2 bytes | The ROM's pointer to the end of the array table: the saved copy must lie above it (523AH). |
| 4121H-4122H 2 bytes | REG 1; for a string result it holds the address of the descriptor (53B4H, 5408H). |
| 4200H-42FFH 256 bytes | DOS sector buffer area; its top (42FCH) is a temporary stack at 527FH. |
| 4318H-4367H 80 bytes | SYS0's command buffer, holding the CMD string copied there by BASIC 57FFH. |
| 436AH 1 byte | SYS0's DOS state byte; bit 7 = MINI-DOS mode, set around the first try of a CMD command (520FH-5217H). |
| 5700H-5703H 4 bytes | BASIC's file work area: mode byte, open flags and record length stored by OPEN (55C9H-55CDH). |
| 5711H 1 byte | High byte of the buffer address in the FCB at 570DH, raised by 1 for records shorter than 256 (5570H). |
| 5716H 1 byte | LRL (record length) byte of the FCB at 570DH, set to 1 to give back one character (5691H). |
| 5952H table | BASIC's CMD"F=" function table: name length, name, address; ends with 00H (52EDH). |
| 64C6H 1 byte | BASIC's file area size, 2 when BASIC was started with the V option (5573H). |
Running a Full DOS Command
A DOS command from CMD"command" is first run as a MINI-DOS command, which leaves BASIC in memory. If the DOS answers ILLEGAL MINI DOS FUNCTION (38H), SYS20 copies BASIC's memory 5200H-70FFH to just below the stack, together with a short routine (5271H) that copies it back, and records a checksum of everything from 7100H to the top of memory in a 64-byte window below the stack (529AH). The command then runs as a full DOS command in 5200H-70FFH. When it returns, the memory is copied back and the checksum is made again; if any byte from 7100H up has changed, BASIC reports MEMORY FAULT (23H).
Disassembly
5200H - Load Entry
BASIC/CMD loads SYS20 through its overlay loader at 576CH with RST 28H code 36H (function 1 of directory slot 16H) 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, 534AH, 53F2H, 5462H, 54C5H, 5504H, 55D4H or 55E8H).
5202H - CMD"command": Run a DOS Command from BASIC
Entered from BASIC 57A5H when the CMD string is longer than one character and does not end in $. BASIC 57FFH has evaluated the string, pushed its text pointer, copied the string in upper case to SYS0's command buffer at 4318H (ending with 0DH) and pushed its length count at 57A4H; Register Pair HL holds 4318H. CMD"S=command" leaves BASIC and runs the DOS command; CMD"F=name" runs one of BASIC's functions POPS, POPR, POPN, ERASE, KEEP, SASZ, SWAP or SS (table at BASIC 5952H); any other string is a DOS command, first run as a MINI-DOS command (BASIC stays in memory). If the DOS answers 38H (ILLEGAL MINI DOS FUNCTION), BASIC's memory 5200H-70FFH is copied below the stack, the command runs as a full DOS command, the memory is copied back, and a checksum of everything from 7100H to the top of memory must be unchanged, or the result is error 23H MEMORY FAULT.
Store the Stack Pointer SP (BASIC's stack, with the text pointer on top) at 5290H, the operand of the LD SP,0000H at 528FH, which puts it back after the command.
Store Register Pair HL (the checksum window's address) at 52C9H, the operand of the LD HL,0000H at 52C8H; the checksum routine also reads it at 529AH and 52A7H.
Store Register Pair HL (the copy's start) at 5272H, the operand of the LD HL,0000H at 5271H, so the copy code knows where to copy back from.
5271H - Back from the Command: Restore BASIC's Memory
5271H-527EH is executed in the saved copy below the stack (the DOS command has used 5200H-70FFH): it copies 5200H-70FFH back and jumps to 527FH in the restored SYS20. The operand at 5272H was set at 5236H; 5275H (5200H) and 5278H (1F00H) are also read as data at 5245H and 522FH.
Load Register Pair HL with the copy's start; the operand 5272H (0000H in the file) was stored at 5236H. This instruction runs in the saved copy.
Load the Stack Pointer SP with BASIC's stack; the operand 5290H (0000H in the file) was stored at 5224H.
529AH - The Memory Checksum
The 64-byte window (its address in the operand 52C9H) is filled with A5H, then every byte from 7100H to the top of memory (40B1H), except the window itself, is XORed into it, byte 0 of the window with byte 0, 64, 128 ... of memory, and so on. The second run (entry 52A4H, after the DOS command) XORs the same bytes into the window again; if memory is unchanged each byte cancels out and the window holds A5H in every byte again: the Z FLAG is set.
Load Register Pair HL with the checksum window's address; the operand 52C9H (0000H in the file) was stored at 522CH. The window restarts here after every 64 bytes.
52E2H - CMD"S=" and CMD"F="
Register Pair DE points at the command's first character (4318H) and Register Pair HL at the = (4319H); Register C holds the length of the CMD string minus 1. S= leaves BASIC for the DOS; F= looks the name up in BASIC's function table at 5952H, whose entries are a length byte, the name and a 2-byte address, ending with a 00H length.
TABLE SEARCH LOOP
Register Pair DE walks through the function table; Register Pair HL is saved and points at the name after F=.
5316H - CMD"F=POPS", "F=POPR" and "F=POPN"
Three of the functions in the table at BASIC 5952H are here. POPS empties BASIC's stack of every GOSUB and FOR. POPR drops the latest GOSUB (and any FOR loops opened after it) without returning. POPN [var] drops a FOR loop (the latest, or the one of var) and any opened after it. Each continues with the next statement. On entry Register Pair HL holds BASIC's text pointer.
534AH - FN: Calling a User Function
Entered from BASIC 577FH through the ROM vector 4155H when an expression holds FN name(arguments). The function's variable entry (found by BASIC 5837H) holds a pointer to the DEF FN statement's text. For each parameter named in the DEF, the parameter variable's current value is saved on the stack, the matching argument of the call is evaluated and assigned to it (the separators of the call and the DEF must match), then the expression after = in the DEF is evaluated, the parameters get their old values back, and the result is converted to the function's type. Register Pair HL is BASIC's text pointer at the function's name on entry.
PARAMETER LOOP
Register Pair HL = the DEF's text at the next parameter, Register Pair DE = the call's text at the next argument.
Store Register Pair HL (the DEF's text pointer, after this parameter) at 5386H, the operand of the LD HL,0000H at 5385H.
Load Register Pair HL with the DEF's text pointer; the operand 5386H (0000H in the file) was stored at 5366H.
Store Register Pair HL (the call's text pointer) at 5386H, the operand of 5385H, which is read back as data at 53E9H.
RESTORE THE PARAMETERS
Each saved parameter left its type (Register A) and its variable's address on the stack; a zero type (pushed at 534FH) ends the loop.
53F2H - INSTR
Entered from BASIC 5786H through the ROM vector 419DH. INSTR([start,]string1,string2) returns the position of string2 in string1, searching from the position start (1 if left out), or 0 if it is not there. Register Pair HL is BASIC's text pointer at the INSTR token on entry.
SEARCH LOOP
Register Pair HL = the place in string1 being tried, Register Pair DE = string2's text, Register C = string2's length, Register B = the places left to try; the position counter is on the stack.
5462H - MID$ on the Left Side of an Assignment
Entered from BASIC 578BH through the ROM link 41D9H. MID$(var$,position[,length])=string replaces characters of var$ in place: from the position, as many as the length (the rest of var$ if left out) and the new string allow; var$ keeps its length. A string whose text lies in the program (a literal assigned earlier) is first copied to the string space so the program is not changed. Register Pair HL is BASIC's text pointer at the MID$ token on entry.
54C5H - &H and &O Constants
Entered from BASIC 5790H through the ROM vector 4194H when an expression holds &. &Hdigits is hexadecimal; &Odigits or &digits is octal. The value is built in Register Pair DE (16 bits, 0-65535) and returned as an integer in REG 1; more than 16 bits is OVERFLOW. Register Pair HL is BASIC's text pointer at the & on entry.
HEXADECIMAL DIGIT LOOP
Register Pair DE (swapped into HL while working) = the value so far; Register Pair HL = the text pointer.
OCTAL DIGIT LOOP
Same as the hexadecimal loop, but only 0-7 are digits and each digit multiplies the value by 8.
5504H - OPEN
Entered from BASIC 5798H through the ROM vector 4179H. OPEN "mode",file,"name"[,type][,record length]. The mode letter (I, O, E, R or D) gives the mode byte for 5700H and the open flags for BASIC 60AEH: whether the file must exist, may be created, is emptied or is positioned at its end. The optional type is two letters: the first F or M, the second I, U or F (MI, MU, MF, FI, FF); the I types have no record length (7FFFH), the others take one up to 4095, and FF and MF need one. Without a type, a random file may have a record length of 1-256 (below 256 only when BASIC was started with the V option, 64C6H = 2). The SYS10 page explains what the bits of the mode byte mean. On entry Register Pair HL is BASIC's text pointer after OPEN.
55D4H - INPUT# and READ Items from a File
Entered from BASIC 579AH through the ROM link 41DCH, which the ROM's INPUT and READ code calls when it is about to assign an item. BASIC 63A9H returns straight to the ROM unless an INPUT# is reading a file; otherwise the next item is read from the file into BASIC's input buffer (5621H) and the ROM's READ code assigns it to the variable.
55E8H - LINE INPUT
Entered from BASIC 579FH through the ROM vector 41A3H (the LINE token). LINE INPUT ["prompt";]var$ reads a whole line from the keyboard (BREAK stops the program); LINE INPUT#file,var$ reads a whole line from a file. Either way the line goes into var$ unchanged, commas and quotes included. On entry Register Pair HL is BASIC's text pointer after LINE.
5621H - Read an Item from a File
Reads characters through BASIC 6119H (from the file open for input) into the input buffer (its address at 40A7H), at most 255. Register D holds the rules: bit 0 = skip leading spaces, and a comma or a line feed ends the item; bit 1 = quotes allowed (a quoted string may hold commas); bit 2 = a space ends the item; bit 3 = inside quotes (set here). A carriage return ends the item; a line feed after it is taken with it. A character read one too far is given back (the FCB is moved back one byte with SYS0 4445H and an LRL of 1). The end of the file is error 7CH INPUT PAST END. The item is then made a string (the ROM's STRLIT at 2868H) or a number (the ROM's FIN at 0E6CH). Register Pair AF on entry holds the Z FLAG for a string item.
SKIP LEADING SPACES
Register D = the item rules; Register A = the character just read.
CHARACTER LOOP
Register Pair HL = where the next character goes in the input buffer, Register B = the room left, Register C = the previous character, Register D = the rules.
AFTER THE ITEM
After a closing quote, or a space ending a number, skip spaces and look for the separator.
56AEH - Unused Bytes
56AEH-56E7H fill the last load record; nothing reads or executes them.