TRS-80 DOS - NEWDOS/80 v2.0 for the Model III - SYS10/SYS Disassembled
Page Customization
Page Index
SYS10/SYS
Other Navigation
Introduction/Summary
NEWDOS/80 v2.0 SYS10/SYS Disassembly - GET and PUT (Model III)
SYS10/SYS carries out the Disk BASIC statements GET and PUT. It loads 4D00H-51E7H in five load records (transfer address 4D00H); the code ends at 51CDH and 51CEH-51E7H are 26 bytes of 00H. BASIC/CMD loads it with LD A,2CH / RST 28H at 610AH: the SYS0/SYS dispatcher calls 4D00H, which drops the dispatcher's return address so that the RET goes straight back to BASIC, and BASIC then jumps to 4D03H (from 6107H). Before that BASIC has pushed Register Pair AF (the Z FLAG set for GET, clear for PUT), read the file number and copied the file area's 2DH-byte header and FCB to the work area 5700H-572CH (Index Register IX = 5700H).
4D03H first sets BASIC's reload flag (the operand 6226H) to 01H, so that BASIC loads SYS10/SYS again after any DOS call it makes for the statement, then marks the mode byte at 5700H with bit 4 for a PUT and reads the position parameter. The file is positioned through BASIC's helpers (which call SYS0/SYS 444EH) and the record is moved: a plain random file moves one record between the file and its record buffer, an item file moves a list of variables or expressions. The statement ends through BASIC 641EH, which copies the work area back to the file area. SYS10/SYS does almost everything through BASIC/CMD's routines 5C9CH-662CH; every call names what the routine does.
The page shows every byte of the file once, in address order.
The Position Parameter
GET f [,position] [,item list] and PUT f [,position] [,item list]. Without a position (or with an empty one, two commas) the file's current position NEXT is used until a record start is known (5701H bit 6). After that a file with fixed-length records goes on to the next record (the record start plus the record length), type MU skips to the next record's 70H marker, and type MI continues where the last GET or PUT ended (4D20H-4D33H).
| Position | Meaning |
|---|---|
| n | A record number, 1 or more: the byte position is (n - 1) x the record length (4E5FH-4E97H). Only files with fixed-length records (mode bit 2). |
| multiplication sign | For an item file with the second letter U or F and a known record start: continue where the last GET or PUT ended (5704H-5706H), inside the record. Type MI, or no record start yet, as without a position; a plain random file is error A6H (4D5CH-4D73H). |
| # | The last record start again (5707H-5709H, 4D75H). |
| $ | Where the last statement started (570AH-570CH, 4D81H). |
| % | No file access: each string variable of the item list is cut or padded with spaces to its length prefix (4D93H, 501CH). |
| & and && | Write the sector buffer if it was changed; && also writes the end of file into the directory through SYS0/SYS 4451H (4DA2H). |
| !n, !$n, !#n, !%, !$% | A byte position: !n gets or puts there, !$n only positions the file, !#n sets the end of file to n (the file must be writable), !% and !$% use the end of file as the position. With fixed-length records the byte position must be a multiple of the record length (4DBCH-4E46H). |
A bad position value (a string, a negative number, a value of 224 or more, a byte position inside a record) is error A6H BAD FILE POSITIONING PARAM; a record number of 0 or one whose position does not fit in 24 bits is 7EH BAD RECORD #.
Item Files
The mode byte at 5700H holds the file's type from OPEN: bit 7 random, bit 6 may be written, bit 5 may be read, bit 4 this statement is a PUT (set by SYS10/SYS), bit 3 the second letter U or F, bit 2 fixed-length records, bit 1 the letter F, bit 0 the letter M. The item file types are MI (01H), MU (09H), MF (0DH), FI and FF. A type M file stores every value with a marker byte: 72H an integer (2 bytes), 73H single precision (4 bytes), 74H double precision (8 bytes), 80H + n a string of n characters (below 128), 71H n a longer string, 00H a filler byte and 70H the start of a record (type MU). A type F file stores the raw bytes of each value, a string as exactly its length prefix in characters.
The item list follows the position: either the number of a program line that holds the list, or a second comma and the list in the statement. Items are separated by commas and the list may end with a semicolon. An item may start with a length prefix (n), 0-255, and # or $ items skip or write n bytes. Before a PUT into an existing record of a type M file, or into a type F file, the list is run once with bit 2 of 572DH set to count the bytes (BASIC 61C8H then writes nothing), so that a list that does not fit is error 8EH RECORD OVERFLOW before anything is written (4F3DH-4F87H).
Variables
ROM Addresses
| Address Size | Contents |
|---|---|
| 40AFH 1 byte | Value Type 02H integer, 03H string, 04H single, 08H double precision; set to an item's type at 5086H, tested through RST 20H. |
| 40D6H-40D7H 2 bytes | FRETOP The bottom of the string space in use: a string above it is in the string space, one below it is a literal in the program (5036H, 50A6H). |
| 40DFH-40E0H 2 bytes | TEMP Where a numeric value was read, stored at 50D1H before the ROM's LET code at 1F33H stores it into the variable. |
| 411DH-4124H 8 bytes | Double Precision REG 1 A double precision value is read to and written from 411DH (50CBH, 5169H). |
| 4121H-4124H 4 bytes | REG 1 An integer (4121H-4122H) or single precision value; 4123H the high mantissa byte (bit 7 the sign) and 4124H the exponent (4DE6H, 4DEAH, 50BFH, 5164H). |
DOS Addresses
| Address Size | Contents |
|---|---|
| 4451H 3 bytes | Write End of File SYS0/SYS vector, called through BASIC 621EH for the && position (4DB3H). |
The Work Area (BASIC/CMD 5700H-572DH)
| Address Size | Contents |
|---|---|
| 5700H 1 byte | Mode Byte IX+00H. Bit 7 random, 6 writable, 5 readable, 4 PUT (4D0DH-4D13H), 3 second letter U or F, 2 fixed-length records, 1 letter F, 0 letter M. The % position stores A2H (4D97H). |
| 5701H 1 byte | Second Mode Byte IX+01H. Bit 7 the file may be extended (4EE9H, 4F61H), bit 6 a record start is known (4D23H, 4D64H; cleared by !$ at 4E30H). |
| 5702H-5703H 2 bytes | Record Length 1-256 (4E74H, 4ED0H, 4F11H). |
| 5704H-5706H 3 bytes | Last End Where the last GET or PUT ended (BASIC 6110H, 610DH, 6122H; 4F70H reads the low 16 bits). |
| 5707H-5709H 3 bytes | Record Start Stored by BASIC 6117H (4D39H, 4E5AH), read by 6129H. |
| 570AH-570CH 3 bytes | Statement Start Where this statement started (4D4BH, 4D4EH), read back by the $ position (4D85H, 4D88H). |
| 570DH-572CH 32 bytes | FCB The file's FCB: 570EH (FCB+1) bit 4 buffer changed (4DA6H), 5710H-5711H (FCB+3) the sector buffer (4F0EH), NEXT 5712H and 5717H-5718H, EOF 5715H and 5719H-571AH. |
| 572DH 1 byte | Statement Flags IX+2DH. Bit 1 the list is in another line (4F2EH), bit 2 counting run (4F7CH, 4F87H), bit 3 the record runs to the end of file (4F5DH), bit 4 the position is at or past the end of file (BASIC 615EH), bit 5 the % position (4D9BH), bit 6 the item has a length prefix (4FE0H, 4FFAH). |
Operands Changed at Run Time
| Address Size | Contents |
|---|---|
| 4F8CH-4F8DH 2 bytes | Room in the Record Operand of LD DE,nnnn at 4F8BH: stored at 4F1BH (from BASIC 6331H) and 4F77H (the existing record's length), copied to 61CAH at 4F8EH. |
| 5094H 1 byte | Length Prefix Operand of LD A,nn at 5093H: the item's prefix n or FFH for none (500CH); BASIC 6136H and 62D8H read it. |
| 5D38H-5D39H 2 bytes | Item Number Operand of BASIC's LD DE,nnnn at 5D37H, used in its error messages (4F95H, 5193H). |
| 61CAH-61CBH 2 bytes | Room Counter Operand of BASIC's LD HL,nnnn at 61C9H, lowered by every item written (4F8EH). |
| 6226H 1 byte | Reload Flag Operand of BASIC's LD A,nn at 6225H: 01H makes BASIC reload SYS10/SYS after a DOS call (4D05H). |
Outside Routines
| Where | Addresses |
|---|---|
| ROM | 09D6H (copy a string), 0A7FH (CINT), 0AF6H (TYPE MISMATCH), 1E5AH (LINGET), 1EC5H (find a line), 1F33H (LET), 260DH (PTRGET), 29E3H (inside FREFAC); RST 10H, RST 18H, RST 20H. |
| BASIC/CMD | 5C9CH, 5CACH, 5CBCH, 5D9DH, 5DA9H, 5DB2H, 5DBEH, 5DC1H, 5DCDH, 5DD0H, 5DD3H, 5DDCH (errors), 5EE1H, 6031H, 603EH, 60EBH, 610DH, 6110H, 6117H, 6122H, 6129H, 612FH, 6136H, 614CH, 615EH, 6190H, 619CH, 61A3H, 61A6H, 61ACH, 61B3H, 61C8H, 61DFH, 620FH, 6214H, 621EH, 6232H, 6237H, 6245H, 6246H, 6258H, 626CH, 62C7H, 62CEH, 62D0H, 62D8H, 62FFH, 6331H, 6346H, 635AH, 6362H, 6368H, 641EH, 661CH, 6623H, 662CH. |
| Entries from BASIC/CMD | 4D03H (from 6107H), 4DE4H (from 6629H), 4E17H (from 6620H). |
Disassembly
4D00H - Load Entry
BASIC loads SYS10/SYS with LD A,2CH / RST 28H (BASIC 610AH). The SYS0/SYS dispatcher (4BC2H) has already dropped the RST's own return address and calls 4D00H with the return to 4BC5H on top of the stack. SYS10/SYS discards that word, so the RET goes straight back to the caller of 610AH: BASIC then jumps to 4D03H (from 6107H), or simply carries on when 610AH only reloaded SYS10/SYS after a DOS call. Because 4BC5H is skipped, 4289H bit 6 stays set; BASIC clears it at the end of the statement (643AH).
4D03H - GET and PUT
Entered by JP 4D03H at BASIC 6107H. BASIC's GET (60FFH, vector 417FH) and PUT (60FEH, vector 4182H) push Register Pair AF with the Z FLAG set for GET and clear for PUT, read the file number through 5F53H, copy the file area's 2DH-byte header to 5700H-572CH (Index Register IX = 5700H; 570DH-572CH is the file's FCB) and clear the statement flags at 572DH (IX+2DH). Register Pair HL is the BASIC text pointer after the file number. The statement is GET f / PUT f, optionally followed by a position (a record number, or one of the characters * # $ % & !) and an item list (see 4F18H).
Store Register A (01H) at 6226H, the operand of BASIC's LD A,nn at 6225H: from now on BASIC reloads SYS10/SYS (through 610AH) after every DOS call it makes, since a DOS call may bring another overlay into 4D00H.
4D5AH - The Position Characters
Register A holds the first character of the position parameter and Register Pair HL points at it. The multiplication sign (token CFH) continues at the position where the last GET or PUT ended, # uses the last record start again, $ the position where the last statement started, % formats string variables to their item lengths without any file access, & writes the buffer (&& also the end of file), ! takes a byte position. Anything else is a record number (4E5FH).
4DE4H - Convert the Position Value
Entered by JP 4DE4H at BASIC 6629H, after 6190H has evaluated an expression (the Z FLAG set if it is a string) and left the text pointer on the stack. Returns the value as a 24-bit number in Register C (low), Register L and Register H (high), with any fraction dropped. A string, a negative value or a value of 224 or more gives error A6H BAD FILE POSITIONING PARAM.
SHIFT OUT THE FRACTION
Register H / L / C = the mantissa, Register A counts up from (exponent - 98H) to 0.
4E17H - Apply the ! Position
Entered by JP 4E17H at BASIC 6620H with the position in Register C, Register L and Register H (Register Pair HL also pushed). The stack holds, from the top, Register Pair HL, the text pointer and the kind pushed at 4DE0H (0 = !, 1 = !$, 2 = !#). 4E37H comes here too with the end of file as the position.
4E48H - Type MU: Skip to the Next Record
Reached from 4D30H for a type MU file (records of marked items, each starting with a 70H byte) when a record start is known and no position was given. Register C and Register Pair HL hold the position where the last statement ended. A PUT carries on from there; a GET skips the rest of the current record, up to the next 70H byte.
FIND THE NEXT RECORD
Register C and Register Pair HL = the position of the marker about to be read.
4E5FH - A Record Number
The position parameter is an expression: a record number, 1 or more. The byte position is (number - 1) times the record length. Only files with fixed-length records (mode bit 2) accept it.
MULTIPLY LOOP
Register Pair HL, Register D, Register E and Register A shift right together as one 40-bit value; each 1 bit shifted out of Register A adds Register Pair BC, the record length from 5702H, to Register Pair HL.
4E9AH - Type MU: the Record Marker
For type MU every record starts with a 70H byte. Register C and Register Pair HL hold the position.
4EBEH - Transfer a Plain Record
The file is positioned. Item files (types with the letter M or F) go to the item list at 4F18H. A plain random file moves one record between the file and its record buffer (the FIELD buffer, see 4F0EH): a whole sector for a record length of 256, or the record in record mode (FCB+1 bit 7, LRL = the length) otherwise.
4F0EH - The Record Buffer
Returns Register Pair HL = the record buffer of the file. The FCB's buffer address (5710H-5711H) is the sector buffer; a file with a record length that is not a multiple of 256 has its record buffer in the 256 bytes before it. Register A = the low byte of the record length, with the Z FLAG set if it is 0.
4F18H - The Item List (IGEL)
Item files (types MI, MU, MF, FI, FF from OPEN's fourth parameter) move the values of a list of variables or expressions. The list follows a comma after the position: either the number of the program line that holds it, or a second comma and the list in the statement itself. Items are separated by commas and the list ends with a semicolon; a list may run on over several program lines, and ' comments are skipped. Type F files hold the values as bare bytes (a string takes the length given by a (n) prefix); type M files put a marker before each value (72H integer, 73H single, 74H double, 80H + n or 71H n for a string, 00H filler, 70H end of record). The available room in the record is counted in BASIC's 61CAH; a PUT to types MU, MF, FI and FF first runs the whole list without writing (572DH bit 2) to count it.
Store Register Pair HL (the room left in the record, returned by BASIC 6331H) at 4F8CH, the operand of LD DE,nnnn at 4F8BH.
MEASURE THE EXISTING RECORD
Register C and Register Pair HL = the file's position as each item of the old record is skipped.
Store Register Pair HL (the record's length) at 4F8CH, the operand of 4F8BH: the new record must fit into it.
Load Register Pair DE with the room in the record, the operand 4F8CH (0000H in the file, stored at 4F1BH and 4F77H).
Store Register Pair DE (the room) at 61CAH, BASIC's room counter (the operand of LD HL,nnnn at 61C9H).
ITEM LOOP
Register Pair HL = the text pointer, Register Pair DE = the item number (kept at BASIC 5D38H for error messages).
Store Register Pair DE (the item number) at 5D38H, the operand of LD DE,nnnn at BASIC 5D37H.
4FC1H - Next Character of the List
RST 10H with two extensions: at the end of a program line the list continues with the next line, and a ' comment (a colon followed by the REM token 93H) skips the rest of the line. A list that runs off the end of the program is error 9AH IGEL SYNTAX ERROR.
SKIP THE COMMENT
Register Pair HL steps to the line's 00H end.
4FDFH - One Item: the (n) Prefix
Register Pair HL points at the item and Register A holds its first character. An item may start with a length in parentheses, (n) with n = 0 to 255, stored at 5094H (FFH when there is none). A parenthesised expression that is followed by a comma, a semicolon or the end is taken as the item itself.
Store Register A (the length prefix, FFH = none) at 5094H, the operand of 5093H (BASIC's 6136H and 62DDH read it there too).
501CH - GET from a Type F File
Each item is a variable (its bytes are read raw, a string takes exactly n bytes), or (n)# / (n)$ to skip n bytes. With the % position (572DH bit 5) no file is read: each string variable is cut or padded with spaces to its length prefix. Register Pair HL = the variable's address, Register C = the prefix, Register A = 00H or the # / $ character.
506AH - GET from a Type M File
Register Pair HL = the item. Each item is # (skip an item, needs a prefix), or a variable. The file's marker decides the value's type: a numeric value is stored through the ROM's LET code (so it is converted to the variable's type), a string needs a string variable and is cut to the length prefix if one is given.
READ THE MARKER
00H filler bytes are skipped; the 70H byte ends the record.
Load Register A with the length prefix, the operand 5094H (00H in the file, stored at 500CH; FFH = none).
50F6H - PUT an Item
For a type F file an item is a variable, (n)# (write n 00H bytes) or (n)$ (keep the n bytes in the file; at the end of file write n 00H bytes). Numbers go out as their raw bytes, a string as exactly n characters, padded with spaces. For a type M file see 5144H. Every write goes through BASIC 61C8H, which writes Register A and then Register B bytes from Register Pair HL, counting B + 1 against the room in the record (error 8EH RECORD OVERFLOW) and only counting while 572DH bit 2 is set.
WRITE n ZERO BYTES
Register C counts the bytes left plus 1.
PAD WITH SPACES
Register H counts up from minus the spaces to 0.
5144H - PUT to a Type M File
Register Pair HL = the item. Each item is an expression (evaluated through BASIC 6190H), or (n)# for a string item of n 00H bytes. A number is written as its marker (72H, 73H or 74H) and its bytes; a string as 80H + length (or 71H and the length for 128 or more) and its characters, cut to the prefix n if one is given.
518EH - After an Item
The text pointer is on the stack. A comma takes the next item; a semicolon ends the list, and nothing may follow it.
51B0H - End the Statement
Register Pair HL = the text pointer. Store where the statement ended as the new position of the last GET or PUT, pad a written item record where needed, copy the work area back to the file area and return to BASIC.
51CEH - Unused Bytes
The rest of the file.