TRS-80 DOS - NEWDOS/80 v2.0 for the Model III - SYS11/SYS Disassembled
Page Customization
Page Index
SYS11/SYS
Other Navigation
Introduction/Summary
NEWDOS/80 v2.0 SYS11/SYS Disassembly - RENUM, Second Part (Model III)
SYS11/SYS carries out the second part of the Disk BASIC command RENUM. It loads 4D0CH-51F3H in five load records (transfer address 4D0CH); the code ends at 51A1H and 51A2H-51F3H are 82 bytes of 00H. SYS13/SYS does the first part: it reads the command's numbers and the options U and X into its own bytes 4D00H-4D0BH, writes each line's new number into the line's link field (lines outside the range get their own number), counts the lines and loads SYS11/SYS with LD A,2DH / RST 28H. Because SYS11/SYS does not load 4D00H-4D0BH, those parameters stay in memory for it.
SYS11/SYS never returns to its caller: it ends by jumping to the ROM at 1AE9H (the links are rebuilt and BASIC goes back to its command level), to BASIC/CMD 5DE2H with an error code, or to SYS0/SYS 4030H after Fatal Error.
The page shows every byte of the file once, in address order.
How RENUM Works
- Line table (4D0CH). The address of every Register C-th line goes into the 128 word entries at 64A3H-65A2H (BASIC/CMD's initialization code, used as the input buffer). The line search (4EC3H) does a binary search over the table and then walks the lines, comparing old line numbers; it returns the line's new number from its link field.
- Order check (5073H). The renumbered lines (the block) must fit between the lines around the place their new numbers belong, else error 8CH SEQ # OVERFLOW before anything is changed.
- First pass (4D28H). Every line number referred to after GOTO, GOSUB, THEN, ELSE, RUN, RESUME, ON ... GOTO/GOSUB lists, ON ERROR GOTO, ERL with a comparison, LIST, LLIST and the item list line of GET and PUT is looked up (token table 4E8AH). Strings, DATA and REM are passed. A reference that cannot be renumbered is listed under Error Lines as number/letter: X a line number was expected, S a number out of range (above 65529, or 0 where only RESUME 0 and ON ERROR GOTO 0 may stand), U a line that does not exist (with option X only inside the range). The change in the number of digits is added up (5153H) and its largest value kept.
- Stop or move. With option U, or after any error, RENUM stops: the program is unchanged. Otherwise the program moves up by its largest growth plus 256 bytes (OUT OF MEMORY if it does not fit under the top of memory less 256), the stack moves to the top of memory and the line table moves with the program.
- Second pass. The program is copied back down from its moved copy with every reference written as the new number (5120H copies each byte; 4E4CH writes the digits). An error now ends with Fatal Error. Text Now Bad and the DOS.
- Placing the block (4FFDH). The block is moved to the end of the program and then inserted at its place, a piece at a time through the free memory (50F1H). The new numbers are copied from the link fields into the line number fields, Done is shown and the ROM rebuilds the links (1AE9H).
Variables
ROM Addresses
| Address Size | Contents |
|---|---|
| 4020H-4021H 2 bytes | Cursor Address The ROM's cursor in the video memory: read for its column at 4F70H, used as the destination of the digits at 4F7AH and moved past them at 4F81H. |
| 40A4H-40A5H 2 bytes | TXTTAB The first program line (4D28H, 4FAEH, 5050H, 506CH, 5092H). |
| 40B1H-40B2H 2 bytes | MEMSIZ The top of memory: the moved program and every piece of the block must stay 256 bytes below it (4FCCH, 50F9H); the stack is moved to it (4FD6H). |
| 40F9H-40FAH 2 bytes | End of Program The end of the program, the start of the simple variables (4FABH, 5017H, 502FH, 50FDH); set at 5003H after the second pass. |
Parameters From SYS13/SYS
| Address Size | Contents |
|---|---|
| 4D00H-4D03H 4 bytes | New Start, Increment SYS13/SYS's next new number and increment (default 10, 10); not used by SYS11/SYS. |
| 4D04H-4D05H 2 bytes | First Old Number The first line of the range (default 0): 4F3AH, 5073H. |
| 4D06H-4D07H 2 bytes | Last Old Number The last line of the range (default 65529): 4F34H, 507FH. |
| 4D08H-4D09H 2 bytes | Last New Number The new number of the range's last line: 50D1H. |
| 4D0AH 1 byte | Option U Not 00H: only list the errors (4F9EH). |
| 4D0BH 1 byte | Option X Not 00H: a missing line is listed only when it lies inside the range (4F2EH). |
BASIC/CMD Areas
| Address Size | Contents |
|---|---|
| 5D2AH-5D2EH 5 bytes | Digit Buffer BASIC/CMD's buffer for the five digits of 5D0BH; 5153H copies the digits onto it so that nothing is written. |
| 64A3H-65A2H 256 bytes | Line Table 128 line addresses (4D0CH), each Register C lines apart; 65A3H is the address after it (4D5CH). Searched at 4EC3H, moved with the program at 4FEDH, updated with the output addresses in the second pass (4D4BH-4D65H). |
Operands Changed at Run Time
| Address Size | Contents |
|---|---|
| 4D4CH-4D4DH 2 bytes | Next Table Entry Operand of 4D4BH: the table entry checked in the second pass (4FEAH, 4D65H). |
| 4DE4H 1 byte | ON Flag Operand of 4DE3H: 01H after ON (4DC1H), cleared at each statement (4DA8H). |
| 4DEDH-4DEEH 2 bytes | Current Line Operand of 4DECH: the old number of the line being scanned (4D78H). |
| 4E81H 1 byte | Line 0 Allowed Operand of 4E80H: 01H after RESUME (4DD1H) or ON ERROR (4DCDH), cleared at each statement (4DA4H). |
| 4EF6H-4EF7H 2 bytes | Output Line Operand of 4EF5H: the output address of the line being copied (4D34H); the program's new end after the second pass (5007H). |
| 4F01H-4F02H 2 bytes | Input Line Operand of 4F00H: the input address of the line being copied (4D38H). |
| 4FA6H 1 byte | Errors Flag Operand of 4FA5H: bit 0 set at 4F65H when the first error is listed. |
| 5014H-5015H 2 bytes | Block Start Operand of 5013H, stored at 507BH. |
| 5035H-5036H 2 bytes | Place Operand of 5034H: where the block goes (50CAH). |
| 50C0H-50C1H 2 bytes | Number After the Block Operand of 50BFH, stored at 5087H. |
| 50C8H-50C9H 2 bytes | Number at the Place Operand of 50C7H, stored at 50AFH. |
| 50F2H-50F3H 2 bytes | Length to Move Operand of 50F1H: the block's length or 0000H (50CDH). |
| 50F7H-50F8H 2 bytes | Length Left Operand of 50F6H: what is left to move after each piece (5117H). |
| 515AH-515BH 2 bytes | Growth Total Operand of 5159H: the change in the text's length so far (4D30H clears it, 5163H stores it). |
| 515EH-515FH 2 bytes | Old Digits Operand of 515DH: the number of digits of the number just read (4E73H). |
| 5121H 1 byte | Pass Flag Operand of 5120H: 00H in the first pass, 01H in the second (4FDBH); read at 4D42H, 4EEFH, 4F44H, 4F57H, 4F97H, 50DCH. |
| 5168H-5169H 2 bytes | Largest Growth Operand of 5167H: the largest growth total (516CH), read at 4FB7H. |
Outside Routines
| Where | Addresses |
|---|---|
| ROM | 0033H (through BASIC 5D3FH), 132FH (through 5D00H), 1AE9H (rebuild the links, RUN reset, command level); RST 10H, RST 18H. |
| SYS0/SYS | 4030H (exit after a displayed error). |
| BASIC/CMD | 5CCCH, 5CCEH (step to the next line), 5D00H (number to digits), 5D3DH, 5D3FH, 5D52H (display a space, a character, a carriage return), 5DE2H (relink and give an error). |
Disassembly
4D00H - Parameters Left by SYS13/SYS
SYS13/SYS does the first part of RENUM: from its 50FEH it reads the command's numbers and options into its own bytes 4D00H-4D0BH, gives every line in the range its new number by writing that number into the line's link field (the first two bytes of the line), counts the lines and loads SYS11/SYS with LD A,2DH / RST 28H at its 51CAH. SYS11/SYS loads from 4D0CH on, so these twelve bytes stay in memory as SYS13/SYS left them.
4D0CH - RENUM, Second Part: the Line Table
The SYS0/SYS dispatcher calls the transfer address 4D0CH with the registers SYS13/SYS set: Register Pair HL = the first program line (from 40A4H), Register Pair DE = 64A3H (the line table), Register B = 80H (128 entries) and Register C = the number of lines per entry (the line count divided by 128, rounded up, at least 1). The table at 64A3H-65A2H (BASIC/CMD's initialization code, used as the input buffer) gets the address of every Register C-th line, so that a line can be found by a binary search (4EC3H). Unused entries point at the program's end marker.
TABLE LOOP
Register Pair DE = the table entry to fill (exchanged with Register Pair HL on each pass), Register Pair HL = the line, Register B = the entries left, Register C = the lines per entry.
4D28H - Scan the Program
The main loop, run twice. In the first pass (the operand 5121H = 00H) every line number that the text refers to is looked up (4E4CH), any reference that cannot be renumbered is listed, and the change in the text's length is added up (515AH, with its highest value in 5168H). In the second pass (5121H = 01H) the program has been moved up in memory (4FABH-4FFAH) and is copied back down byte by byte from Register Pair HL (the input) to Register Pair BC (the output), with every reference written as the new number (5120H copies each byte it reads).
Store Register Pair DE (0000H) at 515AH, the operand of LD HL,nnnn at 5159H: the change in the text's length starts at 0 for this pass.
LINE LOOP
Register Pair HL = the input pointer at the line's link field, Register Pair BC = the output pointer.
Store Register Pair BC (the output address of this line) at 4EF6H, the operand of LD BC,nnnn at 4EF5H, which the line search uses to recognize the line being copied.
Store Register Pair HL (the input address of this line) at 4F01H, the operand of LD HL,nnnn at 4F00H: the line search reads this line from its input copy while it is being rewritten.
Load Register Pair HL with the next table entry to check, the operand 4D4CH (0000H in the file; set to 64A3H at 4FEAH and moved on at 4D65H).
Store Register Pair HL (the next table entry) at 4D4CH, the operand of LD HL,nnnn at 4D4BH, for the next line.
Store Register Pair DE (the line's old number) at 4DEDH, the operand of LD DE,nnnn at 4DECH, so that an error report names this line.
REM
The REM token (93H): the rest of the line is read (and copied) without a look at it.
STRINGS
A quote (22H): the bytes up to the closing quote are read (and copied) without a look at them.
DATA
DATA (88H): the bytes up to a colon outside quotes, or the end of the line, are read (and copied) without a look at them.
STATEMENT START
A colon (3AH, from the table at 4E90H) or the line's first statement (4D7CH): the flags of 4E81H and 4DE4H are cleared.
Store Register A at 4E81H, the operand of OR nn at 4E80H: 00H = line 0 is not a valid reference in this statement (4DCDH stores 01H for ON ERROR GOTO 0).
Store Register A at 4DE4H, the operand of LD A,nn at 4DE3H: the ON flag, 00H here, 01H after ON (4DC1H), when a list of line numbers may follow GOTO or GOSUB.
STATEMENT LOOP
Each byte of the text is looked up in the token table at 4E8AH; a byte with an entry goes to its handler, any other byte is passed.
TABLE SEARCH
Register Pair HL = the table entry, Register A = the byte of the text.
Store Register A (01H) at 4E81H, the operand of OR nn at 4E80H: line 0 is a valid reference after RESUME.
Load Register A with the ON flag, the operand 4DE4H (00H in the file; 01H stored at 4DA8H after ON).
Load Register Pair DE with the old number of the line being scanned, the operand 4DEDH (0000H in the file; stored at 4D78H for each line).
SKIP THE STATEMENT
4E40H returns only with bytes inside the statement; at the statement's end it leaves this loop and goes on at 4E10H.
FIND THE SECOND COMMA
Register E = the parenthesis level, Register D = the outer commas still to pass.
4E40H - Next Byte of the Statement
Reads the next byte at Register Pair HL (copied in the second pass) and returns it in Register A. At the end of the statement (00H or a colon) it does not return: it drops its return address and goes on at 4E10H with the byte in Register A.
4E4CH - Replace a Line Number
Called with Register Pair HL at a line number in the text and Register Pair BC = the output pointer. Reads the decimal number (blanks between its digits are passed by RST 10H) and looks the line up. In the second pass the number is written to the output as the line's new number, or unchanged if the line does not exist; in the first pass only the change in the number of digits is counted. Line 0 is accepted only after RESUME or ON ERROR GOTO. Returns with Register Pair HL after the number and Register Pair BC after the output.
DIGIT LOOP
Register Pair DE = the number so far, Register Pair BC = the digits counted, Register A = the digit character, Register Pair HL = its address.
Store Register Pair BC (the number of digits read) at 515EH, the operand of LD DE,nnnn at 515DH, for the change in the text's length.
Line 0: OR Register A (00H) with the operand 4E81H (00H in the file, cleared at 4DA4H at each statement; 01H after RESUME, 4DD1H, or ON ERROR, 4DCDH): the NZ FLAG is set if line 0 is allowed.
4E8AH - Token Table (Data)
19 entries of three bytes: the handler's address (a word) and the byte of the text it handles, in ascending order of the byte; 4DB1H-4DC0H search it. The last entry (FFH) catches every byte above CAH that has no entry.
4EC3H - Find a Line
Looks for the line with the old number in Register Pair DE. A binary search over the 128 table entries (64A3H) finds the last entry whose line number is not above Register Pair DE; from there the lines are walked. Returns Register Pair HL = the line found (or the next higher one, or the end marker) and Register Pair DE = the contents of its link field (its new number, 0000H at the end marker), with the Z FLAG set if the line exists.
BINARY SEARCH
Register Pair HL = the table entry, Register Pair BC = the step in bytes (halved each time), Register Pair DE = the number wanted.
LINE WALK
Register Pair HL = the line, Register Pair DE = the number wanted.
Load Register Pair BC with the output address of the line being copied, the operand 4EF6H (0000H in the file; stored at 4D34H for each line, and at 5007H the program's new end).
It is the line being copied, not yet complete at its output address: load Register Pair HL with its input address instead, the operand 4F01H (0000H in the file; stored at 4D38H for each line).
4F22H - Write the New Number
Register Pair DE = the old number read at 4E4CH (not 0), with the output pointer and the input pointer on the stack. A reference to a line that does not exist is error letter U (with option X only if it lies inside the renumbered range) and the old number is kept.
4F54H - List an Error
Called from 4DEFH with Register A = the error letter (X or S) and Register Pair DE = the line number to show; 4E87H enters at 4F56H and 4F22H at 4F57H with the input pointer, the output pointer and the error letter already on the stack. The first report shows Error Lines; each report shows the number, a slash and the letter at the cursor. An error in the second pass means the text is already partly rewritten, so it stops with Fatal Error at 50E4H instead.
Set bit 0 of the byte at Register Pair HL, 4FA6H: the operand of LD A,nn at 4FA5H becomes 01H, so the heading is shown only once and the first pass ends without renumbering (4FA8H).
4F97H - End of the First Pass
4D3FH jumps here when the scan reaches the program's end marker. With option U, or after an error was listed, RENUM stops: the lines keep their numbers, Done is shown only for U, and the ROM rebuilds the links (5069H). Otherwise the program is moved up in memory by the text's largest growth plus 256 bytes, the stack is moved to the top of memory, the line table is moved with the program, and the second pass copies the program back down with the new numbers.
Load Register A with the errors flag, the operand 4FA6H (00H in the file; bit 0 set at 4F65H when the first error is listed).
Store Register A (01H) at 5121H, the operand of LD A,nn at 5120H: from now on 5120H copies every byte it reads to the output at Register Pair BC.
Store Register Pair HL (64A3H) at 4D4CH, the operand of LD HL,nnnn at 4D4BH: the second pass checks the table entries from the first one.
TABLE LOOP
Register Pair HL = the table entry, Register Pair BC = the distance, Register E = the entries left. Every line address in the table moves by the same distance as the program.
4FFDH - End of the Second Pass
4F9BH jumps here when the second pass reaches the end marker, with Register Pair HL = the marker in the moved copy and Register Pair BC = the output pointer. The text is rewritten. The renumbered lines (the block) are moved to where their new numbers belong, the new numbers are copied from the link fields into the line number fields, Done is shown and the ROM rebuilds the links.
Store Register Pair BC (the program's new end) at 4EF6H, the operand of LD BC,nnnn at 4EF5H: no line starts there, so the line searches made by 5073H read every line where it is.
MOVE THE BLOCK TO THE END
Register Pair BC = the length of the piece. Each piece is copied to the end of the program and everything after it is moved down over it, until the whole block sits at the end.
Load Register Pair HL with the start of the block, the operand 5014H (0000H in the file, stored at 507BH).
INSERT THE BLOCK
Register Pair BC = the length of the piece. Each piece is taken from the end of the program and put into a gap opened at the place, the last part of the block first.
Load Register Pair DE with the place the block goes, the operand 5035H (0000H in the file, stored at 50CAH).
COPY THE NEW NUMBERS
Register Pair HL = the line, Register Pair DE = its link field (the new number SYS13/SYS put there, or 0000H at the end marker).
5073H - Where the Block Goes
Called from 4D25H (before the first pass) and 500BH (after the second). Finds the lines of the renumbered range (the block, from the first old number in 4D04H to the last in 4D06H) and the line their new numbers must go before: the first line whose number is not below the block's first new number. If the block's last new number (4D08H) is not below that line's new number, the renumbering would put the lines out of order: error 8CH SEQ # OVERFLOW (Fatal Error in the second pass). Stores the block's start (5014H), the place (5035H) and the length to move (50F2H, 0000H if the block stays where it is).
Store Register Pair HL (the block's first line) at 5014H, the operand of LD HL,nnnn at 5013H.
Store Register Pair DE (the new number of the line after the block) at 50C0H, the operand of LD DE,nnnn at 50BFH.
FIND THE PLACE
Register Pair HL = the line, Register Pair DE = the new number of the block's first line. The walk stops at the first line whose number is not below it.
Store Register Pair DE (the new number of the line at the place) at 50C8H, the operand of LD DE,nnnn at 50C7H.
The block stays where it is: load Register Pair DE with the new number of the line after the block, the operand 50C0H (0000H in the file, stored at 5087H).
Load Register Pair DE with the new number of the line at the place, the operand 50C8H (0000H in the file, stored at 50AFH).
Store Register Pair HL (the place, less the block's length when it lies above the block) at 5035H, the operand of LD DE,nnnn at 5034H.
Store Register Pair BC (the block's length, or 0000H when it stays) at 50F2H, the operand of LD DE,nnnn at 50F1H.
50F1H - The Next Piece to Move
The block is moved through the free memory between the end of the program (40F9H) and 256 bytes below the top of memory (40B1H). 50F1H starts with the block's whole length, 50F6H goes on with what is left. Returns Register Pair BC = the piece to move, with the Z FLAG set if none; less than 256 free bytes is OUT OF MEMORY.
Load Register Pair DE with the block's length, the operand 50F2H (0000H in the file, stored at 50CDH).
Load Register Pair DE with what is left of the block, the operand 50F7H (0000H in the file, stored at 5117H).
Store Register Pair HL (what is left after this piece) at 50F7H, the operand of LD DE,nnnn at 50F6H.
511DH - Reading the Text
5120H reads the next byte of the program at Register Pair HL and, in the second pass, also copies it to the output at Register Pair BC. 512EH passes blanks (spaces, 09H and 0AH), copying them in the second pass; 513BH also returns the CARRY FLAG if a digit follows, without reading it; 511DH passes blanks and reads the next byte.
Load Register A with the pass flag, the operand 5121H (00H in the file for the first pass; set to 01H at 4FDBH for the second).
5147H - Display a Message
Displays the text at Register Pair HL up to its 03H end byte, then a carriage return. BASIC 5D3FH also prints each character when BASIC's printer switch at 5D45H is 24H.
5153H - Count or Write a Number
Converts Register Pair DE to decimal through BASIC 5D00H (leading zeros dropped) and copies the digits to Register Pair BC; 5153H points Register Pair BC at BASIC's own digit buffer 5D2AH, so nothing in the program is written and only the count matters. The number of new digits less the number of old digits (515EH) is added to the growth total (515AH), whose highest value is kept in 5168H.
Load Register Pair HL with the growth total, the operand 515AH (0000H in the file; cleared at 4D30H at the start of each pass).
Load Register Pair DE with the number of digits of the old number, the operand 515EH (0000H in the file, stored at 4E73H).
Store Register Pair HL (the growth total) at 515AH, the operand of LD HL,nnnn at 5159H.
Load Register Pair DE with the largest growth total so far, the operand 5168H (0000H in the file; read at 4FB7H).
Store Register Pair HL (the new largest growth total) at 5168H, the operand of LD DE,nnnn at 5167H.
5170H - Messages (Data)
The three texts 5147H displays, each ended by 03H.
519DH - Compare After Taking the Block Out
Called from 50B8H with Register Pair HL = the place, Register Pair BC = the block's length and Register Pair DE = the block's start; the CARRY FLAG is clear (from the RST 18H at 50B5H).
51A2H - Unused Bytes
The rest of the file.