TRS-80 DOS - NEWDOS/80 v2.0 for the Model III - SYS20/SYS Disassembled
Page Customization
Page Index
SYS20/SYS
Other Navigation
Introduction/Summary
NEWDOS/80 v2.0 SYS20/SYS Disassembly - CMD, FN, INSTR, MID$=, &H, OPEN and LINE INPUT (Model III)
SYS20/SYS carries out a set of Disk BASIC statements and functions. It loads 5200H-56E7H in five load records (transfer address 5200H); the code ends at 56ADH and 56AEH-56E7H are 58 bytes of 00H. It is one of the BASIC overlays that BASIC/CMD loads at 5200H through its loader at 576CH (RST 28H code 36H, from 5782H). 5200H itself only returns with the Z FLAG set; BASIC/CMD then jumps to the entry it put in Register Pair BC. The page shows every byte of the file once, in address order.
Entries
| Entry | From BASIC/CMD and what it does |
|---|---|
| 5202H CMD"command" | 57A4H (from the CMD link 57ECH, a string of two or more characters not ending in $, copied to the command buffer 4225H). CMD"S=command" leaves BASIC through SYS0/SYS 4405H. CMD"F=name" runs a function from BASIC/CMD's table at 592BH (POPS, POPR, POPN here; ERASE, KEEP, SASZ, SWAP, SS in BASIC/CMD). Anything else runs through DOS-CALL 4419H, first under MINI-DOS (428AH bit 7); if the DOS answers error 38H, 5200H-70FFH is copied below the stack, the command runs as a full DOS command, the memory is copied back and a checksum of 7100H to the top of memory must be unchanged (else DOS error 23H Memory Fault). |
| 5316H, 5324H, 5334H | CMD"F=POPS" empties BASIC's stack; CMD"F=POPR" drops the latest GOSUB (RETURN WITHOUT GOSUB if there is none); CMD"F=POPN" [var] drops the latest FOR loop, or that of var (NEXT WITHOUT FOR if there is none). Each goes on with the next statement (ROM 1D25H). |
| 534AH FN | 577FH (link 4155H). Saves each parameter variable, assigns the arguments, evaluates the DEF's expression and gives the parameters their old values back. The call's and the DEF's separators must match. UNDEFINED USER FUNCTION if no DEF FN has run. |
| 53F2H INSTR | 5786H (link 419DH). INSTR([start,]string1,string2): the position of string2 in string1 from start (1 if left out; 0 is ILLEGAL FUNCTION CALL), or 0. |
| 5462H MID$= | 578BH (link 41D9H). MID$(var$,position[,length])=string replaces characters of var$ in place; var$ keeps its length. A string whose text lies in the program is copied to the string space first (BASIC 5CC4H). |
| 54C5H &H, &O | 5790H (link 4194H). &H hexadecimal, &O or & alone octal; an integer result up to 16 bits, OVERFLOW above. |
| 5504H OPEN | 5795H (link 4179H). OPEN "mode",file,"name"[,type][,record length]. Modes I, O, E (sequential), R and D (random; D needs an existing file). Types MI, MU, MF, FI, FF; the I types have no record length (7FFFH), U and F take 1-4095 (4095 if left out), MF and FF must have one. A plain random file takes 1-256, below 256 only when the file areas have room for a record buffer (649FH = 02H). |
| 55D4H INPUT# item | 579AH (link 41DCH, called by the ROM at 222DH for each item of INPUT and READ). Only during a file statement (BASIC 6382H): the item is read from the file at 5621H and assigned by the ROM at 2243H. |
| 55E8H LINE INPUT | 579FH (link 41A3H, the LINE token). LINE INPUT ["prompt";]var$ reads a line from the keyboard (BREAK stops the program); LINE INPUT#file,var$ reads one from the file. Not as a direct command. |
5621H reads an item from the file through BASIC 60F2H into the ROM's input buffer, at most 255 characters. Register D holds the rules: bit 0 skips leading spaces and line feeds and lets a comma end the item, bit 1 lets quotes enclose it, bit 2 lets a space end it; a string item uses 03H, a number 05H, LINE INPUT# 00H. A carriage return ends the item unless it follows a line feed, and a line feed after it is taken with it. A character read past the item is given back with SYS0/SYS 4445H. The end of the file before an item starts is INPUT PAST END; inside an item it ends the item.
Variables
ROM Addresses
| Address Size | Contents |
|---|---|
| 40A0H-40A1H 2 bytes | String Space Start BASIC's stack lies just below it (531BH); compared with a string's text at 546FH. |
| 40A7H-40A8H 2 bytes | Input Buffer Where an item from a file is collected (5622H). |
| 40AFH 1 byte | Value Type 02H integer, 03H string, 04H single, 08H double; tested with RST 20H. |
| 40B1H-40B2H 2 bytes | Top of Memory The end of the checksum (52B5H). |
| 40B3H-40B4H 2 bytes | Temporary Pointer The next free string temporary descriptor (53B0H, 53C8H). |
| 40D3H-40D5H 3 bytes | DSCTMP The descriptor work area (53C2H). |
| 40FDH-40FEH 2 bytes | STREND The end of the arrays (523AH). |
| 4121H-4122H 2 bytes | REG 1 A string result's descriptor address (53B4H, 5408H). |
DOS Addresses
| Address Size | Contents |
|---|---|
| 4225H-4274H 80 bytes | Command Buffer The CMD string (up to 79 characters), ended by 0DH (526BH; 4226H is the second character). |
| 428AH 1 byte | Overlay Flags Bit 7 MINI-DOS, set at 520FH and cleared at 5217H. |
| 4300H-43FFH 256 bytes | Sector Buffer 43FCH is the temporary stack at 527FH. |
BASIC/CMD Addresses
| Address Size | Contents |
|---|---|
| 5700H-5701H 2 bytes | Mode and Flags Of the file area's header copy, stored at 55CDH. |
| 5702H-5703H 2 bytes | Record Length Stored at 55C9H. |
| 5711H 1 byte | FCB Buffer High Byte FCB + 4; incremented at 5570H for a record buffer. |
| 5716H 1 byte | FCB Record Length FCB + 9; set to 01H at 5691H to give back one character. |
| 649FH 1 byte | File Area Size High byte of 012DH or 022DH: 02H gives room for a record buffer (5573H). |
Operands Changed at Run Time
| Address Size | Contents |
|---|---|
| 5272H-5273H 2 bytes | Copy Start Operand of 5271H, stored at 5236H. |
| 5275H-5276H 2 bytes | Saved Area Start Operand of 5274H (5200H), read at 5245H. |
| 5278H-5279H 2 bytes | Saved Area Length Operand of 5277H (1F00H), read at 522FH. |
| 5290H-5291H 2 bytes | BASIC Stack Operand of 528FH, stored at 5224H. |
| 52C9H-52CAH 2 bytes | Checksum Window Operand of 52C8H, stored at 522CH, read at 529AH and 52A7H. |
| 5386H-5387H 2 bytes | Text Pointer Operand of 5385H: the DEF's text (5366H) or the call's (53AAH, read at 53E9H). |
Outside Routines and Tables
| Where | Addresses |
|---|---|
| ROM | 0361H (INLIN), 07B2H (OVERR), 0A7FH (CINT), 0A9AH, 0AF4H, 0E6CH (FIN), 1936H (FNDFOR), 197AH (OMERR), 1997H (SNERR), 199DH (NFERR), 1D25H (NEWSTT), 1DBEH, 1E4AH (FCERR), 1EEAH, 1F2BH and 1F33H (LET), 2169H (FINPRT), 21CDH, 2243H, 2335H (FRMPRN), 2337H (FRMEVL), 260DH (PTRGET), 27F8H, 2819H, 2828H (ERRDIR), 2843H, 2868H (STRLIT), 2888H, 29C2H, 29D7H (FRESTR), 29DDH, 29F5H (FRETMS), 2B1CH (GETBYT), 2B1FH (CONINT); RST 08H, RST 10H, RST 18H, RST 20H. |
| SYS0/SYS | 4405H (enter DOS), 4409H (error exit), 4416H (keep the drives turning), 4419H (DOS-CALL), 4445H (back one record). |
| BASIC/CMD | 5824H and 5831H (function names), 5CB7H (copy), 5CC4H, 5DA0H, 5DA9H, 5DAFH, 5DC7H, 5DCAH, 5DD6H (errors), 5DEFH (DOS error), 5E7BH (string variable), 5F36H, 6087H (open), 60F2H (read a byte), 6190H, 621EH, 62C0H, 6368H, 6382H. |
| BASIC/CMD table | 592BH, the CMD"F=" table: length, name and address per entry, 00H at the end (52EDH). |
Disassembly
5200H - Load Entry
BASIC/CMD loads SYS20/SYS through its overlay loader at 576CH with RST 28H code 36H (function 1 of directory slot 16H) 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, 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's CMD link 57ECH has evaluated the string, pushed its text pointer (57EFH), copied the string in upper case to SYS0/SYS's command buffer at 4225H (ending with 0DH) and pushed its length count at 57A4H; Register Pair HL holds 4225H. 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 592BH); 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/SYS. 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 (4225H) and Register Pair HL at the = (4226H); 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 592BH, 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 592BH 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 5824H) 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 5795H 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 6087H: 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, 649FH = 2). The mode byte (5700H): bit 7 random, 6 writable, 5 readable, 3 set by the types U and F (and by every mode letter), 2 fixed-length records, 1 first letter F, 0 first letter M; the open flags (5701H after AND F8H): bit 7 the file may be extended, bit 2 it is emptied, bit 1 it starts at its end, bit 0 (open only) an existing file only. 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 at 222DH for each item it reads. BASIC 6382H 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 60F2H (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 line feeds, and a comma 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 (one right after a line feed does not), and 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/SYS 4445H and an LRL of 1). The end of the file before the item starts is error 7CH INPUT PAST END; inside the item it ends the item (56ABH). 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.