TRS-80 DOS - NEWDOS/80 v2.0 for the Model I - SYS12/SYS Disassembled
Page Customization
Page Index
SYS12/SYS
Other Navigation
Introduction/Summary
NEWDOS/80 v2.0 SYS12/SYS Disassembly - BASIC REF (Model I)
SYS12/SYS is the BASIC command REF, a cross reference of line numbers, variable names and text in the program. It loads into the overlay area at 4D00H-51D2H (1,235 bytes in five load records, transfer address 4D00H) and is called through RST 28H by BASIC's direct statement code in SYS18 (555DH), with BASIC's end of statement (6445H) as the return address. Because it stays in the overlay area until another overlay is loaded, a plain REF can continue the last search. The work areas 51D3H-51EBH lie after the file.
The page shows every byte of the file once, in address order. Calls into BASIC/CMD (5700H up) are linked only where the BASIC page has a row with the right bytes at that address.
REF Parameters (from the code)
| Form | What it does |
|---|---|
| REF | Lists the next line after the last one shown that holds the last item looked for (mode 3). SYNTAX ERROR if there is none; TEXT END when no further line holds it. |
| REF @n | The same, from line n on. |
| REF name / REF number | Every line that uses the variable name (1 or 2 characters, in all its forms: alone, with $ % ! #, and as an array) or the number (up to 5 digits; any number in the text counts, leading zeros ignored) (mode 2). |
| REF "text / REF =text | Every line holding the up to 16 bytes that follow the quote or the = (as they stand in the command line, so after = the text is tokenized) (mode 2). |
| REF * / REF $ | All line numbers used in the text, in numerical order, then all variable names in alphabetical order, each with its lines (modes 0 and 1). REF *name / REF $name start at that item. BREAK pauses, ENTER continues, the up arrow key stops. |
When the character after REF is $, the output also goes to the printer (BASIC 5D6CH). Each line is shown as its number, followed by / or ( (array) and the type character when the item is used in that form, and by a count when it is used more than once.
Bug in the file: REF @n with n above the last program line ends at 4F2BH with a line address left on the stack (4F2BH).
Variables and Patched Code
Locations inside SYS12 whose contents change while it runs:
| Address Range | Purpose |
|---|---|
| 4E0CH 1 byte | The mode: 0 find the next item, 1 report it (full report), 2 report one item, 3 find and list the next line (operand of 4E0BH; written at 4DD1H). |
| 4E76H-4E77H 2 bytes | The number of the line being scanned or last shown; FFFFH = start at the top (operand of 4E75H; written at 4D1DH, 4E17H, 50E7H). |
| 4E7AH-4E7BH 2 bytes | The address of the line being scanned (operand of 4E79H; written at 4F70H). |
| 4ED9H-4EDAH 2 bytes | The count of one counter while it is printed (operand of 4ED8H; written at 4E9CH). |
| 4EEFH-4EF0H 2 bytes | The end of the list of up to 32 line addresses at 4200H-423FH (operand of 4EEEH; written at 512AH, 5182H). |
| 4EF2H-4EF3H 2 bytes | The list's next entry (operand of 4EF1H; written at 4E6DH, 5185H). |
| 4F6DH 1 byte | CAH (JP Z) or C3H (JP) after a match: the line is reported at its end (written at 4DF0H, 50DDH). |
| 4F7CH 1 byte | 21H (LD HL, no effect) or C3H: JP 512FH for a text search (written at 4D44H, 4D4DH). |
| 4FBEH 1 byte | 30H (JR NC, never taken) when the item is a number, 18H (JR, skip numbers) otherwise (written at 4DEBH). |
| 4FFCH, 50A9H 1 byte each | DAH (JP C, mode 0) or C2H (JP NZ, other modes): the comparison of numbers and of names (written at 4DDAH, 4DDDH). |
| 5021H 1 byte | 38H (JR C) or 18H (JR): how a number compares with the best item so far (written at 517CH). |
| 5085H-5086H 2 bytes | Where the last FIELD token is, so FIELD ... AS name counts the name and not AS (operand of 5084H; written at 4FB4H, cleared at 4DF6H). |
| 51BFH-51D2H 20 bytes | The item compared, the best item found, the number collected and the first counters (see 51B2H). |
Locations outside SYS12 that it reads or writes:
| Address Range | Purpose |
|---|---|
| 3840H 1 byte | Keyboard row 6: ENTER (bit 0), BREAK (bit 2), up arrow (bit 3). |
| 4020H 1 byte | Low byte of the ROM's cursor address: the output column (51A1H). |
| 40A4H-40A5H 2 bytes | The ROM's pointer to the first program line. |
| 4200H-423FH 64 bytes | The DOS sector buffer, used as the list of up to 32 line addresses. |
| 51D3H-51EBH 25 bytes | After the file: the remaining counters (51D3H-51DAH) and the search text (51DBH-51EBH). |
| 5D6CH 1 byte | In BASIC/CMD: $ here sends REF's output to the printer too (written at 4D04H). |
Disassembly
4D00H - REF: Read the Parameter
SYS12 is called through RST 28H by BASIC's direct statement code (SYS18 555DH) with Register Pair HL = the text after REF and the return address 6445H (BASIC's end of statement) on the stack. It stays in the overlay area afterwards, so a plain REF can go on from where the last one stopped as long as no other overlay has been loaded. Forms, from the code: REF (the next line holding the last item, listed), REF @n (the same from line n on), REF name or REF number (every line that uses it), REF "text or REF =text (every line holding the text), REF * / REF $ (every line number and variable name of the program, in order; *name / $name start at that name). A $ right after REF also sends the output to the printer.
Store Register Pair DE at 4E76H, the operand of the LD HL at 4E75H: the last line shown, the search starts after it.
COPY THE SEARCH TEXT
Register Pair DE = the command line, Register Pair HL = the buffer, Register B = the bytes left.
Store Register A (C3H) at 4F7CH: the LD HL,512FH there becomes JP 512FH, so every byte of the text is compared with the search text.
Store Register A (21H) at 4F7CH, putting back the LD HL,512FH there (no text search).
COPY THE ITEM
Register Pair DE = the command line, Register Pair HL = the buffer, Register B counts down from 6.
4DB0H - The Full Report: the Next Item
Each round of REF * or REF $ first scans the whole program for the smallest line number or name above the last one reported (mode 0), keeping the addresses of up to 32 lines that use it in the DOS sector buffer at 4200H; then it reports that item (mode 1). Line numbers come before names. Holding BREAK pauses between items (ENTER goes on), the up arrow key stops.
PAUSE
Register Pair HL = 3840H; the loop waits for ENTER (go on) or the up arrow (stop).
Store Register A (the mode) at 4E0CH, the operand of the LD A,00H at 4E0BH.
Store Register A at 4FFCH: mode 0 looks for items above 51BFH (JP C skips smaller ones), the other modes for the same item (JP NZ skips others).
Store Register A at 50A9H, the same test for names.
Store Register A at 4FBEH, the opcode of the number test there.
Store Register A at 4F6DH, putting back the JP Z,4DFCH there: no match in the line yet.
Store Register Pair HL (0000H) at 5085H, the operand of 5084H: no FIELD seen yet.
4DFCH - End of a Line
Reached through the JP at 4F6DH at the end of each line, with Register Pair DE at the line's 00H end. If the line had a match (4F6DH was made a JP), its references are reported (4E80H); otherwise the scan goes on with the next line.
The end of the program: load Register A with the mode; the operand 4E0CH (00H in the file) is stored at 4DD1H.
Store Register Pair HL (FFFFH) at 4E76H, the last line shown: a plain REF starts at the top again.
Store Register Pair HL (the next entry) at 4EF2H, the operand of the LD HL at 4EF1H.
Load Register Pair HL with the line's number; the operand 4E76H (0000H in the file) is stored at 50E7H, 4D1DH and 4E17H.
Load Register Pair HL with the line's address; the operand 4E7AH (0000H in the file) is stored at 4F70H.
4E80H - Report a Line
Prints the line's number once for every kind of use found in the line: the name alone, with $ % ! # (the type characters at 51B2H-51B5H), and each of these as an array (followed by an opening parenthesis, shown with ( instead of /), with the count when it is used more than once. A line-number item or a text search has only the first counter. Register Pair DE is the text pointer at the line's end.
COUNTER LOOP
Register Pair HL = the counter, Register C = its number (0-9), Register B = the counters left.
Store Register A (the count) at 4ED9H, the operand of the LD DE at 4ED8H.
Load Register Pair DE with the count; the operand 4ED9H (0000H in the file) is stored at 4E9CH (its high byte stays 00H).
Load Register Pair BC with the end of the line list; the operand 4EEFH (0000H in the file) is stored at 512AH and 5182H.
Load Register Pair HL with the next entry of the list; the operand 4EF2H (0000H in the file) is stored at 4E6DH and 5185H.
4F07H - Plain REF and REF @n
Finds the first line after the last one shown (or from line n on) that holds the remembered item, in mode 3, and lists it.
FIND THE LINE AFTER THE LAST ONE SHOWN
Register Pair HL = the line, Register Pair BC = the last line shown.
4F46H - Scan the Text
Register Pair DE walks through the program's text. Strings, REM and ' comments, DATA, constants after & and decimal fractions are skipped; line numbers (digit strings) and variable names are collected and compared with the item. A match counts in the counters at 51D1H-51DAH and turns the JP Z,4DFCH at 4F6DH into JP 4DFCH, so the line is reported at its end.
SKIP A STRING
Register Pair DE steps through the string; Register B = the closing quote.
SKIP DATA
Register Pair DE steps through the DATA statement to its colon or the line's end.
SKIP A REMARK
REM or ': Register Pair DE steps to the line's 00H end.
If the Z FLAG is set, JUMP to 4DFCH, which ends the line or the program. The opcode 4F6DH is CAH (JP Z) or, after a match in the line, C3H (JP, always to 4DFCH); set at 4DF0H and 50DDH.
Store Register Pair DE (the line's address) at 4E7AH, the operand of the LD HL at 4E79H.
BYTE LOOP
Register Pair DE = the byte of the line being looked at.
Load Register Pair HL with 512FH, which does nothing here; for a text search the opcode 4F7CH is C3H and this is JP 512FH, comparing every byte with the search text (set at 4D44H and 4D4DH).
Store Register Pair DE (where the FIELD token is) at 5085H, the operand of 5084H, so FIELD ... AS name counts the name and not AS.
A digit: JR NC to 4FE1H is never taken here (the CARRY FLAG is set). With opcode 18H at 4FBEH, set at 4DEBH when the item is not a number, it is a JUMP to 4FE1H that skips every number.
COLLECT THE DIGITS
Register Pair HL = the buffer, Register B counts down the room left.
SKIP DIGITS
Register Pair DE steps over the remaining digits.
JUMP to 4F78H (skip this number) under the condition set at 4DDAH: JP C (DAH, mode 0: a shorter number is smaller) or JP NZ (C2H, other modes: a different length is another number).
The opcode 5021H, set at 517CH, decides: JR C,5037H (38H) when the best item so far is a number (JUMP to 5037H if this one is smaller), or JR 5037H (18H) when it is a name (always JUMP, as any number comes first).
SKIP HEXADECIMAL DIGITS
Register Pair DE steps over 0-9 and A-F.
Load Register Pair DE with the position of the last FIELD token; the operand 5085H (0000H in the file) is stored at 4FB4H and cleared at 4DF6H.
SKIP THE REST OF THE NAME
Only the first two characters count, as in the ROM.
JUMP to 4F78H (skip this name) under the condition set at 4DDDH: JP C (mode 0: smaller names are skipped) or JP NZ (other modes: other names are skipped).
FIND THE TYPE
Index Register IY steps back through # ! % $; Register Pair HL through their counters.
Store C3H (JP) at Register Pair HL, 4F6DH: this line is reported at its end.
Store Register Pair BC (the line's number) at 4E76H, the operand of 4E75H.
5101H - Remember the Line
Adds this line's address to the list at 4200H-423FH (32 lines) unless the list is full or the line is already its last entry.
Store Register Pair HL at 4EEFH, the end of the list (the operand of 4EEEH).
512FH - Text Search
Reached through JP 512FH at 4F7CH with Register A = the current byte of the line. Compares the bytes from there with the search text at 51DBH until its 00H end; a match counts in 51D1H and the scan goes on after it.
COMPARE LOOP
Register Pair DE steps through the line, Register Pair HL through the search text.
514BH - Small Helpers
514BH: the next byte of the line in Register A, skipping spaces, 09H and 0AH. 515AH: CARRY if Register A is not a letter or digit; 5161H: CARRY if it is not a letter. 5168H/516EH: store the best item's first two characters (Register Pair BC) and length byte, and empty the line list; 5171H: set 5021H for the kind of item.
Store Register A at 5021H, the opcode of the best-number test.
Store Register Pair HL at 4EEFH: the list's end is its start, the list is empty.
Store Register Pair HL at 4EF2H, the list's next entry.
5189H - Compare Characters
Compares Register C characters at 51CCH with those at Index Register IY. The Z FLAG is set if they are all equal (or Register C is 0).
COMPARE LOOP
Register Pair HL and Index Register IY step through the two strings; Register B counts.
519BH - Position the Output
519EH prints a space; if the column is 53 or more it starts a new line, and at the start of a line it indents to column 7 (past the item's name).
51B2H - Type Characters and Work Areas
The rest of the file: the type characters, the TEXT END message and the work areas (all zero in the file). After the file (not loaded): 51D3H-51DAH the remaining counters and 51DBH-51EBH the search text.