5200H - Symbol Table Listing: Start
Entered by the JP 5200H at 6460H after assembler pass 2 (unless the NS switch was given). Prints every symbol in alphabetical order with its value (or UNDEF***), the line number of its definition and the line numbers of every line that refers to it. The symbols are not sorted in place: for each line of output, 521CH-52A5H scan the whole symbol table for the smallest name that is greater than the one printed last. 7650H points to the name printed last; it starts at the dummy entry at 7654H-7655H (name 00H), which is lower than any real name. The text scan loop at 550CH is set up here to stop at the end of the text.
5200
LD HL,(5315H) 2A 15 53
Load Register HL with the end-of-text pointer from 5315H.
5203
LD A,H 7C
Copy its high byte into Register A.
5204
LD (550EH),A 32 0E 55
Self-Modifying Code
Store it as the operand of the CP 00H at 550DH (high byte of the scan stop address).
5207
LD A,L 7D
Copy the low byte into Register A.
5208
LD (5513H),A 32 13 55
Self-Modifying Code
Store it as the operand of the CP 00H at 5512H (low byte of the scan stop address).
520B
LD HL,7655H 21 55 76
Point HL to 7655H, the name of the dummy entry at 7654H-7655H (length 01H, name 00H), which sorts below every real symbol.
520E
LD (7650H),HL 22 50 76
Store it into 7650H as the "name printed last".
5211
Next Symbol
GOSUB to 5937H to start a new output line.
5214
LD A,(3840H) 3A 40 38
Read keyboard matrix row 6 at 3840H.
5217
AND 04H E6 04
Keep bit 2, the BREAK key.
5219
If BREAK is held, JUMP to 58DAH, the command loop.
521CH - Symbol Table Listing: Find the Next Name in Order
Walks the symbol table from its bottom (53C3H) to the entry with a zero length. An entry is a flag byte (bits 0-2 = name length), the name, and a 2-byte value. The best candidate so far (7650H) starts as the dummy entry at 7656H-7657H (name FFH), which sorts above every real name. For each entry the name is compared with the name printed last (skip it if it is not greater) and with the candidate (take it if it is smaller). The first character and the end address of both names are patched into CP instructions so the compares are fast.
521C
LD HL,(7650H) 2A 50 76
Load Register HL with the pointer to the name printed last, from 7650H.
521F
LD (764EH),HL 22 4E 76
Save it into 764EH for the compare loop.
5222
LD A,(HL) 7E
Load Register A with the first character of that name.
5223
LD (5252H),A 32 52 52
Self-Modifying Code
Store it as the operand of the CP at 5251H.
5226
DEC HL 2B
Point HL at the entry's flag byte (one byte before the name).
5227
LD A,(HL) 7E
Load Register A with the flag byte.
5228
AND 07H E6 07
Keep bits 0-2, the name length.
522A
ADD A,L 85
Add the low byte of the flag byte's address: Register A = low byte of the address of the last name character.
522B
LD (526DH),A 32 6D 52
Self-Modifying Code
Store it as the operand of the CP at 526CH, which detects the end of the name printed last.
522E
LD HL,7657H 21 57 76
Point HL to 7657H, the name of the dummy entry at 7656H-7657H (length 01H, name FFH): the first candidate.
5231
LD DE,(53C3H) ED 5B C3 53
Load Register DE with the bottom of the symbol table from 53C3H.
5235
LD (7650H),HL 22 50 76
New Candidate
Store the candidate name pointer (HL) into 7650H.
5238
LD A,(HL) 7E
Load Register A with the candidate's first character.
5239
LD (5280H),A 32 80 52
Self-Modifying Code
Store it as the operand of the CP at 527FH.
523C
DEC HL 2B
Point HL at the candidate's flag byte.
523D
LD A,(HL) 7E
Load Register A with it.
523E
AND 07H E6 07
Keep bits 0-2, the name length.
5240
ADD A,L 85
Add the low byte of the flag byte's address: the low byte of the address of the candidate's last character.
5241
LD (5292H),A 32 92 52
Self-Modifying Code
Store it as the operand of the CP at 5291H.
5244
LD A,(DE) 1A
Next Table Entry
Load Register A with the flag byte of the table entry at DE.
5245
AND 07H E6 07
Keep bits 0-2, the name length.
5247
A length of 0 marks the end of the table: JUMP to 52A7H.
5249
LD B,A 47
Keep the length in Register B (characters left to compare) ...
524A
LD C,A 4F
... and in Register C.
524B
INC DE 13
Point DE at the entry's name.
524C
LD (7634H),DE ED 53 34 76
Save the name pointer into 7634H.
5250
LD A,(DE) 1A
Load Register A with the entry's first character.
5251
CP 00H FE 00
Self-Modifying Code
Compare with the first character of the name printed last (operand set at 5223H).
5253
Lower: this entry was already printed. JUMP to 5260H to skip it.
5255
Higher: JUMP to 527FH to compare it with the candidate.
5257
LD HL,(764EH) 2A 4E 76
Same first character: load Register HL with the pointer to the name printed last from 764EH.
525A
JUMP to 526BH to compare the rest.
525C
LD A,(DE) 1A
Compare with the Name Printed Last
Load Register A with the next character of the entry.
525D
CP (HL) BE
Compare it with the character of the name printed last.
525E
Not lower: JUMP to 5269H.
5260
INC B 04
Skip This Entry
Increment Register B (the characters left in this name) ...
5261
INC B 04
... a second time, to include the two value bytes.
5262
LD L,B 68
Copy the count into Register L.
5263
LD H,00H 26 00
Register H = 00H.
5265
ADD HL,DE 19
Add the entry pointer: HL = the next entry's flag byte.
5266
EX DE,HL EB
Move it into DE.
5267
LOOP BACK to 5244H for the next entry.
5269
Higher than the name printed last: JUMP to 5279H to compare it with the candidate.
526B
LD A,L 7D
Load Register A with the low byte of the pointer into the name printed last.
526C
CP 00H FE 00
Self-Modifying Code
Compare with the low byte of that name's last character (operand set at 522BH). The Z FLAG is set at its last character.
526E
INC DE 13
Advance the entry pointer (DE); the flags are not changed.
526F
The name printed last has ended: JUMP to 5276H.
5271
INC HL 23
Advance the pointer into the name printed last.
5272
Decrement the characters left in Register B and LOOP BACK to 525CH.
5274
The entry ended first, so it sorts below the name printed last: JUMP to 5260H to skip it.
5276
DEC B 05
Count the entry character just matched.
5277
The entry ended too, so it is the name printed last itself: JUMP to 5260H to skip it. Otherwise the entry is longer and sorts after it.
5279
LD DE,(7634H) ED 5B 34 76
Compare with the Candidate
Reload Register DE with the entry's name pointer from 7634H.
527D
LD B,C 41
Reload the name length into Register B.
527E
LD A,(DE) 1A
Load Register A with the entry's first character.
527F
CP 00H FE 00
Self-Modifying Code
Compare with the candidate's first character (operand set at 5239H).
5281
Lower: this entry becomes the new candidate. JUMP to 529EH.
5283
Higher: JUMP to 5260H to skip it.
5285
LD HL,(7650H) 2A 50 76
Same first character: load Register HL with the candidate name pointer from 7650H.
5288
JUMP to 5290H to compare the rest.
528A
LD A,(DE) 1A
Load Register A with the next character of the entry.
528B
CP (HL) BE
Compare it with the candidate's character.
528C
Lower: JUMP to 5299H; the entry becomes the new candidate.
528E
Higher: JUMP to 5260H to skip it.
5290
LD A,L 7D
Load Register A with the low byte of the pointer into the candidate.
5291
CP 00H FE 00
Self-Modifying Code
Compare with the low byte of the candidate's last character (operand set at 5241H).
5293
The candidate ended first, so it sorts lower: JUMP to 5260H to skip the entry.
5295
INC DE 13
Advance the entry pointer.
5296
INC HL 23
Advance the candidate pointer.
5297
Decrement the characters left and LOOP BACK to 528AH.
5299
LD DE,(7634H) ED 5B 34 76
The entry ended first, so it sorts lower: reload its name pointer from 7634H ...
529D
LD B,C 41
... and its length into Register B.
529E
INC B 04
Increment Register B (the characters left) ...
529F
INC B 04
... a second time, to include the two value bytes.
52A0
LD L,B 68
Copy the count into Register L.
52A1
LD H,00H 26 00
Register H = 00H.
52A3
ADD HL,DE 19
HL = the next entry's flag byte.
52A4
EX DE,HL EB
Exchange: DE = the next entry, HL = this entry's name.
52A5
JUMP to 5235H to make this entry the candidate and continue the scan.
52A7H - Symbol Table Listing: Print the Chosen Symbol
Reached at the end of the table. If the candidate is still the FFH dummy entry, every symbol has been printed and the listing ends at 6486H. Otherwise the chosen symbol's flag byte and name end are patched into the printing and compare code, the scan controls are reset, and the text scan at 550CH starts from the first line (7700H) to find the symbol's definition and references. An undefined symbol (flag bit 7 clear) has no definition line, so its heading is printed first through 559CH.
52A7
LD HL,(7650H) 2A 50 76
Load Register HL with the chosen name pointer from 7650H.
52AA
LD A,(HL) 7E
Load Register A with its first character.
52AB
LD C,A 4F
Keep the first character in Register C for the text scan.
52AC
INC A 3C
Add 1: the Z FLAG is set only for FFH, the dummy entry.
52AD
A real symbol was found: JUMP to 52B5H.
52AF
All symbols printed: GOSUB to 5937H to end the line.
52B2
JUMP to 6486H to continue the assembler after the listing.
52B5
DEC HL 2B
Point HL at the symbol's flag byte.
52B6
LD A,(HL) 7E
Load Register A with it.
52B7
LD (55EAH),A 32 EA 55
Self-Modifying Code
Store the flag byte as the operand of the LD A,00H at 55E9H.
52BA
AND 07H E6 07
Keep bits 0-2, the name length.
52BC
ADD A,L 85
Add the low byte of the flag byte's address: the low byte of the address of the last name character.
52BD
LD (5689H),A 32 89 56
Self-Modifying Code
Store it as the operand of the LD A,00H at 5688H (end of the name for the compare at 5684H).
52C0
LD A,20H 3E 20
Load Register A with 20H, the JR NZ opcode.
52C2
LD (5524H),A 32 24 55
Self-Modifying Code
Store it at 5524H: the label field of each line is compared with the symbol.
52C5
LD A,28H 3E 28
Load Register A with 28H, the JR Z opcode.
52C7
LD (552FH),A 32 2F 55
Self-Modifying Code
Store it at 552FH: a semicolon in the label field ends the line (normal scanning).
52CA
LD (559EH),A 32 9E 55
Self-Modifying Code
Store 28H at 559EH: the first label match prints the heading.
52CD
XOR A AF
Set Register A to 00H.
52CE
LD (7636H),A 32 36 76
Clear 7636H, the saved count for a reference list overflow.
52D1
LD (764DH),A 32 4D 76
Clear 764DH, the number of references in the list.
52D4
LD HL,763DH 21 3D 76
Point HL to 763DH, the start of the reference list.
52D7
LD (763BH),HL 22 3B 76
Store it into 763BH, the list write pointer.
52DA
LD HL,(7650H) 2A 50 76
Load Register HL with the symbol name pointer from 7650H.
52DD
DEC HL 2B
Point HL at the flag byte.
52DE
LD A,(HL) 7E
Load Register A with it.
52DF
AND 80H E6 80
Keep bit 7, the "defined" flag.
52E1
Undefined (Z FLAG set): GOSUB to 559CH to print the heading now.
52E4
LD HL,7700H 21 00 77
Load HL with 7700H, the start of the text buffer (the first text line). The reference scan starts there.
52E7
JUMP to 550CH to scan the text.
52EAH - Symbol Table Listing: End of a Text Scan
Reached from 5514H when the scan passes the end of the text. Normally the symbol is finished and the next one is chosen (5211H). For a multiply defined symbol the first scan only collected the line numbers of its definitions (559EH = 20H); a second scan then lists its references, starting at the first definition line (7652H).
52EA
LD A,(559EH) 3A 9E 55
Load Register A with the opcode stored at 559EH.
52ED
CP 28H FE 28
Compare with 28H (JR Z, the normal setting).
52EF
Normal: JUMP to 5211H for the next symbol.
52F2
LD A,28H 3E 28
Load Register A with 28H ...
52F4
LD (559EH),A 32 9E 55
Self-Modifying Code
... and restore the JR Z at 559EH.
52F7
LD HL,55EAH 21 EA 55
Point HL to 55EAH, the flag byte patched into the LD A,00H at 55E9H.
52FA
RES 6,(HL) CB B6
Self-Modifying Code
Clear bit 6 (multiply defined) so the heading code does not report it again.
52FC
JUMP to 5500H to scan the text again for references.
52FFH - Working Storage (Not in the File)
Not Loaded
EDTASM/CMD has no load record for 52FFH-54FFH: its first load block ends at 52FEH and the next starts at 5500H. The bytes here are whatever was in memory before; EDTASM sets each variable before it reads it (at 588AH-58B7H, 58E4H-58EDH, 63E3H-63FCH and 6427H-643BH). The rows below list each variable with the code that sets and reads it. There are no bytes to show, so the rows have no opcode column.
52FF
DEFS 1
Not referenced.
5300
DEFS 1
Find String Length
Number of characters in the find string at 5301H. Set to 01H at 58ABH, set by the F command at 5DD6H, read at 5E04H.
5301-5310
DEFS 16
Find String
Up to 16 characters (the limit is the CP 10H at 5DD9H) typed after the F command. Set to a single 0DH at 58AEH.
5311-5312
DEFS 2
Current Line Pointer
Address of the current text line (each line is stored as line number low byte, line number high byte, length byte, text). Set at 591AH (to 5888H when the buffer is empty), 5CB0H, 5E4FH, 5EE7H, 5EFFH, 5F83H and 64DDH; read at 5D16H, 5D57H, 5DDDH, 5E41H, 5E7AH, 6170H and 6E33H.
5313-5314
DEFS 2
Symbol Table Top
Copied from the DOS high-memory pointer at 4049H by 589CH-589FH. Read at 5DABH (memory-full test) and 63E3H (the assembler starts the symbol table here).
5315-5316
DEFS 2
End-of-Text Pointer
Address of the FFH FFH end-of-text marker. 7700H when the buffer is empty (588DH). Changed by the insert, delete and load code (5C95H, 5F1BH, 5FA6H) and by the appendage at 6F6EH; read by the command loop (590DH), the cross-reference lister (5200H), the assembler (64D0H) and the appendage (6F4EH, 7092H).
5317-5318
DEFS 2
Line Number Increment
Set to 10 at 58A5H. Changed by the line-range parser at 5CD6H when an increment is typed. Read at 5C2CH and 5C47H.
5319-531A
DEFS 2
Line Before the Found Line
Set by the line search at 5CDFH as it walks the text (the found line itself when the first line matches). Read at 5D68H, 5E87H and 5EFCH.
531B-531C
DEFS 2
Found Line
Address of the line located by the line search (5D02H). Read at 5E97H, 5EA5H and 5EDBH.
531D-531E
DEFS 2
Line After the Found Line / Assembly Line Pointer
Set by the line search at 5CFDH to the line after the one found, and by 5CABH, 5EDEH and 5F04H. During assembly it is set to 7700H at 642AH and advanced one source line at a time at 64EEH; 64D4H reads it to fetch the next source line.
531F-5320
DEFS 2
Last Object Address
Address of the last byte sent to the object record. The object output routine (6E75H-6E7DH) compares the next byte's address with this value plus one to decide whether the byte continues the current record.
5321-5322
DEFS 2
Object Record Write Pointer
Where the next object byte goes in the record buffer at 5327H. Set at 6EA1H and at 70A9H (the appendage routine called from 6EB9H); read at 6EB3H.
5323
DEFS 1
Object Record Checksum
Started as load-address low byte + high byte at 6E92H-6E94H; each data byte is added at 6EBFH-6EC0H; written after the record by 6EDAH-6EDBH.
5324
DEFS 1
Object Record Byte Count
Cleared at 6E97H and incremented for each byte at 6EA8H-6EAEH (a new record starts when it would reach 81H). 6EC5H-6ECAH use it to size the record write.
5325-5326
DEFS 2
Object Record Load Address
Stored at 6E9DH-6E9FH. Written as part of the record by the loop at 6ED3H.
5327-53A6
DEFS 128
Line Input Buffer / Object Record Data
The command line and edited lines are typed here (5B41H sets the scan pointer 53A8H to 5327H; 5B7DH limits input to 80H characters). The line editor copies a text line here at 5FD4H. During pass 3 of an assembly the same 128 bytes hold the data bytes of the current object record (6EA1H).
53A7
DEFS 1
Not referenced.
53A8-53A9
DEFS 2
Input Scan Pointer
Next character to be read by the get-character routine at 5BBEH (read and advanced at 5BCDH-5BD2H, backed up at 5BF5H-5BF9H). Set to 5327H by the line input routine (5B44H) and to the text of the current source line during assembly (64E7H). Read by the appendage at 6F75H.
53AA
DEFS 1
Input Characters Remaining
Characters left to read at 53A8H. Set at 5B76H, 603EH, 64B7H and 64E3H; tested and counted down by 5BC2H-5BCCH; changed by the appendage at 6FD7H.
53AB-53AC
DEFS 2
File Name Pointer
Address of the cassette file name for W, L and the object tape. Set to 5AFFH ("NONAME") at 6406H or to the typed name at 611CH; read at 5F5DH and 612CH.
53AD
DEFS 1
File Name Length
Cleared at 610AH, set at 611AH (a name of seven or more characters is rejected at 6115H); read at 5F60H and 6124H.
53AE-53AF
DEFS 2
Line Address / Value
The address (or, for EQU, DEFL and DEFS, the value) shown on the listing line; also the address of the next object byte in pass 3. Set at 64C5H, 6B12H, 6B44H, 6B7CH, 6BA0H, 6BD3H and 6EB0H; read at 6B39H and 6E7AH. 6E0BH points HL at 53AFH to list the bytes that follow.
53B0
DEFS 1
Prefix Byte
DDH, FDH, CBH or EDH prefix of the instruction being assembled, or 00H (cleared at 64CDH). The object output at 6E6CH starts at this byte when it is non-zero.
53B1-53B3
DEFS 3
Instruction Bytes
Opcode and operand bytes of the instruction being assembled (53B1H is set from the opcode table at 6585H and by the encoders, for example 6926H, 6B30H, 6B60H; DEFW stores a word at 6B6AH).
53B4-53B5
DEFS 2
Instruction Length
53B4H holds the number of bytes generated for the line (set to 01H by 688DH, changed at 670BH-6720H, 69F7H, 6B07H, 6B4BH); read at 6E22H and 6E68H. 64BAH-64CAH read and clear 53B4H-53B5H as a word.
53B6-53B7
DEFS 2
Location Counter
Address of the next instruction. Advanced by the line length at 64BEH-64C2H; set by ORG (6B79H), DEFS (6B16H) and DEFM (6B47H); read at 62CAH, 65A2H and 6853H.
53B8-53B9
DEFS 2
Error Count
Incremented for each error at 6153H-6157H; displayed after TOTAL ERRORS by 642DH-6445H.
53BA
DEFS 1
Output-to-File Flag
When non-zero, the character output routine at 5939H sends each character to the tape or disk file through 710CH instead of the screen. Set during the W command (5F30H, cleared at 5F45H); cleared at 58B4H, 58E8H and by the appendage at 72A2H.
53BB
DEFS 1
Output Column
Column count used for tab expansion (5964H) and backspacing (5B32H, 5B8FH). Set to FFH at 58EAH and 5D97H.
53BC
DEFS 1
Printer Flag
When non-zero, 5939H prints each character through the ROM at 003BH instead of displaying it. Set at 5E30H by H and T (the P command clears it there), by 6199H while the LP switch is on, and at 6457H; cleared at 58B7H, 58EDH, 61A4H and 6487H.
53BD
DEFS 1
Listing Off Flag
Set to 00H by *L ON and 01H by *L OFF (6508H-652CH). When non-zero, 6E03H does not list the following lines (it is ORed with the NL switch).
53BE
DEFS 1
Object Record Open
FFH while an object record is being filled (6E99H), 00H after it is written (6EDFH). Read at 6BAFH and 6E80H.
53BF
DEFS 1
Error on This Line
Set to 01H by the error routine at 6178H; counted down at 649FH, where the WE switch pauses the assembly.
53C0
DEFS 1
Assembler Pass
01H, 02H or 03H. Cleared at 63EBH and incremented at 643BH. Pass 1 builds the symbol table, pass 2 produces the listing, pass 3 writes the object code (6DF4H-6DFEH). Read at 615CH, 6B3CH, 6B86H, 6BA8H and by the appendage at 7294H.
53C1-53C2
DEFS 2
Expression Work Pointer
Used by the expression evaluator at 62A5H-63C9H.
53C3-53C4
DEFS 2
Symbol Table Bottom
Lowest address used by the symbol table, which grows down from 5313H. Set at 63E6H and 65CDH; read by the cross-reference lister (5231H), the assembler (645AH, 65A8H, 65B8H) and the appendage (708FH) to compute free memory.
53C5
DEFS 1
No Line Numbers Flag
Cleared at 58EEH. The T command sets it (5E1FH) so 5E58H prints the text without line numbers.
53C6-54FD
DEFS 312
Stack Area
Not referenced by address. The stack grows down into this space from 54FEH.
54FE-54FF
DEFS 2
Stack Top
The stack pointer is set to 54FEH at 58B0H, 58DAH and 6496H.
5500H - Symbol Table Listing: Text Scan
Scans the text line by line for the symbol being listed (Register C = its first character; its flag byte and name end are patched in by 52B5H-52BDH). Each line is a line number (2 bytes), a length byte and the text; 7634H holds the address of the current line and Register B counts the characters left in it. The label field is compared at 5522H while 5524H holds 20H (JR NZ); the operand field is compared at 5564H. A semicolon starts a comment and ends the line; an apostrophe (a character constant) also ends the scan of the line. Entry at 5500H is the second scan of a multiply defined symbol, which starts at its first definition line (7652H).
5500
GOSUB to 5937H to start a new output line.
5503
LD HL,(7652H) 2A 52 76
Load Register HL with the first definition line from 7652H.
5508
LD E,B 58
Skip the Rest of the Line
Register E = the characters left in the line (Register B).
5509
LD D,00H 16 00
Register D = 00H.
550B
ADD HL,DE 19
Add them to HL: HL = the next line.
550C
LD A,H 7C
Next Line
Load Register A with the high byte of the line address.
550D
CP 00H FE 00
Self-Modifying Code
Compare with the high byte of the end of the text (operand set at 5204H).
550F
If different, JUMP to 5514H.
5511
LD A,L 7D
Load Register A with the low byte of the line address.
5512
CP 00H FE 00
Self-Modifying Code
Compare with the low byte of the end of the text (operand set at 5208H).
5514
At or past the end of the text: JUMP to 52EAH.
5517
LD (7634H),HL 22 34 76
Store the line address into 7634H.
551A
INC HL 23
Skip the line number ...
551B
INC HL 23
... two bytes.
551C
LD B,(HL) 46
Load Register B with the line length.
551D
INC HL 23
Point HL at the first text character.
551E
INC B 04
Test the length ...
551F
DEC B 05
... for zero.
5520
Empty line: JUMP to 550CH (HL already points to the next line).
5522
LD A,(HL) 7E
Label Field
Load Register A with the first character of the line.
5523
CP C B9
Compare it with the first character of the symbol (Register C).
5524
Self-Modifying Code
Opcode set to 20H (JR NZ) at 52C2H or 18H (JR) at 5610H: skip the label compare if the first character differs, or always once the heading has been printed.
5526
GOSUB to 5684H to compare the rest of the name. The Z FLAG is set on a match.
5529
The label matches: GOSUB to 559CH (heading, or a further definition of a multiply defined symbol).
552C
LD A,(HL) 7E
Label Field Loop
Load Register A with the next character.
552D
CP 3BH FE 3B
Compare it with 3BH (semicolon).
552F
Self-Modifying Code
Opcode 28H (JR Z) or 18H (JR): a comment ends the line; with 18H every line ends here, so only label fields are examined.
5531
CP 09H FE 09
Compare with 09H (tab).
5533
A tab ends the label field: JUMP to 554DH.
5535
CP 20H FE 20
Compare with 20H (space).
5537
A space ends the label field: JUMP to 554DH.
5539
INC HL 23
Advance to the next character.
553A
Decrement the characters left and LOOP BACK to 552CH.
553C
The line ended: JUMP to 550CH.
553E
LD A,(HL) 7E
Skip Blanks Before the Opcode
Load Register A with the next character.
553F
CP 3BH FE 3B
Compare with 3BH (semicolon).
5541
A comment: JUMP to 5508H to skip the rest of the line.
5543
A character above 3BH starts the opcode: JUMP to 555FH.
5545
CP 20H FE 20
Compare with 20H (space).
5547
A space: JUMP to 554DH to skip it.
5549
CP 09H FE 09
Compare with 09H (tab).
554B
Anything else starts the opcode: JUMP to 555FH.
554D
INC HL 23
Advance to the next character.
554E
Decrement the characters left and LOOP BACK to 553EH.
5550
The line ended: JUMP to 550CH.
5552
LD A,(HL) 7E
Opcode Field
Load Register A with the next character.
5553
CP 09H FE 09
Compare with 09H (tab).
5555
A tab ends the opcode: JUMP to 5596H to scan the operand.
5557
CP 20H FE 20
Compare with 20H (space).
5559
A space ends the opcode: JUMP to 5596H.
555B
CP 3BH FE 3B
Compare with 3BH (semicolon).
555D
A comment: JUMP to 5508H.
555F
INC HL 23
Advance to the next character.
5560
Decrement the characters left and LOOP BACK to 5552H.
5562
The line ended: JUMP to 550CH.
5564
LD A,(HL) 7E
Operand Field
Load Register A with the next character.
5565
CP 41H FE 41
Compare with 41H (A).
5567
Below A: JUMP to 558CH.
5569
CP 5BH FE 5B
Compare with 5BH.
556B
Above Z: JUMP to 5596H to step past it.
556D
CP C B9
A letter: compare it with the first character of the symbol (Register C).
556E
Different: JUMP to 557FH to skip this identifier.
5570
GOSUB to 5684H to compare the rest of the name.
5573
A match: GOSUB to 5646H to record the reference. Also entered from 562BH after a reference list overflow.
5576
LD A,(HL) 7E
Skip the Identifier
Load Register A with the next character.
5577
CP 41H FE 41
Compare with 41H (A).
5579
Below A: JUMP to 5584H to test for a digit.
557B
CP 5BH FE 5B
Compare with 5BH.
557D
Above Z: the identifier has ended; JUMP to 5596H.
557F
INC HL 23
Advance to the next character.
5580
Decrement the characters left and LOOP BACK to 5576H.
5582
The line ended: JUMP to 550CH.
5584
CP 30H FE 30
Compare with 30H (0).
5586
Below 0: JUMP to 558CH.
5588
CP 3AH FE 3A
Compare with 3AH.
558A
A digit continues the identifier: JUMP to 557FH.
558C
CP 3BH FE 3B
Compare with 3BH (semicolon).
558E
A comment: JUMP to 5508H to skip the rest of the line.
5591
CP 27H FE 27
Compare with 27H (apostrophe).
5593
A character constant: JUMP to 5508H to skip the rest of the line.
5596
INC HL 23
Advance to the next character.
5597
Decrement the characters left and LOOP BACK to 5564H.
5599
The line ended: JUMP to 550CH.
559CH - Symbol Table Listing: Label Match
Called when the symbol is found in a label field (and from 52E1H for an undefined symbol). With 559EH = 28H (JR Z) the heading is printed (55A9H). After a multiply defined heading, 559EH = 20H (JR NZ) and each further definition line only has its line number added to the heading line (55A0H). Registers HL and BC are preserved.
559C
PUSH HL E5
Save the scan pointer (HL).
559D
PUSH BC C5
Save the characters left (BC).
559E
Self-Modifying Code
Opcode 28H (JR Z) or 20H (JR NZ): with the Z FLAG from the name compare, JUMP to 55A9H to print the heading.
55A0
LD HL,(7634H) 2A 34 76
Print One Line Number
Load Register HL with the current line address from 7634H. Also entered from 564DH.
55A3
GOSUB to 56D3H to print its line number, starting a new indented output line when the current one is full.
55A6
POP BC C1
Restore Register BC.
55A7
POP HL E1
Restore Register HL.
55A9
LD HL,(7634H) 2A 34 76
Heading
Load Register HL with the current line (the definition line) from 7634H.
55AC
LD (7652H),HL 22 52 76
Store it into 7652H, where a second scan of a multiply defined symbol starts.
55AF
LD HL,(7650H) 2A 50 76
Load Register HL with the symbol name pointer from 7650H.
55B2
LD A,(55EAH) 3A EA 55
Load Register A with the symbol's flag byte (from the operand of the LD at 55E9H).
55B5
AND 07H E6 07
Keep bits 0-2, the name length.
55B7
LD B,A 47
Register B = the name length.
55B9
GOSUB to 56B6H to print the name (HL advances past it, to the value).
55BC
POP BC C1
Restore the name length.
55BD
LD A,07H 3E 07
Load Register A with 07H.
55BF
SUB B 90
Subtract the name length.
55C0
LD B,A 47
Register B = the number of padding spaces.
55C1
GOSUB to 56CDH to print them, so the value starts in column 8.
55C4
INC HL 23
Point HL at the value's high byte.
55C5
GOSUB to 6E4EH to print it as two hex digits.
55C8
DEC HL 2B
Point HL at the low byte.
55C9
GOSUB to 6E4EH to print it.
55CC
GOSUB to 56C8H to print a space.
55CF
LD A,(55EAH) 3A EA 55
Load Register A with the flag byte from 55EAH.
55D2
AND 80H E6 80
Keep bit 7, the "defined" flag.
55D4
Defined: JUMP to 55DEH.
55D6
LD HL,760DH 21 0D 76
Point HL to the text UNDEF*** at 760DH.
55D9
GOSUB to 56BEH to print it.
55DE
LD HL,(7634H) 2A 34 76
Load Register HL with the definition line address from 7634H.
55E1
GOSUB to 56E7H to print its line number.
55E4
LD B,02H 06 02
Load Register B with 02H.
55E6
GOSUB to 56CDH to print two spaces.
55E9
LD A,00H 3E 00
Self-Modifying Code
Load Register A with the symbol's flag byte (operand set at 52B7H).
55EB
AND 40H E6 40
Keep bit 6, the "multiply defined" flag.
55ED
Multiply defined: JUMP to 562EH.
55F0
LD A,07H 3E 07
Load Register A with 07H.
55F2
LD (7633H),A 32 33 76
Store it into 7633H: seven line numbers fit on the heading line.
55F5
LD HL,763DH 21 3D 76
Point HL to 763DH, the list of references found before the definition line.
55F8
LD A,(764DH) 3A 4D 76
Load Register A with the number of entries from 764DH.
55FF
PUSH AF F5
Print the Saved References
Save the count.
5600
LD E,(HL) 5E
Load Register E with the low byte of a line address from the list.
5602
LD D,(HL) 56
Load Register D with the high byte.
5603
INC HL 23
Advance to the next entry.
5604
PUSH HL E5
Save the list pointer.
5605
EX DE,HL EB
HL = the line address.
5606
GOSUB to 56D3H to print its line number.
5609
POP HL E1
Restore the list pointer.
560A
POP AF F1
Restore the count.
560B
DEC A 3D
Count this entry.
560C
LOOP BACK to 55FFH while entries remain.
560E
LD A,18H 3E 18
Load Register A with 18H, the JR opcode.
5610
LD (5524H),A 32 24 55
Self-Modifying Code
Store it at 5524H: from now on label fields are not compared (the definition has been found).
5613
LD A,28H 3E 28
Load Register A with 28H, the JR Z opcode.
5615
LD (552FH),A 32 2F 55
Self-Modifying Code
Store it at 552FH: normal line scanning (operand fields are examined again).
5618
LD A,(7636H) 3A 36 76
Load Register A with the overflow count from 7636H.
561C
POP BC C1
Restore Register BC.
561D
POP HL E1
Restore Register HL.
561E
RET Z C8
No overflow: RETURN to the scan.
561F
POP HL E1
Overflow: discard the return address, because the scan resumes where the ninth reference was found.
5620
LD B,A 47
Register B = the characters that were left in that line.
5621
LD HL,(7637H) 2A 37 76
Load Register HL with the line address saved at 7637H ...
5624
LD (7634H),HL 22 34 76
... and make it the current line (7634H).
5627
LD HL,(7639H) 2A 39 76
Load Register HL with the scan position saved at 7639H.
562A
XOR A AF
Set the Z FLAG.
562B
JUMP to 5573H, which records that reference (now printed directly, because 5524H = 18H) and continues the scan.
562E
LD HL,75F8H 21 F8 75
Multiply Defined
Point HL to the text MULTIPLY DEFINED AT at 75F8H.
5631
GOSUB to 56BEH to print it.
5634
LD A,20H 3E 20
Load Register A with 20H, the JR NZ opcode.
5636
LD (559EH),A 32 9E 55
Self-Modifying Code
Store it at 559EH: further label matches print their line numbers (55A0H).
5639
LD A,18H 3E 18
Load Register A with 18H, the JR opcode.
563B
LD (552FH),A 32 2F 55
Self-Modifying Code
Store it at 552FH: every line ends after its label field, so only definitions are collected in this scan.
563E
LD A,04H 3E 04
Load Register A with 04H.
5640
LD (7633H),A 32 33 76
Store it into 7633H: four line numbers fit after the text.
5643
JUMP to 55A6H to return to the scan.
5646H - Symbol Table Listing: Record a Reference
Called from 5573H when the symbol appears in an operand field. After the heading (5524H = 18H) the line number is printed at once. Before the heading, up to eight line addresses are kept in the list at 763DH. A ninth reference saves the scan position (7637H, 7639H, 7636H) and switches to label-only scanning until the definition is found; 5618H then resumes from the saved position.
5646
PUSH HL E5
Save the scan pointer (HL).
5647
PUSH BC C5
Save the characters left (BC).
5648
LD A,(5524H) 3A 24 55
Load Register A with the opcode at 5524H.
564B
CP 18H FE 18
Compare with 18H (JR): has the heading been printed?
564D
Yes: JUMP to 55A0H to print the line number now.
5650
LD A,(764DH) 3A 4D 76
Load Register A with the number of saved references from 764DH.
5654
CP 09H FE 09
Compare with 09H.
5656
A ninth reference: JUMP to 566CH.
5658
LD (764DH),A 32 4D 76
Store the new count into 764DH.
565B
LD HL,(763BH) 2A 3B 76
Load Register HL with the list write pointer from 763BH.
565E
LD DE,(7634H) ED 5B 34 76
Load Register DE with the current line address from 7634H.
5662
LD (HL),E 73
Store the line address low byte in the list.
5663
INC HL 23
Advance the list pointer.
5664
LD (HL),D 72
Store the high byte.
5665
INC HL 23
Advance the list pointer.
5666
LD (763BH),HL 22 3B 76
Store it back into 763BH.
5669
JUMP to 55A6H to restore the registers and return.
566C
LD (7639H),HL 22 39 76
List Full
Save the scan position (HL) into 7639H.
566F
LD HL,(7634H) 2A 34 76
Load Register HL with the current line address from 7634H ...
5672
LD (7637H),HL 22 37 76
... and save it into 7637H.
5675
LD A,B 78
Load Register A with the characters left in the line (Register B) ...
5676
LD (7636H),A 32 36 76
... and save them into 7636H (non-zero marks the overflow).
5679
LD A,18H 3E 18
Load Register A with 18H, the JR opcode.
567B
LD (552FH),A 32 2F 55
Self-Modifying Code
Store it at 552FH: only label fields are scanned until the definition is found.
567E
POP BC C1
Restore Register BC.
567F
POP HL E1
Restore Register HL.
5680
POP AF F1
Discard the return address to 5576H.
5681
JUMP to 5508H to skip the rest of this line.
5684H - Symbol Table Listing: Compare the Name at HL
Register HL points to a character in the text that equals the symbol's first character, Register B = characters left in the line. Returns the Z FLAG set if the symbol's name follows and is not immediately followed by a letter or digit. If the line ends during the compare, the line is abandoned (56B2H).
5684
LD DE,(7650H) ED 5B 50 76
Load Register DE with the symbol name pointer from 7650H.
5688
LD A,00H 3E 00
Self-Modifying Code
Load Register A with the low byte of the address of the symbol's last character (operand set at 52BDH).
568A
CP E BB
Compare it with the low byte of the name pointer (Register E).
568B
The whole name has matched: JUMP to 5699H.
568D
INC DE 13
Advance the name pointer.
568E
INC HL 23
Advance the text pointer.
568F
DEC B 05
Count one text character.
5690
The line ended during the name: JUMP to 56B2H.
5693
LD A,(DE) 1A
Load Register A with the next name character.
5694
CP (HL) BE
Compare it with the text character.
5695
Equal: LOOP BACK to 5688H.
5698
RET C9
Different: RETURN with the NZ FLAG.
5699
LD A,B 78
Load Register A with the characters left (Register B).
569A
DEC A 3D
Subtract one.
569B
RET Z C8
The name ends the line: RETURN with the Z FLAG (a match).
569C
INC HL 23
Advance to the character after the name.
569E
LD A,(HL) 7E
Load Register A with that character.
569F
CP 5BH FE 5B
Compare with 5BH.
56A1
Above Z: JUMP to 56AFH (a match).
56A3
CP 41H FE 41
Compare with 41H (A).
56A5
A letter: JUMP to 56B0H (no match; the text identifier is longer).
56A7
CP 3AH FE 3A
Compare with 3AH.
56A9
3AH-40H: JUMP to 56AFH (a match).
56AB
CP 30H FE 30
Compare with 30H (0).
56AD
A digit: JUMP to 56B0H (no match).
56AF
XOR A AF
Set Register A to 00H.
56B0
OR A B7
Test Register A: the Z FLAG is set for a match, clear for a letter or digit.
56B2
POP AF F1
Discard the return address into the scan.
56B3
JUMP to 550CH for the next line.
56B6H - Symbol Table Listing: Output Helpers
Small output routines used by the listing. All output goes through 5939H (screen, or printer when 53BCH is set).
56B6
LD A,(HL) 7E
Print B Characters
Load Register A with the character at HL.
56B7
GOSUB to 5939H to print it.
56BB
Decrement Register B and LOOP BACK to 56B6H.
56BE
LD A,(HL) 7E
Print Until 03H
Load Register A with the character at HL.
56BF
CP 03H FE 03
Compare with 03H, the terminator.
56C1
RET Z C8
At the terminator: RETURN.
56C2
GOSUB to 5939H to print the character.
56C8
LD A,20H 3E 20
Print a Space
Load Register A with 20H.
56CA
JUMP to 5939H to print it.
56CD
Print B Spaces
GOSUB to 56C8H to print a space.
56D0
Decrement Register B and LOOP BACK to 56CDH.
56D3
LD A,(7633H) 3A 33 76
Print a Reference Line Number
Load Register A with the number of line numbers still room for on this output line (7633H).
56D7
Room left: JUMP to 56E3H.
56D9
Line full: GOSUB to 5937H to start a new line.
56DC
LD B,14H 06 14
Load Register B with 14H (20).
56DE
GOSUB to 56CDH to indent 20 spaces.
56E1
LD A,07H 3E 07
Seven line numbers fit on the new line.
56E3
DEC A 3D
Count this one.
56E4
LD (7633H),A 32 33 76
Store the count into 7633H.
56E7
LD E,(HL) 5E
Print a Line Number
Load Register E with the low byte of the line number at HL.
56E9
LD D,(HL) 56
Load Register D with the high byte.
56EA
EX DE,HL EB
HL = the line number.
56EB
JUMP to 5D75H to print it as five decimal digits and a space.
56EEH - Assembler: Index Displacement Range Check
Called from 66F9H with Register DE = an (IX+d) or (IY+d) displacement. Adds 80H: the result's high byte is 00H only when the displacement is -128 to +127. 6672H reports FIELD OVERFLOW when it is not.
56EE
PUSH HL E5
Save Register HL.
56EF
LD HL,0080H 21 80 00
Load Register HL with 0080H.
56F2
ADD HL,DE 19
Add the displacement.
56F3
LD A,H 7C
Load Register A with the high byte of the sum.
56F4
POP HL E1
Restore Register HL.
56F5
JUMP to 6672H, which reports FIELD OVERFLOW if Register A is not 00H.
56F8H - B Command: Return to DOS
The B entry of the command table. Puts the JP opcode (C3H) back into the DOS BREAK key vector at 4312H (6F00H replaced it with RET) and exits to the DOS.
56F8
LD A,C3H 3E C3
Load Register A with C3H, the JP opcode.
56FA
LD (4312H),A 32 12 43
Store it at 4312H, the first byte of the DOS BREAK key vector.
56FD
JUMP to the DOS at 402DH, the normal exit.
5700H - Display Character, Then Turn the Cursor On
Called from the command loop at 58F3H to display the * command prompt (Register A = 2AH). It sends the character in Register A through the common output routine at 5939H and then sends 0EH, the Level II video control code that turns the cursor on.
5700
GOSUB to 5939H to output the character in Register A (the prompt character passed by the caller) to the screen, or to the printer if 53BCH is non-zero.
5703
LD A,0EH 3E 0E
Load Register A with 0EH, the video driver control code that turns the blinking cursor on.
5705
JUMP to 5939H to output the 0EH cursor-on code. 5939H returns directly to the caller of 5700H.
5708H - Cassette-Only Cleanup on Return to the Command Loop
Reached from 71DAH when no disk file is active (762CH = 00H). It clears the appendage's DOS-error flag at 762EH and then jumps to the ROM routine that turns the cassette motor off.
5708
XOR A AF
Set Register A to 00H.
5709
LD (762EH),A 32 2E 76
Store 00H into 762EH, the appendage's DOS error flag (set to the error code by 726FH when a DOS call fails). Clearing it here means the next close at 71E4H will flush and close normally.
570C
JUMP to the Level II ROM routine at 01F8H, which turns the cassette motor off and returns to the caller of 71D5H (the command loop at 58E0H).
570FH - Unreferenced Copy of the ROM Video Driver (Dead Code)
Dead Code
Nothing in EDTASM/CMD jumps to, calls, or points at any address from 570FH to 57A9H (verified against every branch and every 16-bit operand in the file). These bytes have the same instruction sequence as parts of the Level II ROM video driver: the 32/64 character mode switch (OUT (FFH),A), the control-code dispatcher for codes 08H and 0AH-1FH, the screen scroll (a 03C0H-byte LDIR from 3C40H down to 3C00H), and the erase-to-end-of-line and erase-to-end-of-screen loops. The 16-bit operands that referred to Level II RAM have been changed (for example the ROM's port FFH image at 403DH, whose bit 3 marks 32 character mode, appears here as 5228H, which is the AND 07H instruction in EDTASM's symbol search), and several JR targets fall outside this block into unrelated EDTASM code, sometimes in the middle of an instruction. Because the block is never executed, those targets are shown but not linked, and the comments below describe what each instruction would do.
570F
JR Z,5763H in the ROM copy. If the Z FLAG is set, JUMP to 5763H (the width-mode test inside this block).
5711
OUT (FFH),A D3 FF
Output Register A to port FFH. On the Model I this port latch selects the 32/64 character display mode (and drives the cassette outputs).
5713
INC HL 23
Increment HL (a video RAM pointer in the ROM original).
5714
LD A,L 7D
Copy the low byte of the video pointer into Register A.
5715
AND FEH E6 FE
Clear bit 0 of Register A so the pointer lands on an even column (32 character mode uses every other position).
5717
LD L,A 6F
Put the even-aligned low byte back into Register L.
5719
OR A B7
Control Code Dispatcher (ROM Copy)
Test Register A (the character being displayed).
571A
RET Z C8
If A = 00H, RETURN.
571B
CP 05H FE 05
Compare Register A against 05H.
571D
JR Z,56A9H 28 8A
If A = 05H, JUMP to 56A9H. Not linked: 56A9H lies in EDTASM's symbol-name check routine and has nothing to do with this block.
571F
LD DE,5688H 11 88 56
Load Register DE with 5688H, a return address pushed for the handlers below. In EDTASM, 5688H is the self-modified LD A,00H in the symbol-name compare routine, so this return address only makes sense in the ROM original.
5722
PUSH DE D5
Push the 5688H return address onto the stack.
5723
CP 08H FE 08
Compare Register A against 08H (backspace).
5725
JR Z,56E1H 28 BA
If backspace, JUMP to 56E1H. Not linked: 56E1H is the LD A,07H inside EDTASM's cross-reference column routine at 56D3H, unrelated.
5727
CP 0AH FE 0A
Compare Register A against 0AH (line feed).
5729
If line feed, JUMP to 5781H (the new-line handler in this block).
572C
CP 0DH FE 0D
Compare Register A against 0DH (carriage return).
572E
If carriage return, JUMP to 5781H (the new-line handler in this block).
5731
CP 0EH FE 0E
Compare Register A against 0EH (cursor on).
5733
JR Z,56C7H 28 92
If 0EH, JUMP to 56C7H. Not linked: 56C7H is the offset byte of the JR 56BEH at 56C6H in EDTASM, not an instruction.
5735
CP 0FH FE 0F
Compare Register A against 0FH (cursor off).
5737
JR Z,56CEH 28 95
If 0FH, JUMP to 56CEH. Not linked: 56CEH is the middle of the CALL 56C8H at 56CDH in EDTASM.
5739
CP 17H FE 17
Compare Register A against 17H (select 32 character mode).
573B
JR Z,5709H 28 CC
If 17H, JUMP to 5709H. Not linked: 5709H is the LD (762EH),A in the live 5708H routine, which is unrelated.
573D
CP 18H FE 18
Compare Register A against 18H (backspace the cursor).
573F
JR Z,56EDH 28 AC
If 18H, JUMP to 56EDH. Not linked: 56EDH is the middle of the JP 5D75H at 56EBH in EDTASM.
5741
CP 19H FE 19
Compare Register A against 19H (advance the cursor).
5743
JR Z,56FFH 28 BA
If 19H, JUMP to 56FFH. Not linked: 56FFH is the middle of the JP 402DH at 56FDH in EDTASM.
5745
CP 1AH FE 1A
Compare Register A against 1AH (cursor down).
5747
JR Z,56FAH 28 B1
If 1AH, JUMP to 56FAH. Not linked: 56FAH is the LD (4312H),A in EDTASM's B command routine at 56F8H, unrelated.
5749
CP 1BH FE 1B
Compare Register A against 1BH (cursor up).
574B
JR Z,5704H 28 B7
If 1BH, JUMP to 5704H, which is the operand byte of the LD A,0EH at 5703H. Not linked.
574D
CP 1CH FE 1C
Compare Register A against 1CH (home the cursor).
574F
JR Z,56D3H 28 82
If 1CH, JUMP to 56D3H. Not linked: 56D3H is EDTASM's cross-reference column routine, unrelated.
5751
CP 1DH FE 1D
Compare Register A against 1DH (cursor to start of line).
5753
If 1DH, JUMP to 5770H in this block.
5755
CP 1EH FE 1E
Compare Register A against 1EH (erase to end of line).
5757
If 1EH, JUMP to 5790H in this block.
5759
CP 1FH FE 1F
Compare Register A against 1FH (erase to end of screen).
575B
If 1FH, JUMP to 5799H in this block.
575D
RET C9
Any other control code: RETURN.
575E
LD (HL),A 77
Store Character (ROM Copy)
Store the character in Register A at the video RAM address in HL.
575F
INC HL 23
Advance HL to the next screen position.
5760
LD A,(5228H) 3A 28 52
Load Register A from 5228H. In the ROM original this operand is 403DH (the saved port FFH value, bit 3 = 32 character mode); 5228H is the AND 07H instruction in EDTASM's symbol search, not a data byte.
5763
AND 08H E6 08
Keep only bit 3 of Register A (the 32 character mode bit in the ROM original).
5765
If bit 3 is clear (64 character mode), JUMP to 5768H.
5767
INC HL 23
32 character mode: advance HL one more position.
5768
LD A,H 7C
Load Register A with the high byte of the video pointer.
5769
CP 40H FE 40
Compare against 40H: has the pointer passed the end of video RAM (3FFFH)?
576B
RET NZ C0
If not past the end, RETURN.
576C
LD DE,FFC0H 11 C0 FF
Load Register DE with FFC0H (-64).
576F
ADD HL,DE 19
Move HL back one line (64 bytes) so it points at the start of the last screen line.
5770
PUSH HL E5
Save HL (the cursor position) on the stack.
5771
LD DE,3C00H 11 00 3C
Scroll the Screen (ROM Copy)
Load Register DE with 3C00H, the first byte of video RAM (destination).
5774
LD HL,3C40H 21 40 3C
Load Register HL with 3C40H, the first byte of the second screen line (source).
5777
PUSH BC C5
Save Register BC.
5778
LD BC,03C0H 01 C0 03
Load Register BC with 03C0H (960), the number of bytes in screen lines 2-16.
577B
LDIR ED B0
Copy lines 2-16 up one line.
577D
POP BC C1
Restore Register BC.
577E
EX DE,HL EB
Exchange so HL = 3FC0H, the start of the last screen line.
577F
JUMP to 579AH to blank the last line.
5781
LD A,L 7D
New Line (ROM Copy)
Load Register A with the low byte of the cursor address.
5782
AND C0H E6 C0
Keep bits 6-7 to find the start of the current 64-byte line.
5784
LD L,A 6F
Put it back in Register L: HL = start of the current line.
5785
PUSH HL E5
Save that address.
5786
LD DE,0040H 11 40 00
Load Register DE with 0040H (64, one screen line).
5789
ADD HL,DE 19
Point HL at the start of the next line.
578A
LD A,H 7C
Load Register A with the high byte of the new address.
578B
CP 40H FE 40
Compare against 40H: has it moved past video RAM?
578D
If so, JUMP to 5771H to scroll the screen.
578F
POP DE D1
Discard the saved line start into Register DE.
5790
PUSH HL E5
Erase to End of Line (ROM Copy)
Save the cursor address.
5791
LD D,H 54
Load Register D with the high byte of the cursor address.
5792
LD A,L 7D
Load Register A with the low byte of the cursor address.
5793
OR 3FH F6 3F
Set the low 6 bits: the last column of this line.
5795
LD E,A 5F
Register DE = address of the last column of this line.
5796
INC DE 13
Register DE = the first address past this line (the stop address).
5797
JUMP to 579DH to fill with spaces.
5799
PUSH HL E5
Erase to End of Screen (ROM Copy)
Save the cursor address.
579A
LD DE,4000H 11 00 40
Load Register DE with 4000H, the first address past video RAM (the stop address).
579D
LD (HL),20H 36 20
Fill Loop
Store a space (20H) at the address in HL.
57A0
LD A,H 7C
Load Register A with the high byte of HL.
57A1
CP D BA
Compare it with the high byte of the stop address in Register D.
57A2
If different, LOOP BACK to 579DH.
57A4
LD A,L 7D
Load Register A with the low byte of HL.
57A5
CP E BB
Compare it with the low byte of the stop address in Register E.
57A6
If different, LOOP BACK to 579DH.
57A8
POP HL E1
Restore the cursor address into HL.
57AAH - Unreferenced Copy of the ROM Printer Driver (Dead Code)
Dead Code
Nothing in EDTASM/CMD reaches 57AAH-57F5H. This block has the same instruction sequence as the Level II ROM printer driver at 058DH-05D8H, with only the internal JR offsets changed: Register C holds the character, Register IX points to a printer Device Control Block (IX+03H = lines per page, IX+04H = line counter), and 37E8H is the memory-mapped printer port. EDTASM itself prints by calling the ROM at 003BH (see 5954H), so this copy is never used.
57AA
LD A,C 79
Load Register A with the character to print (Register C).
57AB
OR A B7
Test Register A for 00H.
57AC
If A = 00H (a status request), JUMP to 57EEH to read the printer status.
57AE
CP 0BH FE 0B
Compare Register A against 0BH (vertical tab / top of form).
57B0
If 0BH, JUMP to 57BCH to space to the top of the next page.
57B2
CP 0CH FE 0C
Compare Register A against 0CH (form feed).
57B4
If not a form feed, JUMP to 57D1H to print the character normally.
57B6
XOR A AF
Form feed: set Register A to 00H.
57B7
OR (IX+03H) DD B6 03
OR in IX+03H, the lines-per-page value from the DCB.
57BA
If lines per page = 00H (paging disabled), JUMP to 57D1H and send the 0CH to the printer.
57BC
LD A,(IX+03H) DD 7E 03
Load Register A with IX+03H, the lines per page.
57BF
SUB (IX+04H) DD 96 04
Subtract IX+04H, the lines already printed on this page. Register A = lines left on the page.
57C2
LD B,A 47
Copy that line count into Register B as the loop counter.
57C3
Line Feed Loop
GOSUB to 57EEH to read the printer status (Z FLAG set = ready).
57C6
If the printer is not ready (NZ), LOOP BACK to 57C3H and test again.
57C8
LD A,0AH 3E 0A
Load Register A with 0AH (line feed).
57CA
LD (37E8H),A 32 E8 37
Send the line feed to the printer port at 37E8H.
57CD
Decrement the line count in Register B and LOOP BACK to 57C3H until the page is finished.
57CF
JUMP to 57E9H to reset the line counter.
57D1
PUSH AF F5
Print a Character
Save the character (Register A) on the stack.
57D2
Wait Until Ready
GOSUB to 57EEH to read the printer status.
57D5
If not ready (NZ), LOOP BACK to 57D2H.
57D7
POP AF F1
Restore the character into Register A.
57D8
LD (37E8H),A 32 E8 37
Send the character to the printer port at 37E8H.
57DB
CP 0DH FE 0D
Compare the character against 0DH (carriage return).
57DD
RET NZ C0
If it was not a carriage return, RETURN.
57DE
INC (IX+04H) DD 34 04
Carriage return: increment IX+04H, the lines-printed counter.
57E1
LD A,(IX+04H) DD 7E 04
Load Register A with the updated line count (IX+04H).
57E4
CP (IX+03H) DD BE 03
Compare it with IX+03H, the lines per page.
57E7
LD A,C 79
Restore the original character from Register C into Register A (flags are not changed).
57E8
RET NZ C0
If the page is not full (NZ), RETURN.
57E9
LD (IX+04H),00H DD 36 04 00
Store 00H into IX+04H: the lines-printed counter restarts for the new page.
57EE
LD A,(37E8H) 3A E8 37
Printer Status
Read the printer status byte from 37E8H.
57F1
AND F0H E6 F0
Keep the upper four status bits.
57F3
CP 30H FE 30
Compare against 30H (selected and not busy). The Z FLAG is set when the printer is ready.
57F5
RET C9
RETURN with the Z FLAG showing the ready state.
57F6H - Unreferenced Copy of the ROM DCB, Keyboard, and Delay Routines (Dead Code)
Dead Code
Nothing in EDTASM/CMD reaches 57F6H-5833H; the only reference into this block (the CALL 5805H at 5817H) is inside it. The bytes have the same form as the Level II ROM routines at 0013H-0064H: the device-call entry points that set B = 01H (input), 02H (output) or 04H (control) before dispatching through a Device Control Block, the keyboard/video/printer entry points that load DE with a DCB address, the wait-for-key loop at 0049H, the 16-byte keyboard special-key table at 0050H, and the BC delay loop at 0060H. The DCB and dispatcher addresses were changed from the ROM's 4015H, 401DH, 4025H and 03C2H to 5500H, 5508H, 5510H and 55CEH, which are EDTASM code (55CEH is the last byte of the CALL 56C8H at 55CCH), so none of this could run correctly.
57F6
PUSH BC C5
Save Register BC (ROM 0013H: input from a device).
57F7
LD B,01H 06 01
Load Register B with 01H, the "input" request code.
57F9
JUMP to 5814H, the common dispatch.
57FB
PUSH BC C5
Save Register BC (ROM 001BH: output to a device).
57FC
LD B,02H 06 02
Load Register B with 02H, the "output" request code.
57FE
JUMP to 5814H, the common dispatch.
5800
PUSH BC C5
Save Register BC (ROM 0023H: control request).
5801
LD B,04H 06 04
Load Register B with 04H, the "control" request code.
5803
JUMP to 5814H, the common dispatch.
5805
LD DE,5500H 11 00 55
Load Register DE with 5500H (the ROM copy's keyboard DCB address; 5500H is EDTASM code).
5808
JUMP to 57F6H for an input request.
580A
LD DE,5508H 11 08 55
Load Register DE with 5508H (the ROM copy's video DCB address; EDTASM code).
580D
JUMP to 57FBH for an output request.
580F
LD DE,5510H 11 10 55
Load Register DE with 5510H (the ROM copy's printer DCB address; EDTASM code).
5812
JUMP to 57FBH for an output request.
5814
JP 55CEH C3 CE 55
JUMP to 55CEH. Not linked: in the ROM this is JP 03C2H (the DCB dispatcher); 55CEH is the last byte of the CALL 56C8H at 55CCH.
5817
Wait for a Key (ROM 0049H Copy)
GOSUB to 5805H to scan the keyboard through the (invalid) DCB.
581A
OR A B7
Test the key code in Register A.
581B
RET NZ C0
If a key was returned (NZ), RETURN with it in Register A.
581C
No key: LOOP BACK to 5817H.
581E-582D
DEFB 0DH, 0DH, 1FH, 1FH, 01H, 01H, 5BH, 1BH, 0AH, 1AH, 08H, 18H, 09H, 19H, 20H, 20H 0D 0D 1F 1F 01 01 5B 1B 0A 1A 08 18 09 19 20 20
Keyboard Special-Key Table (ROM 0050H Copy)
Unshifted/shifted code pairs for ENTER (0DH/0DH), CLEAR (1FH/1FH), BREAK (01H/01H), up arrow (5BH/1BH), down arrow (0AH/1AH), left arrow (08H/18H), right arrow (09H/19H) and space (20H/20H). Nothing reads this copy.
582E
DEC BC 0B
Delay Loop (ROM 0060H Copy)
Decrement the delay count in Register BC.
582F
LD A,B 78
Load Register A with the high byte of the count.
5830
OR C B1
OR in the low byte: Z FLAG set when BC = 0000H.
5831
If BC is not zero, LOOP BACK to 582EH.
5834H - Get a Key (Wait, Filter, and Force Upper Case)
Waits for a key through the ROM keyboard routine at 0049H and returns it in Register A. Six control keys are returned as-is (the table at 5850H). Any other code below 1AH is ignored and the routine waits for another key. Everything else goes through the appendage routine at 7062H, which converts lower case a-z to upper case. Registers DE and HL are preserved. Called by the command-line input routine (5B49H), the line editor (5FE7H, 6052H, 608CH, 60E4H), and the pause handler at 5866H.
5834
PUSH DE D5
Save Register DE (the caller's value) on the stack.
5835
PUSH HL E5
Save Register HL (the caller's value) on the stack.
5836
Key Loop
GOSUB to the Level II ROM at 0049H, which waits until a key is pressed and returns its code in Register A.
5839
LD HL,5850H 21 50 58
Point HL to the table of six accepted control keys at 5850H.
583C
LD E,06H 1E 06
Load Register E with 06H, the number of entries in that table.
583E
CP (HL) BE
Table Scan
Compare the key code in Register A against the table entry at HL.
583F
INC HL 23
Advance HL to the next table entry (flags are not changed).
5840
If the key matches a table entry (Z FLAG set), JUMP to 584DH to return it unchanged.
5842
DEC E 1D
Decrement the entry count in Register E.
5843
If entries remain, LOOP BACK to 583EH.
5845
CP 1AH FE 1A
Not in the table: compare the key code against 1AH.
5847
If the key is below 1AH (an unaccepted control code), JUMP back to 5836H and wait for another key.
5849
GOSUB to 7062H in the appendage, which converts a lower case letter to upper case. If the key is 7BH-7FH, 7062H does not return here: it jumps back to 5836H to wait for another key, leaving this CALL's return address (584CH) on the stack.
584C
NOP 00
Patch Space
NOP. The 7062H call occupies 5849H-584BH; this byte is unused.
584D
POP HL E1
Restore Register HL.
584E
POP DE D1
Restore Register DE.
584F
RET C9
RETURN with the key code in Register A.
5850-5855
DEFB 08H, 09H, 0AH, 0DH, 18H, 01H 08 09 0A 0D 18 01
Accepted Control Keys
The six codes below 1AH that 5834H returns: 08H (left arrow / backspace), 09H (right arrow / tab), 0AH (down arrow), 0DH (ENTER), 18H (shift left arrow), 01H (BREAK). Register E = 06H at 583CH matches this count.
5856H - Check the Keyboard for BREAK or Pause
Scans the keyboard once without waiting (ROM 002BH). Returns at once with Z set if no key is down, or with the key in Register A if it is not special. BREAK (01H) abandons the current command and goes to the command loop at 58DAH. Shift-@ (60H) pauses output: 5866H waits for another key and that key is tested the same way. Called during listing and assembly (5E48H, 6464H, 6499H). Register DE is preserved.
5856
PUSH DE D5
Save Register DE on the stack (the ROM scan at 002BH changes it).
5857
GOSUB to the Level II ROM keyboard scan at 002BH. Register A returns the key code, or 00H if no key is pressed.
585A
POP DE D1
Restore Register DE.
585B
OR A B7
Test the key code in Register A.
585C
RET Z C8
If no key (A = 00H), RETURN with the Z FLAG set.
585D
RET M F8
If the code has bit 7 set, RETURN with it.
585E
CP 01H FE 01
Test the Key
Compare the key code against 01H (BREAK).
5860
If BREAK, JUMP to 58DAH: reset the stack and return to the * command prompt.
5863
CP 60H FE 60
Compare the key code against 60H (shift-@, the pause key).
5865
RET NZ C0
Any other key: RETURN with the code in Register A and the NZ FLAG set.
5866
Pause
GOSUB to 5834H to wait for the next key (returned in Register A).
5869
JUMP back to 585EH to test that key (BREAK aborts, shift-@ pauses again, anything else resumes).
586BH - Prompt READY CASSETTE (Cassette Only) and Wait
Called before a cassette read (5F50H) or write (6121H). When the appendage has a disk file open (762CH non-zero), 7046H skips both the message and the wait and returns to this routine's caller.
586B
LD HL,5AE4H 21 E4 5A
Point HL to the message READY CASSETTE at 5AE4H.
586E
GOSUB to 7046H. If no disk file is active, it displays the message (followed by a carriage return) and returns here. If a disk file is active, it discards this return address and returns directly to the caller of 586BH.
5871
Cassette: JUMP to 5866H to wait for a key; BREAK aborts, shift-@ waits again, any other key continues.
5873H - Assembler Switch Table and Flags
Table searched by the assembler command at 6419H (via 627CH) when parsing A command switches that follow a slash. Each entry is a length byte (02H), the two-letter switch name, and a flag byte that 6424H increments when the switch is given. The flags are cleared at 63EEH-63FCH before each assembly.
5873-5875
DEFB 02H, 4EH, 4CH 02 4E 4C
Switch NL (no listing): length 02H, then "NL".
5876
DEFB 00H 00
NL Flag
Non-zero = do not produce the assembly listing. Read at 618FH, 6EE8H (via 6EE5H).
5877-5879
DEFB 02H, 4EH, 4FH 02 4E 4F
Switch NO (no object code): length 02H, then "NO".
587A
DEFB 00H 00
NO Flag
Non-zero = do not write object code. Read at 648AH and at 7240H in the appendage (skips the object file prompt).
587B-587D
DEFB 02H, 4CH, 50H 02 4C 50
Switch LP (listing to printer): length 02H, then "LP".
587E
DEFB 00H 00
LP Flag
Non-zero = also send the listing to the printer. Read at 6194H, 6454H, 6E05H.
587F-5881
DEFB 02H, 4EH, 53H 02 4E 53
Switch NS (no symbol table): length 02H, then "NS".
5882
DEFB 00H 00
NS Flag
Non-zero = do not print the symbol table. Returned in Register A by the appendage at 70A5H and tested at 6451H.
5883-5885
DEFB 02H, 57H, 45H 02 57 45
Switch WE (wait on errors): length 02H, then "WE".
5886
DEFB 00H 00
WE Flag
Non-zero = pause after a line with an error. Read and changed at 64A2H-64AFH.
5887
DEFB 00H 00
End of the switch table.
5888-5889
DEFW 0064H 64 00
Empty-Buffer Line Record
Line number 100 (0064H). When the text buffer is empty, 5917H points the current-line pointer at 5311H to this word, so a following I command starts numbering at line 100.
588AH - Cold Start: Initialize the Editor/Assembler
Reached from the program entry point at 6F00H. Empties the text buffer, sets the symbol table top from the DOS high-memory pointer, sets default values, clears the screen and shows the TRS-80 EDITOR/ASSEMBLER 1.1 banner, then falls into the command loop at 58DAH.
588A
LD HL,7700H 21 00 77
Load Register HL with 7700H, the start of the text buffer (the first byte after the loaded program). This operand is also read as data at 6F51H and 6F6BH.
588D
LD (5315H),HL 22 15 53
Store 7700H into 5315H, the end-of-text pointer: the text buffer is empty.
5890
LD (HL),FFH 36 FF
Store FFH at 7700H, the first byte of the end-of-text marker.
5892
INC HL 23
Advance HL to 7701H.
5893
LD (HL),FFH 36 FF
Store FFH at 7701H. The two bytes FFH FFH mark the end of the text (a line number of FFFFH).
5895
JUMP to 589CH, skipping the five unreferenced bytes at 5897H.
5897-589B
DEFB 47H, 2FH, 77H, 0BEH, 70H 47 2F 77 BE 70
Unreferenced Bytes
Skipped by the JR at 5895H and not referenced anywhere. As instructions they read LD B,A / CPL / LD (HL),A / CP (HL) / LD (HL),B (a write-and-compare RAM test sequence).
589C
LD HL,(4049H) 2A 49 40
Load Register HL with the contents of 4049H, the DOS pointer to the highest usable memory address.
589F
LD (5313H),HL 22 13 53
Store it into 5313H, the symbol table top. The assembler starts the symbol table there (63E3H) and builds it downward.
58A2
LD HL,000AH 21 0A 00
Load Register HL with 000AH (10).
58A5
LD (5317H),HL 22 17 53
Store 10 into 5317H, the default line number increment used by the I and N commands.
58A8
LD HL,5300H 21 00 53
Point HL to 5300H, the find string length.
58AB
LD (HL),01H 36 01
Set the find string length at 5300H to 01H.
58AD
INC HL 23
Advance HL to 5301H, the first byte of the find string.
58AE
LD (HL),0DH 36 0D
Set the find string to a single 0DH, so an F command with no text searches for a carriage return.
58B0
LD SP,54FEH 31 FE 54
Set the stack pointer to 54FEH, the top of EDTASM's stack area.
58B3
XOR A AF
Set Register A to 00H.
58B4
LD (53BAH),A 32 BA 53
Clear 53BAH, the output-to-file flag (character output goes to the screen, not to the tape or disk file).
58B7
LD (53BCH),A 32 BC 53
Clear 53BCH, the printer flag (character output does not go to the printer).
58BA
GOSUB to the Level II ROM at 01F8H to turn the cassette motor off.
58BD
EI FB
Enable interrupts.
58BE-58C1
NOP x 4 00 x 4
Patch Space
Four unused NOP bytes (00H).
58C2
LD A,1CH 3E 1C
Load Register A with 1CH, the video code that homes the cursor.
58C4
GOSUB to 5939H to output the 1CH.
58C7
LD A,1FH 3E 1F
Load Register A with 1FH, the video code that erases to the end of the screen.
58C9
GOSUB to 5939H to clear the screen.
58CC
LD A,0EH 3E 0E
Load Register A with 0EH, the video code that turns the cursor on.
58CE
GOSUB to 5939H to output the 0EH.
58D1
LD HL,5AC9H 21 C9 5A
Point HL to the banner TRS-80 EDITOR/ASSEMBLER 1.1 at 5AC9H.
58D4
GOSUB to 592FH to display the banner. 592FH ends every message with a carriage return.
58D7
GOSUB to 5937H to output a carriage return. Many commands end by jumping here (for example 58D7H is the target of 5B5BH, 6075H, 648EH, 6BC3H and the appendage's 7285H), which gives a blank line before the command loop at 58DAH.
58DAH - Command Loop
The editor's main loop, reached after every command, error and BREAK. It resets the stack, lets the appendage finish any disk file (71D5H), pushes 58DAH so a command handler's RET comes back here, shows the * prompt and reads a command line into 5327H. The first non-space character is looked up in the command table at 5B05H and the handler is entered by a RET with its address on the stack.
58DA
LD SP,54FEH 31 FE 54
Set the stack pointer to 54FEH, the top of EDTASM's stack.
58DD
GOSUB to 71D5H in the appendage: if a disk file is open it is finished and closed; otherwise the DOS error flag is cleared and the cassette motor is turned off (5708H).
58E0
LD BC,58DAH 01 DA 58
Load Register BC with 58DAH, the address of this loop ...
58E3
PUSH BC C5
... and push it, so each command handler returns here.
58E4
XOR A AF
Set Register A to 00H.
58E5
LD HL,53BAH 21 BA 53
Point HL to 53BAH.
58E8
LD (HL),A 77
Clear the output-to-file flag (53BAH).
58E9
INC HL 23
Point HL to 53BBH.
58EA
LD (HL),FFH 36 FF
Set the output column (53BBH) to FFH; printing the prompt makes it 00H.
58EC
INC HL 23
Point HL to 53BCH.
58ED
LD (HL),A 77
Clear the printer flag (53BCH).
58EE
LD (53C5H),A 32 C5 53
Clear 53C5H, the "no line numbers" flag set by T.
58F1
LD A,2AH 3E 2A
Load Register A with 2AH (*), the prompt.
58F3
GOSUB to 5700H to display it and turn the cursor on.
58F6
LD C,01H 0E 01
Load Register C with 01H so that an up or down arrow is accepted as a whole command line.
58F8
GOSUB to 5B41H to read the command line into 5327H (count in 53AAH).
58FB
GOSUB to 5BBBH to get its first non-space character.
58FE
RET Z C8
An empty line: RETURN to 58DAH (the pushed address).
58FF
LD HL,5B05H 21 05 5B
Point HL to the command table at 5B05H.
5902
LD B,0FH 06 0F
Load Register B with 0FH, the number of table entries.
5904
CP (HL) BE
Table Search
Compare the command character with the table entry.
5906
LD E,(HL) 5E
Load Register E with the handler address low byte.
5908
LD D,(HL) 56
Load Register D with the high byte.
5909
INC HL 23
Advance HL to the next entry (the flags from the compare are kept).
590A
No match: JUMP to 5926H.
590C
PUSH DE D5
Push the handler address; the RET below enters it.
590D
LD HL,(5315H) 2A 15 53
Load Register HL with the end-of-text pointer from 5315H.
5910
LD DE,7700H 11 00 77
Load Register DE with 7700H, the start of the text buffer.
5913
GOSUB to 5DC2H to compare them. The Z FLAG is set if the buffer is empty.
5916
RET NZ C0
Text present: RETURN, which enters the handler.
5917
LD HL,5888H 21 88 58
The buffer is empty: point HL to 5888H, the dummy line record (line 100) ...
591A
LD (5311H),HL 22 11 53
... and make it the current line (5311H).
591D
LD A,B 78
Load Register A with the entry number in Register B (15 for the first entry, 1 for the last).
591E
CP 04H FE 04
Compare with 04H.
5920
RET C D8
L, I or B (B below 04H): RETURN, which enters the handler.
5921
LD HL,59C6H 21 C6 59
Any other command: point HL to NO TEXT IN BUFFER at 59C6H.
5924
JUMP to 592BH to display it.
5926
Decrement the entry count and LOOP BACK to 5904H.
5928
LD HL,59A2H 21 A2 59
Not a command: point HL to ILLEGAL COMMAND at 59A2H.
592B
LD BC,58DAH 01 DA 58
Error Message Entry
Load Register BC with 58DAH ...
592E
PUSH BC C5
... and push it, so the message display returns to the command loop.
592FH - Display a Message
Prints the characters at HL through 5939H until one with bit 7 set has been printed, then prints a carriage return (it falls into 5937H). HL is left after the message.
592F
LD A,(HL) 7E
Load Register A with the character at HL.
5931
GOSUB to 5939H to print it (5939H prints only the low 7 bits on the screen or printer).
5934
RLCA 07
Rotate bit 7 into the CARRY FLAG.
5935
Bit 7 clear: LOOP BACK to 592FH.
5937
LD A,0DH 3E 0D
Carriage Return
Load Register A with 0DH and fall into 5939H.
5939H - Output a Character
Sends Register A to the tape or disk file when the output-to-file flag (53BAH) is set (the W command); otherwise displays it (ROM 0033H) or prints it (ROM 003BH when 53BCH is set). Keeps the output column at 53BBH and expands a tab (09H) to spaces up to the next multiple of 8. All registers and flags are preserved.
5939
PUSH AF F5
Save Register A and the flags.
593A
PUSH HL E5
Save Register HL.
593B
LD HL,53BAH 21 BA 53
Point HL to 53BAH, the output-to-file flag.
593E
INC (HL) 34
Increment it ...
593F
DEC (HL) 35
... and decrement it: the Z FLAG is set if it is 00H.
5940
INC HL 23
Point HL to 53BBH, the output column.
5941
PUSH AF F5
Save the character and the result of the test.
5942
Output to file (NZ): GOSUB to 710CH to write the character to the tape or, when the appendage has a disk file open, to the disk file.
5945
POP AF F1
Restore the character and the test result.
5946
Output to file: JUMP to 595CH; nothing is displayed.
5948
CP 09H FE 09
Compare the character with 09H (tab).
594A
A tab: JUMP to 595FH to expand it.
594C
INC (HL) 34
Count one column (53BBH).
594D
AND 7FH E6 7F
Clear bit 7 of the character.
594F
INC HL 23
Point HL to 53BCH, the printer flag.
5950
INC (HL) 34
Increment it ...
5951
DEC (HL) 35
... and decrement it: the Z FLAG is set if it is 00H.
5952
PUSH DE D5
Save Register DE (the ROM routines change it).
5953
PUSH AF F5
Save the character and the result of the test.
5954
Printer on: GOSUB to the Level II ROM printer routine at 003BH.
5957
POP AF F1
Restore the character and the test result.
5958
Printer off: GOSUB to the Level II ROM display routine at 0033H.
595B
POP DE D1
Restore Register DE.
595C
POP HL E1
Restore Register HL.
595D
POP AF F1
Restore Register A and the flags.
595F
LD A,20H 3E 20
Tab
Load Register A with 20H (space).
5961
GOSUB to 5939H to print it (this advances the column at 53BBH).
5964
LD A,(HL) 7E
Load Register A with the output column.
5965
AND 07H E6 07
Keep bits 0-2.
5967
Not yet at a multiple of 8: LOOP BACK to 595FH.
5969
JUMP to 595CH to restore the registers and return.
596BH - Editor and Assembler Messages (Data)
Data
Text displayed by 592FH, which prints characters until it has printed one with bit 7 set and then prints a carriage return. The last character of each message therefore has bit 7 set (for example C4H is "D" + 80H). The error messages are shown by 592BH, which also pushes 58DAH so the display returns to the command loop; assembler errors pass the message address in DE to 614BH instead. The NONAME default file name at the end has no terminator because it is used as a fixed 6-byte name.
596B-597A
DEFM "STRING NOT FOUND" 53 54 52 49 4E 47 20 4E 4F 54 20 46 4F 55 4E C4
Message STRING NOT FOUND. The final byte C4H is "D" with bit 7 set. Used at 5DF3H (F command, text not found).
597B-598A
DEFM "BAD PARAMETER(S)" 42 41 44 20 50 41 52 41 4D 45 54 45 52 28 53 A9
Message BAD PARAMETER(S). The final byte A9H is ")" with bit 7 set. Used at 5D24H (bad command parameter; also the appendage error exit at 6FADH).
598B-5996
DEFM "NO SUCH LINE" 4E 4F 20 53 55 43 48 20 4C 49 4E C5
Message NO SUCH LINE. The final byte C5H is "E" with bit 7 set. Used at 5EB7H (line number not in the text).
5997-59A1
DEFM "BUFFER FULL" 42 55 46 46 45 52 20 46 55 4C CC
Message BUFFER FULL. The final byte CCH is "L" with bit 7 set. Used at 5DBCH (memory-full test).
59A2-59B0
DEFM "ILLEGAL COMMAND" 49 4C 4C 45 47 41 4C 20 43 4F 4D 4D 41 4E C4
Message ILLEGAL COMMAND. The final byte C4H is "D" with bit 7 set. Used at 5928H (command letter not in the table at 5B05H).
59B1-59C5
DEFM "LINE NUMBER TOO LARGE" 4C 49 4E 45 20 4E 55 4D 42 45 52 20 54 4F 4F 20 4C 41 52 47 C5
Message LINE NUMBER TOO LARGE. The final byte C5H is "E" with bit 7 set. Used at 5C3BH (line numbering passed 65535).
59C6-59D6
DEFM "NO TEXT IN BUFFER" 4E 4F 20 54 45 58 54 20 49 4E 20 42 55 46 46 45 D2
Message NO TEXT IN BUFFER. The final byte D2H is "R" with bit 7 set. Used at 5921H (a command that needs text was typed while the buffer is empty).
59D7-59DF
DEFM "BAD LABEL" 42 41 44 20 4C 41 42 45 CC
Message BAD LABEL. The final byte CCH is "L" with bit 7 set. Used at 6533H (assembler error).
59E0-59F2
DEFM "BRANCH OUT OF RANGE" 42 52 41 4E 43 48 20 4F 55 54 20 4F 46 20 52 41 4E 47 C5
Message BRANCH OUT OF RANGE. The final byte C5H is "E" with bit 7 set. Used at 686EH (assembler error: JR/DJNZ target too far).
59F3-5A09
DEFM "ILLEGAL ADDRESSING MODE" 49 4C 4C 45 47 41 4C 20 41 44 44 52 45 53 53 49 4E 47 20 4D 4F 44 C5
Message ILLEGAL ADDRESSING MODE. The final byte C5H is "E" with bit 7 set. Used at 66E2H (assembler error).
5A0A-5A17
DEFM "ILLEGAL OPCODE" 49 4C 4C 45 47 41 4C 20 4F 50 43 4F 44 C5
Message ILLEGAL OPCODE. The final byte C5H is "E" with bit 7 set. Used at 6569H (assembler error: mnemonic not in the table).
5A18-5A2A
DEFM "MISSING INFORMATION" 4D 49 53 53 49 4E 47 20 49 4E 46 4F 52 4D 41 54 49 4F CE
Message MISSING INFORMATION. The final byte CEH is "N" with bit 7 set. Used at 61D0H (assembler error: operand missing).
5A2B-5A3A
DEFM "NO END STATEMENT" 4E 4F 20 45 4E 44 20 53 54 41 54 45 4D 45 4E D4
Message NO END STATEMENT. The final byte D4H is "T" with bit 7 set. Used at 6B80H (assembler error: the text ended without an END line).
5A3B-5A4D
DEFM "MULTIPLE DEFINITION" 4D 55 4C 54 49 50 4C 45 20 44 45 46 49 4E 49 54 49 4F CE
Message MULTIPLE DEFINITION. The final byte CEH is "N" with bit 7 set. Used at 6629H (assembler error).
5A4E-5A5B
DEFM "FIELD OVERFLOW" 46 49 45 4C 44 20 4F 56 45 52 46 4C 4F D7
Message FIELD OVERFLOW. The final byte D7H is "W" with bit 7 set. Used at 6674H (assembler error: value does not fit in a byte).
5A5C-5A72
DEFM "MULTIPLY DEFINED SYMBOL" 4D 55 4C 54 49 50 4C 59 20 44 45 46 49 4E 45 44 20 53 59 4D 42 4F CC
Message MULTIPLY DEFINED SYMBOL. The final byte CCH is "L" with bit 7 set. Used at 65F8H (assembler error).
5A73-5A87
DEFM "SYMBOL TABLE OVERFLOW" 53 59 4D 42 4F 4C 20 54 41 42 4C 45 20 4F 56 45 52 46 4C 4F D7
Message SYMBOL TABLE OVERFLOW. The final byte D7H is "W" with bit 7 set. Used at 65C7H (assembler error: symbol table would overwrite the text).
5A88-5A93
DEFM "TOTAL ERRORS" 54 4F 54 41 4C 20 45 52 52 4F 52 D3
Message TOTAL ERRORS. The final byte D3H is "S" with bit 7 set. Used at 6448H (printed before the error count at the end of an assembly).
5A94-5AA3
DEFM "UNDEFINED SYMBOL" 55 4E 44 45 46 49 4E 45 44 20 53 59 4D 42 4F CC
Message UNDEFINED SYMBOL. The final byte CCH is "L" with bit 7 set. Used at 65EFH (assembler error).
5AA4-5AB3
DEFM "EXPRESSION ERROR" 45 58 50 52 45 53 53 49 4F 4E 20 45 52 52 4F D2
Message EXPRESSION ERROR. The final byte D2H is "R" with bit 7 set. Used at 62E2H (assembler error).
5AB4-5AC8
DEFM "NO ROOM BETWEEN LINES" 4E 4F 20 52 4F 4F 4D 20 42 45 54 57 45 45 4E 20 4C 49 4E 45 D3
Message NO ROOM BETWEEN LINES. The final byte D3H is "S" with bit 7 set. Used at 5C6FH (no unused line number is left between two lines).
5AC9-5AE3
DEFM "TRS-80 EDITOR/ASSEMBLER 1.1" 54 52 53 2D 38 30 20 45 44 49 54 4F 52 2F 41 53 53 45 4D 42 4C 45 52 20 31 2E B1
Message TRS-80 EDITOR/ASSEMBLER 1.1. The final byte B1H is "1" with bit 7 set. Used at 58D1H (sign-on banner at cold start).
5AE4-5AF1
DEFM "READY CASSETTE" 52 45 41 44 59 20 43 41 53 53 45 54 54 C5
Message READY CASSETTE. The final byte C5H is "E" with bit 7 set. Used at 586BH (cassette prompt; skipped by the appendage when a disk file is open).
5AF2-5AFE
DEFM "READY PRINTER" 52 45 41 44 59 20 50 52 49 4E 54 45 D2
Message READY PRINTER. The final byte D2H is "R" with bit 7 set. Used at 5E20H (H and T commands).
5AFF-5B04
DEFM "NONAME" 4E 4F 4E 41 4D 45
Default File Name
Six characters, no terminator. 6406H stores 5AFFH in the file name pointer at 53ABH before each assembly, and 6121H writes the name (padded with spaces to six characters) into the tape or disk file header. A name typed after the command replaces it (6107H).
5B05H - Command Table (Data)
Data
Searched by the command loop at 58FFH-5926H: 15 entries (B = 0FH at 5902H), each a command character followed by the handler address (low byte first). The matching handler address is pushed and reached by a RET at 5916H or 5920H. When the text buffer is empty, only the last three entries (L, I, B, which leave Register B below 04H) are allowed; the others give NO TEXT IN BUFFER. The W, L and down-arrow entries point into the Apparat appendage.
5B05-5B07
DEFB 'P' / DEFW 5E2AH 50 2A 5E
Command P: Print lines on the screen. Handler at 5E2AH.
5B08-5B0A
DEFB 'H' / DEFW 5E20H 48 20 5E
Command H: Hard copy: print lines on the printer. Handler at 5E20H.
5B0B-5B0D
DEFB 'T' / DEFW 5E1CH 54 1C 5E
Command T: Type lines on the printer without line numbers. Handler at 5E1CH.
5B0E-5B10
DEFB 'D' / DEFW 5EE3H 44 E3 5E
Command D: Delete lines. Handler at 5EE3H.
5B11-5B13
DEFB 'R' / DEFW 5ECDH 52 CD 5E
Command R: Replace a line. Handler at 5ECDH.
5B14-5B16
DEFB 'N' / DEFW 5C02H 4E 02 5C
Command N: Renumber the text. Handler at 5C02H.
5B17-5B19
DEFB 'A' / DEFW 63E3H 41 E3 63
Command A: Assemble. Handler at 63E3H.
5B1A-5B1C
DEFB 'W' / DEFW 6F14H 57 14 6F
Command W: Write the text to tape or disk (appendage entry 6F14H). Handler at 6F14H.
5B1D-5B1F
DEFB 'F' / DEFW 5DC8H 46 C8 5D
Command F: Find a string. Handler at 5DC8H.
5B20-5B22
DEFB 5BH / DEFW 5E72H 5B 72 5E
Command up arrow (5BH): Display the previous line. Handler at 5E72H.
5B23-5B25
DEFB 0AH / DEFW 705AH 0A 5A 70
Command down arrow (0AH): Display the next line (appendage entry 705AH). Handler at 705AH.
5B26-5B28
DEFB 'E' / DEFW 5FC1H 45 C1 5F
Command E: Edit a line. Handler at 5FC1H.
5B29-5B2B
DEFB 'L' / DEFW 6F08H 4C 08 6F
Command L: Load text from tape or disk (appendage entry 6F08H). Handler at 6F08H.
5B2C-5B2E
DEFB 'I' / DEFW 5C41H 49 41 5C
Command I: Insert lines. Handler at 5C41H.
5B2F-5B31
DEFB 'B' / DEFW 56F8H 42 F8 56
Command B: Return to DOS. Handler at 56F8H.
5B32H - Read a Line from the Keyboard
Reads keys through 5834H into the buffer at 5327H (53A8H is set to point there) and echoes them. ENTER ends the line; the count goes to 53AAH. Backspace (08H) erases one character, shift left arrow (18H) erases the whole line (5B32H), BREAK goes back to the command loop. At most 128 characters are accepted. With Register C non-zero, an up arrow (5BH) or down arrow (0AH) typed as the first key ends the line at once as a one-character command. Register D counts the characters typed.
5B32
LD HL,53BBH 21 BB 53
Erase the Line
Point HL to 53BBH, the output column (the number of characters printed on this screen line after the prompt).
5B35
LD B,(HL) 46
Load Register B with the column.
5B36
LD A,08H 3E 08
Load Register A with 08H (backspace).
5B39
Characters remain: GOSUB to 5939H to backspace over one.
5B3C
Characters remain: LOOP BACK to 5B38H.
5B3F
LD (HL),00H 36 00
Set the output column to 00H.
5B41
LD HL,5327H 21 27 53
Main Entry
Point HL to the line buffer at 5327H.
5B44
LD (53A8H),HL 22 A8 53
Store it into 53A8H, the input scan pointer.
5B47
LD D,00H 16 00
Register D = 00H characters typed.
5B49
Key Loop
GOSUB to 5834H to wait for a key (returned in Register A).
5B4C
CP 18H FE 18
Compare with 18H (shift left arrow).
5B4E
Erase the line: JUMP to 5B32H.
5B50
CP 08H FE 08
Compare with 08H (backspace).
5B52
Not a backspace: JUMP to 5B59H.
5B54
GOSUB to 5B89H to erase the last character.
5B59
CP 01H FE 01
Compare with 01H (BREAK).
5B5B
BREAK: JUMP to 58D7H (carriage return, command loop).
5B5E
CP 0DH FE 0D
Compare with 0DH (ENTER).
5B60
ENTER: JUMP to 5B75H to end the line.
5B62
LD (HL),A 77
Store the character in the buffer.
5B63
CP 5BH FE 5B
Compare with 5BH (up arrow).
5B65
Up arrow: JUMP to 5B6BH.
5B67
CP 0AH FE 0A
Compare with 0AH (down arrow).
5B69
Any other character: JUMP to 5B7CH.
5B6B
INC C 0C
Arrow Key
Test Register C ...
5B6D
Arrows not allowed as commands: LOOP BACK to 5B49H and ignore the key.
5B6F
LD A,D 7A
Load Register A with the number of characters typed.
5B70
DEC A 3D
Subtract one.
5B71
Something was already typed: LOOP BACK to 5B49H and ignore the arrow.
5B74
INC D 14
Count the arrow as the one character of the line.
5B75
LD A,D 7A
End of Line
Load Register A with the number of characters typed.
5B76
LD (53AAH),A 32 AA 53
Store it into 53AAH, the input characters remaining.
5B79
JUMP to 5937H to output a carriage return and return.
5B7C
LD A,D 7A
Load Register A with the number of characters typed.
5B7D
CP 80H FE 80
Compare with 80H (128).
5B7F
The buffer is full: LOOP BACK to 5B49H and ignore the key.
5B81
LD A,(HL) 7E
Load Register A with the stored character.
5B82
INC HL 23
Advance the buffer pointer.
5B83
INC D 14
Count the character.
5B84
GOSUB to 5939H to echo it.
5B89H - Erase the Last Character
Used by line input (5B54H) and the line editor (609AH, 6104H). Register HL = the position after the last character, Register D = characters before it. Moves HL back one and erases the character on the screen. A tab cannot be erased by backspacing, so the whole screen line is erased and the remaining characters are displayed again from 5327H.
5B89
INC D 14
Test Register D ...
5B8B
RET Z C8
Nothing to erase: RETURN.
5B8C
DEC HL 2B
Move HL back to the last character.
5B8E
LD A,(HL) 7E
Load Register A with the character.
5B8F
LD HL,53BBH 21 BB 53
Point HL to 53BBH, the output column.
5B92
CP 09H FE 09
Compare the character with 09H (tab).
5B94
A tab: JUMP to 5BA0H.
5B96
LD A,08H 3E 08
Load Register A with 08H (backspace).
5B98
GOSUB to 5939H to backspace on the screen (this adds one to the column).
5B9B
DEC (HL) 35
Take one off the column for the backspace ...
5B9C
DEC (HL) 35
... and one for the erased character.
5B9D
DEC D 15
One character fewer (Register D).
5BA0
PUSH BC C5
Erasing a Tab
Save Register BC.
5BA1
LD B,(HL) 46
Load Register B with the output column.
5BA2
LD A,08H 3E 08
Load Register A with 08H (backspace).
5BA4
GOSUB to 5939H to backspace.
5BA7
Decrement Register B and LOOP BACK to 5BA4H: the whole screen line is erased.
5BA9
LD (HL),B 70
Set the output column to 00H (Register B).
5BAA
DEC D 15
One character fewer (Register D).
5BAB
Nothing left: JUMP to 5BB8H.
5BAD
LD HL,5327H 21 27 53
Point HL to the start of the line in 5327H.
5BB0
LD B,D 42
Register B = the characters left.
5BB1
LD A,(HL) 7E
Load Register A with the next character.
5BB3
GOSUB to 5939H to display it again.
5BB6
Decrement Register B and LOOP BACK to 5BB1H.
5BB8
POP BC C1
Restore Register BC.
5BB9
POP HL E1
Restore HL (the new end position).
5BBBH - Get the Next Input Character (Two Entry Points)
Reads the next character of the line being scanned: the pointer is at 53A8H and the count of characters left is at 53AAH. Tabs (09H) are returned as spaces.
Entry 5BBBH
Skips spaces: Register B = 20H, and every character equal to B is passed over.
Entry 5BBEH
Returns the very next character: 5BBEH is the second byte of the CP AFH instruction at 5BBDH, so execution starts with AFH = XOR A, which makes Register B = 00H (no character is skipped).
Exit
At the end of the line: A = 0DH, the Z FLAG and the CARRY FLAG are set. Otherwise A = the character, with the Z FLAG clear and the CARRY FLAG set by 5BE4H only when the character is not a digit (0-9). Registers BC and HL are preserved.
5BBB
LD A,20H 3E 20
Load Register A with 20H (space), the character to skip, for the 5BBBH entry.
5BBD
CP AFH FE AF
Compare against AFH. This instruction is only a container: its operand byte AFH (at 5BBEH) is the XOR A instruction executed by the 5BBEH entry. From 5BBBH the compare result is not used.
5BBF
PUSH BC C5
Save Register BC.
5BC0
PUSH HL E5
Save Register HL.
5BC1
LD B,A 47
Copy the skip character into Register B (20H from 5BBBH, 00H from 5BBEH).
5BC2
LD HL,53AAH 21 AA 53
Next Character
Point HL to 53AAH, the count of input characters remaining.
5BC5
INC (HL) 34
Increment the count ...
5BC6
DEC (HL) 35
... and decrement it again. The Z FLAG is set if the count at 53AAH is 00H (the line is used up); the count itself is unchanged.
5BC7
LD A,0DH 3E 0D
Load Register A with 0DH (carriage return), the value returned at the end of the line.
5BC9
SCF 37
Set the CARRY FLAG (the Z FLAG from 5BC6H is not changed).
5BCA
If no characters are left (Z FLAG set), JUMP to 5BE1H to return A = 0DH with Z and CARRY set.
5BCC
DEC (HL) 35
Decrement the remaining character count at 53AAH.
5BCD
LD HL,(53A8H) 2A A8 53
Load Register HL with the input scan pointer from 53A8H.
5BD0
LD A,(HL) 7E
Load Register A with the character at that position.
5BD1
INC HL 23
Advance the pointer.
5BD2
LD (53A8H),HL 22 A8 53
Store the advanced pointer back into 53A8H.
5BD5
CP 09H FE 09
Compare the character against 09H (tab).
5BD7
If it is not a tab, JUMP to 5BDBH.
5BD9
LD A,20H 3E 20
A tab is treated as a space: Register A = 20H.
5BDB
CP B B8
Compare the character with Register B, the skip character.
5BDC
If they match (a space while skipping), LOOP BACK to 5BC2H for the next character.
5BDE
GOSUB to 5BE4H, which clears the Z FLAG and sets the CARRY FLAG unless the character is a digit 0-9.
5BE1
POP HL E1
Restore Register HL.
5BE2
POP BC C1
Restore Register BC.
5BE3
RET C9
RETURN with the character in Register A.
5BE4H - Test for a Digit
Register A = a character. Returns the CARRY FLAG clear if it is 0-9 and set if it is not. The Z FLAG is always clear on return from the compare path, and Register A is unchanged. Called from 5BDEH, 5FEAH (line editor repeat count) and 637FH (number evaluation). 5BEDH shares the ending at 5BE9H.
5BE4
CP 30H FE 30
Compare the character with 30H (0).
5BE6
RET C D8
Below 0: RETURN with the CARRY FLAG set (not a digit).
5BE7
CP 3AH FE 3A
Compare the character with 3AH, one above 9. The CARRY FLAG is set for 0-9.
5BE9
CCF 3F
Reverse the CARRY FLAG: now clear for a digit (or letter, from 5BF2H) and set otherwise. Also reached from 5BF2H.
5BEA
INC A 3C
Increment Register A ...
5BEB
DEC A 3D
... and decrement it again: this clears the Z FLAG (A is never 00H here) and leaves the CARRY FLAG alone.
5BEDH - Test for a Letter
Register A = a character. Returns the CARRY FLAG clear if it is A-Z and set if it is not. Register A is unchanged. Called from 61E5H and 620EH (operand classification).
5BED
CP 41H FE 41
Compare the character with 41H (A).
5BEF
RET C D8
Below A: RETURN with the CARRY FLAG set (not a letter).
5BF0
CP 5BH FE 5B
Compare the character with 5BH, one above Z. The CARRY FLAG is set for A-Z.
5BF2
JUMP to 5BE9H to reverse the CARRY FLAG and return.
5BF4H - Put Back the Last Input Character
Undoes one 5BBBH/5BBEH read: moves the scan pointer at 53A8H back one character and adds one to the count of characters left at 53AAH, so the same character is read again. All registers are preserved (the flags are changed by the INC).
5BF4
PUSH HL E5
Save Register HL.
5BF5
LD HL,(53A8H) 2A A8 53
Load Register HL with the scan pointer from 53A8H ...
5BF8
DEC HL 2B
... move it back one character ...
5BF9
LD (53A8H),HL 22 A8 53
... and store it.
5BFC
LD HL,53AAH 21 AA 53
Point HL to 53AAH, the count of characters left.
5BFF
INC (HL) 34
Add one to the count.
5C00
POP HL E1
Restore Register HL.
5C02H - N Command: Renumber the Text
N start,increment. Renumbers every line from the first (7700H), giving the first line the start number (the current line's number if none is typed) and adding the increment (5317H) for each following line. The text is walked twice: the first pass (CARRY FLAG set) only checks that no number reaches FFFAH; the second pass (CARRY FLAG clear) writes the numbers.
5C02
GOSUB to 5CC7H to read the start number (Register HL) and the increment (stored in 5317H).
5C05
SCF 37
Set the CARRY FLAG: the first pass only checks.
5C06
PUSH HL E5
Pass Start
Save the start number.
5C07
LD DE,7700H 11 00 77
Load Register DE with 7700H, the first line.
5C0A
PUSH AF F5
Save the pass flag (CARRY).
5C0B
PUSH HL E5
Line Loop
Save the number for this line.
5C0C
LD HL,(5315H) 2A 15 53
Load Register HL with the end-of-text pointer from 5315H.
5C0F
GOSUB to 5DC2H to compare it with the line pointer (DE). The Z FLAG is set at the end of the text.
5C12
EX DE,HL EB
Exchange: HL = the line pointer.
5C13
POP DE D1
Restore the number for this line into DE.
5C14
Not at the end: JUMP to 5C1CH.
5C16
POP AF F1
End of the text: restore the pass flag.
5C17
CCF 3F
Complement the CARRY FLAG.
5C18
POP HL E1
Restore the start number.
5C19
After the first pass (now NO CARRY): LOOP BACK to 5C06H for the writing pass.
5C1B
RET C9
After the second pass: RETURN.
5C1C
POP AF F1
Restore the pass flag ...
5C1D
PUSH AF F5
... and save it again.
5C1E
INC HL 23
Point HL at the line number's high byte.
5C1F
First pass: JUMP to 5C25H without writing.
5C21
DEC HL 2B
Point HL back at the low byte.
5C22
LD (HL),E 73
Store the new number's low byte.
5C24
LD (HL),D 72
Store the high byte.
5C25
INC HL 23
Point HL at the length byte.
5C26
LD C,(HL) 4E
Load Register C with the line length.
5C27
LD B,00H 06 00
Register B = 00H.
5C29
INC BC 03
Add one for the length byte itself.
5C2A
ADD HL,BC 09
HL = the next line.
5C2B
PUSH HL E5
Save the next line pointer.
5C2C
LD HL,(5317H) 2A 17 53
Load Register HL with the increment from 5317H.
5C2F
ADD HL,DE 19
Add it to this line's number.
5C30
Past 65535: JUMP to 5C3BH for the error.
5C32
LD DE,FFFAH 11 FA FF
Load Register DE with FFFAH.
5C35
GOSUB to 5DC2H to compare the new number with FFFAH.
5C38
POP DE D1
Restore the next line pointer into DE.
5C39
Below FFFAH: LOOP BACK to 5C0BH.
5C3B
LD HL,59B1H 21 B1 59
Point HL to LINE NUMBER TOO LARGE at 59B1H.
5C3E
JUMP to 592BH to display it and return to the command loop.
5C41H - I Command: Insert Lines
I start,increment. Inserts lines typed from the keyboard, numbering them from the start number (the current line's number if none is typed) in steps of the increment. If a line with the start number exists, insertion starts at the next number after it. Insertion continues until BREAK (which leaves through 5B41H) or an error.
5C41
GOSUB to 5CC7H to read the start number and increment and search for that line. The Z FLAG is set if it exists.
5C44
The line does not exist: JUMP to 5C55H to insert it.
5C46
EX DE,HL EB
Next Number
Move the number into DE.
5C47
LD HL,(5317H) 2A 17 53
Load Register HL with the increment from 5317H.
5C4B
Past 65535: JUMP to 5C3BH for LINE NUMBER TOO LARGE.
5C4D
LD DE,FFFAH 11 FA FF
Load Register DE with FFFAH.
5C50
GOSUB to 5DC2H to compare the new number with FFFAH.
5C53
FFFAH or higher: JUMP to 5C3BH for the error.
5C55
PUSH HL E5
Save the number.
5C56
GOSUB to 5C5CH to read and insert one line with this number (the CARRY FLAG is set, which selects keyboard input).
5C59
POP HL E1
Restore the number.
5C5A
LOOP BACK to 5C46H for the next line.
5C5CH - Insert One Line
Inserts a line with the number in the caller's stack slot before the line at 531DH (set by the last line search). Two entries:
5C5CH
With the CARRY FLAG set (from 5C56H): the number is displayed and the line is read from the keyboard into 5327H.
5C60H
The second byte of the LD B,B7H at 5C5FH, so it runs B7H = OR A, which clears the CARRY FLAG: the text already in 5327H (length in 53AAH) is used. The line editor (6041H) and the R command reach this through 5ED6H.
The number must be lower than that of the following line, otherwise NO ROOM BETWEEN LINES. The rest of the text is moved up to open a gap of length + 3 bytes, the pointers 5315H, 531DH and 5311H are updated, and the line (number, length, text) is stored in the gap.
5C5C
POP HL E1
Pop the return address into HL.
5C5D
EX (SP),HL E3
Exchange it with the line number below it on the stack (HL = the number).
5C5E
PUSH HL E5
Push the number again (the return address stays under it).
5C5F
LD B,B7H 06 B7
Load Register B with B7H. This instruction exists for the 5C60H entry: its operand B7H is the OR A instruction that the edit and replace code executes.
5C61
LD HL,(531DH) 2A 1D 53
Load Register HL with the following line's address from 531DH.
5C64
LD E,(HL) 5E
Load Register E with that line's number, low byte.
5C66
LD D,(HL) 56
Load Register D with the high byte.
5C67
DEC HL 2B
Point HL back at the line.
5C68
EX (SP),HL E3
Exchange: HL = the new line's number; the following line's address goes on the stack.
5C69
PUSH AF F5
Save the input choice (the CARRY FLAG).
5C6A
GOSUB to 5DC2H to compare the new number with the following line's number.
5C6D
Lower: JUMP to 5C75H.
5C6F
LD HL,5AB4H 21 B4 5A
Point HL to NO ROOM BETWEEN LINES at 5AB4H.
5C72
JUMP to 592BH to display it and return to the command loop.
5C75
GOSUB to 5DA9H to check that memory is not full.
5C78
POP AF F1
Restore the input choice ...
5C79
PUSH AF F5
... and save it again.
5C7A
Keyboard input: GOSUB to 5D75H to display the line number.
5C7D
POP AF F1
Restore the input choice.
5C7E
EX (SP),HL E3
Exchange: HL = the following line's address; the new number goes on the stack.
5C7F
PUSH HL E5
Save the following line's address.
5C80
LD C,00H 0E 00
Load Register C with 00H: arrow keys are not accepted as input.
5C82
Keyboard input: GOSUB to 5B41H to read the line into 5327H (count in 53AAH).
5C85
POP DE D1
Restore the insertion point (the following line's address) into DE.
5C86
LD HL,(5315H) 2A 15 53
Load Register HL with the end-of-text pointer from 5315H.
5C89
INC HL 23
Point HL at the second byte of the FFH FFH end marker, the last byte to move.
5C8A
LD B,00H 06 00
Register B = 00H.
5C8C
LD A,(53AAH) 3A AA 53
Load Register A with the new line's length from 53AAH.
5C8F
LD C,A 4F
Register BC = the length.
5C90
PUSH BC C5
Save the length.
5C91
PUSH HL E5
Save the address of the last byte to move.
5C92
ADD HL,BC 09
Add the length ...
5C93
INC HL 23
... plus 1 ...
5C94
INC HL 23
... plus 1: HL = the new address of the end marker (old + length + 3 - 1).
5C95
LD (5315H),HL 22 15 53
Store it into 5315H, the end-of-text pointer.
5C98
INC HL 23
Point HL at the destination of the last byte.
5C99
EX DE,HL EB
Exchange: DE = destination end, HL = insertion point.
5C9A
XOR A AF
Byte Count
Set Register A to 00H.
5C9B
SUB L 95
Subtract the low byte of the insertion point.
5C9C
LD L,A 6F
Register L = the negated low byte.
5C9D
SBC A,H 9C
Subtract the high byte with the borrow: A = -L - H - borrow.
5C9E
SUB L 95
Subtract Register L (which now holds -L): A = -H - borrow.
5C9F
LD H,A 67
Register H = the negated high byte: HL = 0 - insertion point.
5CA0
POP BC C1
Load Register BC with the address of the last byte to move ...
5CA1
PUSH BC C5
... and keep it on the stack.
5CA2
ADD HL,BC 09
Add: HL = last byte - insertion point.
5CA3
INC HL 23
Add one: the number of bytes to move.
5CA4
LD B,H 44
Copy the count into Register B ...
5CA6
POP HL E1
Restore the address of the last byte to move into HL.
5CA7
LDDR ED B8
Move the rest of the text up, from the end backward.
5CA9
EX DE,HL EB
Exchange: HL = one byte below the moved text.
5CAA
INC HL 23
Point HL at the moved following line.
5CAB
LD (531DH),HL 22 1D 53
Store its new address into 531DH.
5CAE
EX DE,HL EB
Exchange: HL = one byte below the gap.
5CAF
INC HL 23
Point HL at the start of the gap.
5CB0
LD (5311H),HL 22 11 53
Store it into 5311H: the new line becomes the current line.
5CB3
POP BC C1
Restore the length into Register BC.
5CB4
POP DE D1
Restore the line number into DE.
5CB5
LD (HL),E 73
Store the line number's low byte.
5CB7
LD (HL),D 72
Store the high byte.
5CB9
LD (HL),C 71
Store the length byte.
5CBA
INC HL 23
Point HL at the text part of the gap.
5CBB
EX DE,HL EB
Exchange: DE = the text destination.
5CBC
EX (SP),HL E3
Exchange with the stack: HL = the return address, and the line number goes on the stack (the caller at 5C59H pops it).
5CBD
PUSH HL E5
Push the return address.
5CBE
LD HL,5327H 21 27 53
Point HL to the new text in 5327H.
5CC1
LD A,B 78
Copy BC Bytes
Load Register A with the high byte of the count. Also called from 5FD7H.
5CC2
OR C B1
OR in the low byte.
5CC3
RET Z C8
A count of 0: RETURN.
5CC4
LDIR ED B0
Copy the text into the gap.
5CC7H - Read a Line Number and Increment, and Find the Line
Parses number,increment after the command (5D09H with , as the delimiter, then 5D07H). A typed increment of 0 is BAD PARAMETER(S); a typed increment is stored in 5317H. Then falls into the line search at 5CDAH.
5CC7
LD B,2CH 06 2C
Load Register B with 2CH (,), the delimiter after the line number.
5CC9
GOSUB to 5D09H to read the line number into HL (the current line's number if none is typed).
5CCD
GOSUB to 5D07H to read the increment.
5CD0
None typed (Z FLAG set): JUMP to 5CD9H.
5CD2
LD A,H 7C
Load Register A with the increment's high byte ...
5CD3
OR L B5
... OR the low byte.
5CD4
An increment of 0: JUMP to 5D24H for BAD PARAMETER(S).
5CD6
LD (5317H),HL 22 17 53
Store the increment into 5317H.
5CD9
POP HL E1
Restore the line number.
5CDA
PUSH HL E5
Find a Line
Save the line number being searched for. Also called directly (5D65H, 5E81H, 5EA1H, 5EC3H, 5EF9H, 5FC4H). Returns the Z FLAG set if the line exists. 531BH = that line, or the first line with a higher number; 531DH = the line after it (the same higher line when not found); 5319H = the line examined before it. HL is returned unchanged.
5CDB
LD HL,7700H 21 00 77
Load Register HL with 7700H, the first line.
5CDF
LD (5319H),HL 22 19 53
Search Loop
Store the line pointer into 5319H.
5CE2
POP HL E1
Restore the line pointer.
5CE3
LD B,H 44
Copy it into Register B ...
5CE4
LD C,L 4D
... and C (the line being examined).
5CE5
LD E,(HL) 5E
Load Register E with the line number's low byte.
5CE7
LD D,(HL) 56
Load Register D with the high byte.
5CE8
INC HL 23
Advance to the length byte.
5CE9
PUSH DE D5
Save the line number.
5CEA
LD E,(HL) 5E
Load Register E with the length.
5CEB
INC HL 23
Advance to the text.
5CEC
LD D,00H 16 00
Register D = 00H.
5CEE
ADD HL,DE 19
HL = the next line.
5CEF
POP DE D1
Restore the line number into DE.
5CF0
EX (SP),HL E3
Exchange: HL = the number searched for; the next line's address goes on the stack.
5CF1
GOSUB to 5DC2H to compare the number searched for with this line's number.
5CF4
EX (SP),HL E3
Exchange back: HL = the next line.
5CF5
Equal: JUMP to 5CFDH.
5CF7
PUSH HL E5
Save the next line.
5CF8
LD H,B 60
Copy this line's address ...
5CF9
LD L,C 69
... into HL.
5CFA
The number searched for is higher: LOOP BACK to 5CDFH (the end marker FFFFH stops the loop).
5CFC
POP DE D1
Lower: discard the next line; HL = this line.
5CFD
LD (531DH),HL 22 1D 53
Store HL into 531DH (the next line, or this line when not found).
5D00
LD H,B 60
Copy this line's address ...
5D01
LD L,C 69
... into HL.
5D02
LD (531BH),HL 22 1B 53
Store it into 531BH.
5D05
POP HL E1
Restore the number searched for into HL.
5D06
RET C9
RETURN with the Z FLAG from the compare.
5D07H - Read a Line Number
Reads a line number from the command line. Entry 5D07H ends it at the end of the line (B = 0DH); entry 5D09H takes the delimiter in Register B. Besides decimal digits (values above 65529 are refused by the check at 5D34H), # means the first line, . the current line and * the last line. Returns HL = the number. With nothing typed, HL = the current line's number and the Z FLAG is set; the Z FLAG is also set when the delimiter was found, and clear when the line ended after a number. Register D counts what was typed; Register E is set after #, . or *. Anything else gives BAD PARAMETER(S).
5D07
LD B,0DH 06 0D
Load Register B with 0DH, the end of the line, as the delimiter.
5D09
LD DE,0000H 11 00 00
Register DE = 0000H (nothing typed yet).
5D0C
LD H,D 62
Register H = 00H ...
5D0D
LD L,D 6A
... and L = 00H: the number is 0.
5D0E
Character Loop
GOSUB to 5BBBH to get the next non-space character.
5D11
A character: JUMP to 5D1EH.
5D13
INC D 14
End of the line: test Register D ...
5D15
RET NZ C0
Something was typed: RETURN with HL = the number and the NZ FLAG.
5D16
LD HL,(5311H) 2A 11 53
Nothing typed: load Register HL with the current line pointer from 5311H.
5D19
LD A,(HL) 7E
Load Register A with the line number's low byte.
5D1B
LD H,(HL) 66
Load Register H with the high byte.
5D1C
LD L,A 6F
Register L = the low byte.
5D1D
RET C9
RETURN with the current line's number and the Z FLAG.
5D1E
INC E 1C
Test Register E ...
5D20
No #, . or * yet: JUMP to 5D2AH.
5D22
CP B B8
Compare the character with the delimiter (Register B).
5D23
RET Z C8
The delimiter: RETURN with the Z FLAG.
5D24
LD HL,597BH 21 7B 59
Bad Parameter
Point HL to BAD PARAMETER(S) at 597BH. Many routines jump here.
5D27
JUMP to 592BH to display it and return to the command loop.
5D2A
Not a digit (CARRY FLAG from 5BBBH): JUMP to 5D4AH.
5D2C
PUSH HL E5
Save the number.
5D2D
LD HL,5D72H 21 72 5D
Load Register HL with 5D72H ...
5D30
EX (SP),HL E3
... and exchange it with the stack: the number is back in HL and 5D72H is the return address for the digit code below.
5D31
SUB 30H D6 30
Add a Digit
Convert the ASCII digit to its value. Also called from 5F8EH.
5D33
PUSH DE D5
Save Register DE.
5D34
LD DE,1999H 11 99 19
Load Register DE with 1999H (6553).
5D37
PUSH AF F5
Save the digit.
5D38
GOSUB to 5DC2H to compare the number with 1999H.
5D3B
1999H or more would overflow: JUMP to 5D24H.
5D3D
POP AF F1
Restore the digit.
5D3E
LD D,H 54
Copy the number's high byte into Register D ...
5D3F
LD E,L 5D
... and the low byte into Register E.
5D40
ADD HL,HL 29
HL = number x 2.
5D41
ADD HL,HL 29
HL = number x 4.
5D42
ADD HL,DE 19
HL = number x 5.
5D43
ADD HL,HL 29
HL = number x 10.
5D44
LD D,00H 16 00
Register D = 00H ...
5D46
LD E,A 5F
... and E = the digit.
5D47
ADD HL,DE 19
Add the digit.
5D48
POP DE D1
Restore Register DE.
5D49
RET C9
RETURN (to 5D72H from the loop).
5D4A
INC D 14
Test Register D ...
5D4C
A number was already typed: JUMP to 5D22H, where only the delimiter is accepted.
5D4E
CP 23H FE 23
Compare the character with 23H (#).
5D50
LD HL,7700H 21 00 77
Load Register HL with 7700H, the first line (the flags are kept).
5D53
#: JUMP to 5D6DH to take its number.
5D55
CP 2EH FE 2E
Compare with 2EH (.).
5D57
LD HL,(5311H) 2A 11 53
Load Register HL with the current line pointer from 5311H.
5D5C
CP 2AH FE 2A
Compare with 2AH (*).
5D5E
Anything else: JUMP to 5D24H for the error.
5D60
LD HL,FFFFH 21 FF FF
*: load Register HL with FFFFH, the end marker's number.
5D63
PUSH DE D5
Save Register DE.
5D64
PUSH BC C5
Save Register BC.
5D65
GOSUB to 5CDAH to search for it; 5319H is left pointing to the last line.
5D68
LD HL,(5319H) 2A 19 53
Load Register HL with the last line's address from 5319H.
5D6B
POP BC C1
Restore Register BC.
5D6C
POP DE D1
Restore Register DE.
5D6D
LD A,(HL) 7E
Load Register A with the line number's low byte.
5D6F
LD H,(HL) 66
Load Register H with the high byte.
5D70
LD L,A 6F
Register L = the low byte.
5D71
INC E 1C
Set Register E: only the delimiter may follow.
5D72
INC D 14
Count what was typed (Register D).
5D75H - Print a 5-Digit Decimal Number
Prints HL as five decimal digits followed by a space, and sets the output column (53BBH) so that the text after a line number starts at column 0 for tab stops. Each digit is sent with bit 7 set (B0H-B9H): the screen and printer show it normally (5939H clears bit 7), and a source file written by W keeps bit 7, which the load code expects. Registers HL, DE and BC are preserved.
5D75
PUSH HL E5
Save Register HL.
5D76
PUSH DE D5
Save Register DE.
5D77
PUSH BC C5
Save Register BC.
5D78
LD DE,5D9FH 11 9F 5D
Point DE to the table of negative powers of ten at 5D9FH.
5D7B
LD A,(DE) 1A
Digit Loop
Load Register A with the power's low byte.
5D7C
LD C,A 4F
Copy it into Register C.
5D7E
LD A,(DE) 1A
Load Register A with the high byte.
5D7F
LD B,A 47
Copy it into Register B.
5D81
PUSH DE D5
Save the table pointer.
5D82
LD A,AFH 3E AF
Load Register A with AFH (one less than B0H, which is "0" with bit 7 set).
5D84
INC A 3C
Count one more for this digit.
5D85
LD D,H 54
Keep the value before the subtraction: high byte in Register D ...
5D86
LD E,L 5D
... and low byte in Register E.
5D87
ADD HL,BC 09
Add the negative power: subtract it.
5D88
No borrow (CARRY set means it did not go below 0): LOOP BACK to 5D84H.
5D8A
EX DE,HL EB
Restore the value before the last subtraction.
5D8B
POP DE D1
Restore the table pointer.
5D8C
GOSUB to 5939H to print the digit.
5D8F
INC C 0C
Increment the power's low byte: only the last entry (FFH) becomes 00H.
5D90
More digits: LOOP BACK to 5D7BH.
5D92
POP BC C1
Restore Register BC.
5D93
POP DE D1
Restore Register DE.
5D94
POP HL E1
Restore Register HL.
5D95
LD A,FFH 3E FF
Load Register A with FFH ...
5D97
LD (53BBH),A 32 BB 53
... and store it into the output column (53BBH); the space below makes it 00H.
5D9A
LD A,20H 3E 20
Load Register A with 20H (space).
5D9C
JUMP to 5939H to print it and return.
5D9F-5DA8
DEFW D8F0H, FC18H, FF9CH, FFF6H, FFFFH F0 D8 18 FC 9C FF F6 FF FF FF
Powers of Ten (Data)
-10000, -1000, -100, -10 and -1, used by 5D75H.
5DA9H - Check for Memory Full
Compares the end of the text (5315H) with the symbol table top (5313H) minus 256 bytes. If there is not enough room, BUFFER FULL is displayed and the command ends. Registers HL and DE are preserved.
5DA9
PUSH HL E5
Save Register HL.
5DAA
PUSH DE D5
Save Register DE.
5DAB
LD HL,(5313H) 2A 13 53
Load Register HL with the symbol table top from 5313H.
5DAE
LD DE,(5315H) ED 5B 15 53
Load Register DE with the end-of-text pointer from 5315H.
5DB2
DEC H 25
Subtract 256 from the symbol table top.
5DB3-5DB5
NOP x 3 00 x 3
Three unused NOP bytes (00H).
5DB6
GOSUB to 5DC2H to compare.
5DB9
POP DE D1
Restore Register DE.
5DBA
POP HL E1
Restore Register HL.
5DBB
RET NC D0
Room left: RETURN.
5DBC
LD HL,5997H 21 97 59
Point HL to BUFFER FULL at 5997H.
5DBF
JUMP to 592BH to display it and return to the command loop.
5DC2H - Compare HL with DE
Sets the flags as for HL - DE: Z if equal, CARRY if HL is lower. Only Register A is changed.
5DC2
LD A,H 7C
Load Register A with the high byte of HL.
5DC3
SUB D 92
Subtract the high byte of DE.
5DC4
RET NZ C0
The high bytes differ: RETURN with that result.
5DC5
LD A,L 7D
Load Register A with the low byte of HL.
5DC6
SUB E 93
Subtract the low byte of DE.
5DC8H - F Command: Find a String
F text. Stores up to 16 characters as the find string (5300H = length, 5301H = text); with no text, the previous string is used. Searches from the line after the current line to the end of the text and displays the first line that contains the string, which becomes the current line. Otherwise STRING NOT FOUND.
5DC8
LD DE,5301H 11 01 53
Point DE to 5301H, the find string.
5DCB
LD B,00H 06 00
Register B = 00H characters stored.
5DCD
Collect the String
GOSUB to 5BBEH for the next character (spaces are kept).
5DD0
End of the command line: JUMP to 5DDDH.
5DD2
LD (DE),A 12
Store the character in the find string.
5DD5
LD A,B 78
Load Register A with the count ...
5DD6
LD (5300H),A 32 00 53
... and store it into 5300H, the find string length.
5DD9
CP 10H FE 10
Compare with 10H (16).
5DDB
Room for more: LOOP BACK to 5DCDH.
5DDD
LD HL,(5311H) 2A 11 53
Load Register HL with the current line pointer from 5311H.
5DE1
POP HL E1
Next Line
Restore the line pointer.
5DE2
INC HL 23
Skip the line number ...
5DE3
INC HL 23
... two bytes.
5DE4
LD E,(HL) 5E
Load Register E with the line length.
5DE5
INC HL 23
Point HL at the text.
5DE6
LD D,00H 16 00
Register D = 00H.
5DE8
ADD HL,DE 19
HL = the next line.
5DE9
EX DE,HL EB
Move it into DE.
5DEA
LD HL,(5315H) 2A 15 53
Load Register HL with the end-of-text pointer from 5315H.
5DED
DEC HL 2B
Subtract one.
5DEE
GOSUB to 5DC2H to compare it with the next line's address.
5DF1
The next line is before the end: JUMP to 5DF9H to search it.
5DF3
LD HL,596BH 21 6B 59
Point HL to STRING NOT FOUND at 596BH.
5DF6
JUMP to 592BH to display it and return to the command loop.
5DF9
EX DE,HL EB
HL = the line to search.
5DFB
INC HL 23
Skip the line number ...
5DFC
INC HL 23
... two bytes.
5DFD
LD C,(HL) 4E
Load Register C with the line length.
5DFE
PUSH HL E5
Save the pointer (at the length byte).
5DFF
POP HL E1
Next Start Position
Restore the position pointer.
5E00
INC HL 23
Advance to the next character of the line.
5E01
LD DE,5300H 11 00 53
Point DE to 5300H, the find string length.
5E04
LD A,(DE) 1A
Load Register A with the length ...
5E05
LD B,A 47
... into Register B.
5E06
INC DE 13
Point DE at the find string.
5E07
LD A,C 79
Load Register A with the characters left in the line (Register C).
5E08
CP B B8
Compare with the string length.
5E09
Fewer characters left than the string: JUMP to 5DE1H for the next line.
5E0B
PUSH HL E5
Save the start position.
5E0C
DEC C 0D
One start position fewer.
5E0D
LD A,(DE) 1A
Compare
Load Register A with the next string character.
5E0E
CP (HL) BE
Compare it with the text character.
5E0F
INC HL 23
Advance the text pointer.
5E10
INC DE 13
Advance the string pointer.
5E11
Different: JUMP to 5DFFH to try the next start position.
5E13
Decrement Register B and LOOP BACK to 5E0DH until the whole string matched.
5E15
POP HL E1
Found: discard the start position.
5E16
POP HL E1
Restore the line pointer into HL.
5E17
LD BC,0001H 01 01 00
Load Register BC with 0001H: display one line.
5E1A
JUMP to 5E4FH to display it and make it the current line.
5E1CH - P, H and T Commands: Display or Print Lines
Three entries:
5E1CH (T)
Sets 53C5H so the lines are printed without line numbers, then continues as H.
5E20H (H)
Shows READY PRINTER, waits for a key (5866H) and prints the lines.
5E2AH (P)
The second byte of the LD B,AFH at 5E29H, so it runs AFH = XOR A: Register A = 00H, and the lines go to the screen.
Register A (the key from 5866H, or 00H for P) becomes the printer flag (53BCH). With a range (start:end, 5E9BH) every line in it is shown; with nothing typed, 16 lines from the current line. BREAK stops and shift-@ pauses (5856H). The last line shown becomes the current line.
5E1C
LD HL,53C5H 21 C5 53
T: point HL to 53C5H, the "no line numbers" flag.
5E20
LD HL,5AF2H 21 F2 5A
H: point HL to READY PRINTER at 5AF2H.
5E23
GOSUB to 592FH to display it.
5E26
GOSUB to 5866H to wait for a key (BREAK goes back to the command loop). Register A = the key, not 00H.
5E29
LD B,AFH 06 AF
Load Register B with AFH. This instruction exists for the 5E2AH entry: its operand AFH is the XOR A that the P command runs.
5E2B
PUSH AF F5
Save Register A: non-zero for H and T, 00H for P.
5E2C
GOSUB to 5E9BH to read the range. HL = the first line, DE = the line after the last, Register B = non-zero if a range was typed.
5E2F
POP AF F1
Restore Register A.
5E30
LD (53BCH),A 32 BC 53
Store it into 53BCH, the printer flag.
5E33
INC B 04
Test Register B ...
5E35
LD BC,FFFFH 01 FF FF
Load Register BC with FFFFH: no line limit (the flags are kept).
5E38
A range was typed: JUMP to 5E44H.
5E3A
LD BC,0010H 01 10 00
No range: load Register BC with 0010H (16 lines).
5E3D
LD HL,(5315H) 2A 15 53
Load Register HL with the end-of-text pointer from 5315H ...
5E40
EX DE,HL EB
... as the stop address in DE.
5E41
LD HL,(5311H) 2A 11 53
Load Register HL with the current line pointer from 5311H.
5E44
Line Loop
GOSUB to 5DC2H to compare the line pointer with the stop address.
5E47
RET Z C8
Reached: RETURN.
5E48
GOSUB to 5856H to check for BREAK or shift-@.
5E4B
DEC BC 0B
Count one line.
5E4C
LD A,B 78
Load Register A with the count's high byte ...
5E4D
OR C B1
... OR the low byte.
5E4E
RET Z C8
The count is used up: RETURN.
5E4F
LD (5311H),HL 22 11 53
Show One Line
Make this line the current line (5311H). Also entered from 5E1AH, 5E75H (arrows) and 5F3CH (W).
5E52
PUSH DE D5
Save the stop address.
5E53
LD E,(HL) 5E
Load Register E with the line number's low byte.
5E55
LD D,(HL) 56
Load Register D with the high byte.
5E56
INC HL 23
Advance to the length byte.
5E57
EX DE,HL EB
Exchange: HL = the line number.
5E58
LD A,(53C5H) 3A C5 53
Load Register A with the "no line numbers" flag from 53C5H.
5E5C
Clear: GOSUB to 5D75H to print the line number and a space.
5E5F
EX DE,HL EB
Exchange back: HL = the length byte.
5E60
LD E,(HL) 5E
Load Register E with the line length.
5E61
INC HL 23
Text Loop
Advance HL.
5E62
DEC E 1D
Count one character.
5E63
Characters left: JUMP to 5E6CH.
5E66
GOSUB to 5937H to end the output line.
5E69
POP DE D1
Restore the stop address.
5E6A
JUMP to 5E44H with HL at the next line.
5E6C
LD A,(HL) 7E
Load Register A with the text character.
5E6D
GOSUB to 5939H to print it.
5E72H - Up Arrow and Down Arrow Commands
Up arrow (5BH) enters at 5E72H with the CARRY FLAG set and shows the line before the current one. Down arrow enters through the appendage at 705AH, which jumps to 5E74H: the second byte of the LD B,AFH at 5E73H, so it runs AFH = XOR A (NO CARRY) and shows the line after the current one. At the first or last line the current line is shown again. The line shown becomes the current line.
5E72
SCF 37
Up arrow: set the CARRY FLAG.
5E73
LD B,AFH 06 AF
Load Register B with AFH. This instruction exists for the 5E74H entry: its operand AFH is the XOR A that the down arrow runs.
5E75
LD BC,5E4FH 01 4F 5E
Load Register BC with 5E4FH, the "show one line" code ...
5E78
PUSH BC C5
... and push it as the return address.
5E79
PUSH AF F5
Save the direction (the CARRY FLAG).
5E7A
LD HL,(5311H) 2A 11 53
Load Register HL with the current line pointer from 5311H.
5E7D
LD E,(HL) 5E
Load Register E with its number's low byte.
5E7F
LD D,(HL) 56
Load Register D with the high byte.
5E80
EX DE,HL EB
Exchange: HL = the current line's number.
5E81
GOSUB to 5CDAH to find it: 5319H = the line before, 531DH = the line after.
5E84
LD BC,0001H 01 01 00
Load Register BC with 0001H: show one line.
5E87
LD HL,(5319H) 2A 19 53
Load Register HL with the line before from 5319H.
5E8A
POP AF F1
Restore the direction.
5E8B
RET C D8
Up arrow: RETURN to 5E4FH to show the line before.
5E8C
LD HL,(5315H) 2A 15 53
Load Register HL with the end-of-text pointer from 5315H ...
5E8F
EX DE,HL EB
... into DE.
5E90
LD HL,(531DH) 2A 1D 53
Load Register HL with the line after from 531DH.
5E93
GOSUB to 5DC2H to compare it with the end of the text.
5E96
RET NZ C0
Not the end: RETURN to 5E4FH to show the line after.
5E97
LD HL,(531BH) 2A 1B 53
The current line is the last: load Register HL with it from 531BH.
5E9A
RET C9
RETURN to 5E4FH to show it again.
5E9BH - Read a Line Range
Reads start:end (either may be #, ., * or a number; with nothing typed the current line is used). Returns HL = the address of the first line of the range, DE = the address of the line after the last, Register B non-zero if a start was typed. Without an end number the start line must exist (NO SUCH LINE); an end lower than the start gives BAD PARAMETER(S).
5E9B
LD B,3AH 06 3A
Load Register B with 3AH (:), the delimiter after the start number.
5E9D
GOSUB to 5D09H to read the start number into HL.
5EA0
PUSH DE D5
Save Register DE (Register D = non-zero if a start was typed).
5EA1
GOSUB to 5CDAH to find the start line. The Z FLAG is set if it exists.
5EA4
EX DE,HL EB
Move the start number into DE.
5EA5
LD HL,(531BH) 2A 1B 53
Load Register HL with the start line's address from 531BH.
5EA9
PUSH DE D5
Save the start number.
5EAA
PUSH AF F5
Save the search result (Register A = 00H and the Z FLAG if found).
5EAB
GOSUB to 5D07H to read the end number.
5EAE
POP AF F1
Restore the search result.
5EAF
INC D 14
Test Register D (non-zero if an end was typed) ...
5EB1
POP DE D1
Restore the start number into DE.
5EB2
An end was typed: JUMP to 5EBDH.
5EB4
OR A B7
Test the search result.
5EB5
The start line exists: JUMP to 5EC6H; the range is that one line.
5EB7
LD HL,598BH 21 8B 59
Point HL to NO SUCH LINE at 598BH. Also reached from 5ED0H and 5FC7H.
5EBA
JUMP to 592BH to display it and return to the command loop.
5EBD
GOSUB to 5DC2H to compare the end number with the start number.
5EC0
The end is lower: JUMP to 5D24H for BAD PARAMETER(S).
5EC3
GOSUB to 5CDAH to find the end line.
5EC6
LD HL,(531DH) 2A 1D 53
Load Register HL with the line after the range from 531DH.
5EC9
EX DE,HL EB
Move it into DE.
5ECA
POP HL E1
Restore the first line's address into HL.
5ECB
POP BC C1
Restore Register BC (Register B = non-zero if a start was typed).
5ECDH - R Command and Line Deletion
5ECDH (R)
R line,increment deletes the line and then continues as the I command at 5C56H: the line is typed again with the same number, followed by new lines.
5ED6H
Deletes the line found by the last search (531BH up to 531DH) and returns to the address in BC (5C56H for R, 5C60H for the line editor).
5EE3H (D)
D start:end deletes a range of lines.
The text after the deleted lines is moved down and the end-of-text pointer is updated. When the deletion reaches the end of the text, the line before the deleted block becomes the current line.
5ECD
R: GOSUB to 5CC7H to read the line number and increment and find the line.
5ED0
The line does not exist: JUMP to 5EB7H for NO SUCH LINE.
5ED2
LD BC,5C56H 01 56 5C
Load Register BC with 5C56H, where the I command inserts the line typed next.
5ED5
PUSH HL E5
Save the line number (5C59H pops it).
5ED6
PUSH BC C5
Delete the Found Line
Push the continuation address (Register BC).
5ED7
LD HL,(531DH) 2A 1D 53
Load Register HL with the line after it from 531DH ...
5EDA
EX DE,HL EB
... as the source of the move in DE.
5EDB
LD HL,(531BH) 2A 1B 53
Load Register HL with the found line from 531BH (the destination).
5EDE
LD (531DH),HL 22 1D 53
Store it into 531DH: after the deletion the following line is at this address.
5EE3
D: GOSUB to 5E9BH to read the range. HL = the first line, DE = the line after the last.
5EE6
PUSH HL E5
Save the first line's address.
5EE7
LD (5311H),HL 22 11 53
Make it the current line (5311H).
5EEA
LD HL,(5315H) 2A 15 53
Load Register HL with the end-of-text pointer from 5315H.
5EED
GOSUB to 5DC2H to compare it with the source (DE).
5EF0
The deletion does not reach the end of the text: JUMP to 5F08H.
5EF2
EX (SP),HL E3
Exchange: HL = the first line, the end of the text goes on the stack.
5EF3
PUSH HL E5
Save the first line.
5EF4
PUSH DE D5
Save the source.
5EF5
LD A,(HL) 7E
Load Register A with the first line's number, low byte.
5EF7
LD H,(HL) 66
Load Register H with the high byte.
5EF8
LD L,A 6F
Register L = the low byte.
5EF9
GOSUB to 5CDAH to find that line; 5319H = the line before it.
5EFC
LD HL,(5319H) 2A 19 53
Load Register HL with the line before from 5319H ...
5EFF
LD (5311H),HL 22 11 53
... and make it the current line (5311H).
5F02
POP DE D1
Restore the source.
5F03
POP HL E1
Restore the first line.
5F04
LD (531DH),HL 22 1D 53
Store it into 531DH.
5F07
EX (SP),HL E3
Exchange: HL = the end of the text, the first line goes on the stack.
5F08
PUSH DE D5
Move the Text Down
Save the source.
5F09
XOR A AF
Set Register A to 00H.
5F0A
SUB E 93
Subtract the source's low byte.
5F0B
LD E,A 5F
Register E = the negated low byte.
5F0C
SBC A,D 9A
Subtract the high byte with the borrow (A = -E - D - borrow).
5F0D
SUB E 93
Subtract Register E (A = -D - borrow).
5F0E
LD D,A 57
Register D = the negated high byte: DE = 0 - source.
5F0F
ADD HL,DE 19
HL = end of text - source.
5F11
INC HL 23
... and one more, so the FFH FFH end marker moves too.
5F12
LD B,H 44
Copy the count into Register B ...
5F14
POP HL E1
Restore the source into HL.
5F15
POP DE D1
Restore the destination (the first line) into DE.
5F16
LDIR ED B0
Move the text down over the deleted lines.
5F18
DEC DE 1B
Step DE back ...
5F19
DEC DE 1B
... to the first byte of the moved end marker.
5F1A
EX DE,HL EB
Move it into HL.
5F1B
LD (5315H),HL 22 15 53
Store it into 5315H, the end-of-text pointer.
5F1E
RET C9
RETURN (to the command loop for D, or to the address pushed at 5ED6H).
5F1FH - W Command: Write the Text to Tape
Reached from the appendage at 6F1FH (with a disk file already open when D= was used). Writes the header (D3H and the six-character name) through 6121H, then lists the whole text with line numbers through 5E4FH while the output-to-file flag (53BAH) is set, so every character goes to 710CH instead of the screen, and ends with 1AH. On tape each line is five digits with bit 7 set, a space, the text and 0DH.
5F1F
GOSUB to 6107H to read the file name (default NONAME).
5F22
GOSUB to 5BBEH to check for more on the command line.
5F25
Anything else typed: JUMP to 5D24H for BAD PARAMETER(S).
5F28
LD C,D3H 0E D3
Load Register C with D3H, the source file header byte.
5F2A
GOSUB to 6121H to write the leader (cassette only), D3H and the name.
5F2D
LD HL,53BAH 21 BA 53
Point HL to 53BAH, the output-to-file flag.
5F30
INC (HL) 34
Set it: character output now goes to 710CH.
5F31
PUSH HL E5
Save the flag's address.
5F32
LD BC,0000H 01 00 00
Load Register BC with 0000H: no line limit (the count wraps to FFFFH at 5E4BH).
5F35
LD HL,(5315H) 2A 15 53
Load Register HL with the end-of-text pointer from 5315H ...
5F38
EX DE,HL EB
... as the stop address in DE.
5F39
LD HL,7700H 21 00 77
Load HL with 7700H, the start of the text buffer: W writes the text from the first line up to the end-of-text pointer (DE).
5F3C
GOSUB to 5E4FH to list every line into the file.
5F3F
LD A,1AH 3E 1A
Load Register A with 1AH, the end-of-file byte.
5F41
GOSUB to 710CH to write the 1AH end-of-file byte to the tape or disk file.
5F44
POP HL E1
Restore the flag's address.
5F45
DEC (HL) 35
Clear the output-to-file flag.
5F46
RET C9
RETURN to the command loop (which closes a disk file through 71D5H).
5F47H - L Command: Load Text from Tape
Reached from the appendage at 6F11H. Finds the source file header (D3H and the name; the name is compared only as far as the name typed, and not at all for a disk file), then reads the lines and appends them after the existing text, blinking the indicator at 3C3FH once per line. Each line is five digits with bit 7 set, a space, the text and 0DH; 1AH ends the file.
5F47
GOSUB to 6107H to read the file name.
5F4A
GOSUB to 5BBEH to check for more on the command line.
5F4D
Anything else typed: JUMP to 5D24H for BAD PARAMETER(S).
5F50
GOSUB to 586BH to show READY CASSETTE and wait for a key (skipped for a disk file).
5F53
GOSUB to 706DH: for cassette it starts the tape and finds the leader (ROM 0293H); for a disk file it returns at once.
5F56
Find the Header
GOSUB to 70B6H to read the next byte (tape) or the first byte (disk; a disk file without the D3H header byte is passed straight to the line reader at 5F79H).
5F59
CP D3H FE D3
Compare it with D3H.
5F5B
Not the header: LOOP BACK to 5F56H.
5F5D
LD HL,(53ABH) 2A AB 53
Load Register HL with the file name pointer from 53ABH.
5F60
LD A,(53ADH) 3A AD 53
Load Register A with the name length from 53ADH.
5F63
GOSUB to 704FH: Register C = the number of header name characters to compare (the typed name length, or 00H for a disk file) and Register B = 07H.
5F66
DEC C 0D
Compare the Name
Count one name character.
5F67
All compared: JUMP to 5F74H.
5F6A
DEC B 05
One header byte fewer to skip.
5F6B
GOSUB to 70C6H to read the next header byte from the tape or disk file.
5F6E
CP (HL) BE
Compare it with the name character.
5F6F
INC HL 23
Advance the name pointer.
5F70
Different: JUMP to 5F56H to look for the next header.
5F74
GOSUB to 70C6H to read and skip the next header byte.
5F77
Decrement Register B and LOOP BACK to 5F74H. The last byte read is the first byte of the text.
5F79
CP 1AH FE 1A
Next Line
Compare the byte with 1AH, the end of the file.
5F7B
RET Z C8
End of the file: RETURN.
5F7C
LD B,A 47
Keep the byte (the first digit) in Register B.
5F7D
GOSUB to 5DA9H to check that memory is not full.
5F80
LD HL,7700H 21 00 77
Load Register HL with 7700H ...
5F83
LD (5311H),HL 22 11 53
... and make the first line the current line (5311H).
5F86
LD A,B 78
Load Register A with the first digit.
5F87
LD HL,0000H 21 00 00
HL = 0, the line number.
5F8A
LD B,05H 06 05
Load Register B with 05H, the number of digits.
5F8C
AND 7FH E6 7F
Clear bit 7 of the digit.
5F8E
GOSUB to 5D31H to add the digit to the line number.
5F91
GOSUB to 70C6H to read the next line number digit.
5F94
Decrement Register B and LOOP BACK to 5F8CH. After the fifth digit, the byte read is the space after the number.
5F96
EX DE,HL EB
Move the line number into DE.
5F97
LD HL,(5315H) 2A 15 53
Load Register HL with the end-of-text pointer from 5315H (the new line goes there).
5F9A
LD (HL),E 73
Store the line number's low byte.
5F9C
LD (HL),D 72
Store the high byte.
5F9E
LD (HL),00H 36 00
Store a length of 00H.
5FA0
LD D,H 54
Copy the length byte's address into Register D ...
5FA2
GOSUB to 7086H to blink the load indicator at 3C3FH (asterisk / space).
5FA5
INC HL 23
Character Loop
Advance HL.
5FA6
LD (5315H),HL 22 15 53
Store it into 5315H: the end marker follows the text read so far.
5FA9
LD (HL),FFH 36 FF
Store FFH.
5FAC
LD (HL),FFH 36 FF
Store FFH: the two bytes are the end marker.
5FAE
DEC HL 2B
Step HL back to where the next character goes.
5FAF
GOSUB to 70C6H to read the next text character.
5FB2
CP 0DH FE 0D
Compare with 0DH, the end of the line.
5FB4
Not the end: JUMP to 5FBBH.
5FB6
GOSUB to 70C6H to read the byte after the carriage return (the next line number digit, or 1AH at the end of the file).
5FB9
JUMP to 5F79H for the next line.
5FBB
EX DE,HL EB
Exchange: HL = the length byte.
5FBC
INC (HL) 34
Add one to the length.
5FBD
EX DE,HL EB
Exchange back.
5FBE
LD (HL),A 77
Store the character over the end marker.
5FC1H - E Command: Edit a Line
E line (the current line if no number is typed). Copies the line's text into 5327H with a 00H terminator, displays its number, and reads edit subcommands. Throughout the editor: Register HL = the edit position in the copy, Register D = characters before the cursor, Register E = the line length, Register B = the repeat count typed before a subcommand (1 if none), and 5FE5H is pushed so each subcommand returns for the next key. The line number stays on the stack under it. Subcommands handled here: A (start again from the original line), L (show the edited line and start again at its beginning) and space (move right). The rest are at 6030H-6106H.
5FC1
GOSUB to 5D07H to read the line number (Register HL).
5FC4
GOSUB to 5CDAH to find it. Register BC = the line's address. Also reached from 600EH.
5FC7
The line does not exist: JUMP to 5EB7H for NO SUCH LINE.
5FCA
PUSH HL E5
Save the line number.
5FCB
LD H,B 60
Copy the line's address into Register H ...
5FCD
INC HL 23
Skip the line number ...
5FCE
INC HL 23
... two bytes.
5FCF
LD C,(HL) 4E
Load Register C with the line length.
5FD0
LD B,00H 06 00
Register B = 00H.
5FD2
PUSH BC C5
Save the length.
5FD3
INC HL 23
Point HL at the text.
5FD4
LD DE,5327H 11 27 53
Point DE to the edit buffer at 5327H.
5FD7
GOSUB to 5CC1H to copy the text there.
5FDA
XOR A AF
Set Register A to 00H ...
5FDB
LD (DE),A 12
... and store it after the text as the terminator.
5FDC
POP DE D1
Restore the length into DE (Register E = length, Register D = 00H characters before the cursor).
5FDD
LD HL,5327H 21 27 53
Start of Line
Point HL to the start of the edit buffer. Also reached from 601FH.
5FE0
EX (SP),HL E3
Exchange with the stack: HL = the line number, the edit position goes on the stack.
5FE1
GOSUB to 5D75H to display the line number.
5FE4
EX (SP),HL E3
Exchange back: HL = the edit position, the line number goes on the stack.
5FE5
LD B,00H 06 00
Next Subcommand
Register B = 00H, no repeat count yet. Each subcommand returns here.
5FE7
GOSUB to 5834H to wait for a key.
5FEA
GOSUB to 5BE4H: the CARRY FLAG is clear for a digit.
5FED
Not a digit: JUMP to 5FFBH.
5FEF
SUB 30H D6 30
Convert the digit to its value.
5FF1
LD C,A 4F
Keep it in Register C.
5FF2
LD A,B 78
Load Register A with the count so far.
5FF5
ADD A,B 80
Add the count: x 5.
5FF7
ADD A,C 81
Add the digit.
5FF8
LD B,A 47
Store the new count in Register B.
5FF9
LOOP BACK to 5FE7H for the next key.
5FFB
PUSH HL E5
Save the edit position.
5FFC
LD HL,5FE5H 21 E5 5F
Load Register HL with 5FE5H ...
5FFF
EX (SP),HL E3
... and exchange it with the stack: 5FE5H becomes the return address and HL is the edit position again.
6000
DEC B 05
Test Register B ...
6002
A count was typed: JUMP to 6005H.
6004
INC B 04
No count: use 1.
6005
CP 41H FE 41
Compare the key with 41H (A).
6007
Not A: JUMP to 6010H.
6009
POP BC C1
A: discard the 5FE5H return address.
600A
GOSUB to 5937H to end the output line.
600D
POP HL E1
Restore the line number.
600E
JUMP to 5FC4H to copy the original line again and start over.
6010
CP 4CH FE 4C
Compare the key with 4CH (L).
6012
Not L: JUMP to 6021H.
6014
LD B,80H 06 80
L: load Register B with 80H so 6025H shows everything up to the terminator.
6016
GOSUB to 6025H to show the rest of the line.
6019
GOSUB to 5937H to end the output line.
601C
POP BC C1
Discard the 5FE5H return address.
601D
LD D,00H 16 00
Register D = 00H: the cursor is at the start.
601F
JUMP to 5FDDH to show the line number and continue editing the changed copy from its start.
6021
CP 20H FE 20
Compare the key with 20H (space).
6023
Not a space: JUMP to 6030H for the other subcommands.
6025
LD A,(HL) 7E
Move Right
Load Register A with the character at the edit position. Also called from 6016H, 6036H and 6089H with B = 80H.
6026
OR A B7
Test it for the 00H terminator.
6027
RET Z C8
At the end of the line: RETURN.
6028
INC D 14
One more character before the cursor (Register D).
6029
GOSUB to 5939H to display the character.
602C
INC HL 23
Advance the edit position.
602D
Decrement the count in Register B and LOOP BACK to 6025H.
6030H - Edit Subcommands: ENTER and E (Keep the Edited Line)
Part of the line editor started by the E command at 5FC1H. The line being edited is a 00H-terminated copy in the buffer at 5327H. Throughout the editor: Register HL = the edit position in that copy, Register D = the number of characters before the cursor, Register E = the length of the edited line, Register B = the repeat count typed before the subcommand (1 if none), and the top of the stack holds 5FE5H so each subcommand's RET goes back for the next key. ENTER shows the rest of the line first; E does not. Both then replace the original line in the text with the edited copy.
6030
CP 0DH FE 0D
Compare the subcommand key in Register A against 0DH (ENTER).
6032
If it is not ENTER, JUMP to 6047H to test the next subcommand.
6034
LD B,80H 06 80
ENTER: load Register B with 80H (128), more than any line length, so the whole rest of the line is shown.
6036
GOSUB to 6025H to display the characters from the edit position (HL) to the 00H terminator. Register D counts them.
6039
Accept the Line
GOSUB to 5937H to output a carriage return.
603C
POP BC C1
Discard the 5FE5H subcommand return address from the stack.
603D
LD A,E 7B
Load Register A with Register E, the length of the edited line.
603E
LD (53AAH),A 32 AA 53
Store the length into 53AAH, the input character count that the line-insert code uses when it copies the new line from 5327H.
6041
LD BC,5C60H 01 60 5C
Load Register BC with 5C60H, the continuation address for 5ED6H. 5C60H is the second byte of the LD B,B7H at 5C5FH, so it resumes with B7H = OR A inside the line-insert routine.
6044
JUMP to 5ED6H, which pushes 5C60H, removes the original line from the text buffer, and returns to 5C60H to insert the edited line.
6047H - Edit Subcommands E, C, D, Q, I, X, H, S, K and Backspace
Continues the subcommand tests begun at 6005H. Register A = the subcommand key, Register B = the repeat count, HL = edit position, D = characters before the cursor, E = line length.
6047
CP 45H FE 45
Compare the key against 45H (E, end the edit without showing the rest of the line).
6049
If E, JUMP to 6039H to replace the original line with the edited copy.
604B
CP 43H FE 43
Compare the key against 43H (C, change characters).
604D
If not C, JUMP to 6066H.
604F
LD A,(HL) 7E
Change Loop
Load Register A with the character at the edit position (HL).
6050
OR A B7
Test it for 00H, the end of the line.
6051
RET Z C8
If at the end of the line, RETURN to 5FE5H for the next subcommand.
6052
GOSUB to 5834H to wait for the replacement key (returned in Register A).
6055
CP 09H FE 09
Compare the key against 09H (tab).
6057
A tab is accepted: JUMP to 605DH.
6059
CP 1AH FE 1A
Compare the key against 1AH.
605B
Any other control code below 1AH is ignored: LOOP BACK to 6052H for another key.
605D
LD (HL),A 77
Store the new character over the old one in the edit buffer.
605E
GOSUB to 5939H to display the new character.
6061
INC HL 23
Advance the edit position (HL).
6062
INC D 14
Count one more character before the cursor (Register D).
6063
Decrement the repeat count in Register B and LOOP BACK to 604FH until it reaches zero.
6065
RET C9
RETURN to 5FE5H for the next subcommand.
6066
CP 44H FE 44
Compare the key against 44H (D, delete characters).
6068
If not D, JUMP to 6073H.
606A
LD A,(HL) 7E
Delete Loop
Load Register A with the character at the edit position.
606B
OR A B7
Test it for 00H, the end of the line.
606C
RET Z C8
If at the end of the line, RETURN to 5FE5H.
606D
GOSUB to 60A1H to remove the character at HL (the rest of the line moves left one byte and Register E decreases by 1).
6070
Decrement the repeat count in Register B and LOOP BACK to 606AH until it reaches zero.
6072
RET C9
RETURN to 5FE5H for the next subcommand.
6073
CP 51H FE 51
Compare the key against 51H (Q, quit).
6075
If Q, JUMP to 58D7H: output a carriage return and go back to the command loop. The original line is left unchanged.
6078
CP 49H FE 49
Compare the key against 49H (I, insert at the cursor).
607A
If I, JUMP to 608CH, the insert loop.
607C
CP 58H FE 58
Compare the key against 58H (X, extend: go to the end of the line and insert).
6080
CP 48H FE 48
Compare the key against 48H (H, hack: delete the rest of the line and insert).
6082
If not H, JUMP to 60DAH.
6084
LD (HL),00H 36 00
H: store 00H at the edit position, cutting the line off at the cursor.
6086
LD E,D 5A
The line length (Register E) is now the number of characters before the cursor (Register D).
6087
LD B,80H 06 80
Load Register B with 80H so that 6025H shows everything up to the terminator.
6089
GOSUB to 6025H to display the rest of the line and move HL and D to its end.
608C
Insert Loop
GOSUB to 5834H to wait for a key (returned in Register A).
608F
CP 0DH FE 0D
Compare the key against 0DH (ENTER).
6091
If ENTER, JUMP to 6034H: show the rest of the line and replace the original line with the edited copy.
6093
CP 1BH FE 1B
Compare the key against 1BH (shift up arrow, escape).
6095
RET Z C8
If 1BH, leave insert mode: RETURN to 5FE5H for the next subcommand.
6096
CP 08H FE 08
Compare the key against 08H (backspace).
6098
If not a backspace, JUMP to 60B1H to insert the character.
609A
Backspace: GOSUB to 5B89H, which moves the edit position (HL) back one character and backspaces the display (it returns at once if Register D = 00H).
609D
LD BC,608CH 01 8C 60
Load Register BC with 608CH, the insert loop address ...
60A0
PUSH BC C5
... and push it as the return address, so the delete below returns to the insert loop.
60A1
PUSH HL E5
Delete One Character
Save the edit position (HL).
60A2
DEC E 1D
The line is one character shorter: decrement Register E.
60A3
LD A,(HL) 7E
Shift Loop
Load Register A with the byte at HL.
60A4
OR A B7
Test it for 00H.
60A5
SCF 37
Set the CARRY FLAG (the Z FLAG from the OR A is kept).
60A6
If the terminator has been reached, JUMP to 60AFH.
60A8
INC HL 23
Point HL at the following byte.
60A9
LD A,(HL) 7E
Load Register A with that byte.
60AA
DEC HL 2B
Step HL back.
60AB
LD (HL),A 77
Copy the following byte down one position.
60AF
POP HL E1
Restore the edit position into HL.
60B0
RET C9
RETURN with the CARRY FLAG set.
60B1
CP 09H FE 09
Compare the key against 09H (tab).
60B3
A tab is accepted: JUMP to 60B9H.
60B5
CP 1AH FE 1A
Compare the key against 1AH.
60B7
Any other control code below 1AH is ignored: LOOP BACK to 608CH.
60B9
PUSH AF F5
Insert a Character
Save the key in Register A.
60BA
LD A,E 7B
Load Register A with the line length (Register E).
60BB
CP 80H FE 80
Compare it against 80H (128), the longest line allowed.
60BD
If the line is shorter, JUMP to 60C2H.
60BF
POP AF F1
The line is full: discard the key ...
60C0
... and LOOP BACK to 608CH.
60C2
SUB D 92
Subtract the characters before the cursor (Register D): Register A = characters from the cursor to the end.
60C3
LD C,A 4F
Copy that count into Register C.
60C4
INC C 0C
Add one for the 00H terminator.
60C5
LD B,00H 06 00
Register BC = the number of bytes to move.
60C7
ADD HL,BC 09
Point HL one byte past the 00H terminator (edit position + characters to the end + 1).
60C8
PUSH DE D5
Save Register DE.
60C9
LD D,H 54
Copy that address into Register D ...
60CA
LD E,L 5D
... and Register E: DE is the destination of the move.
60CB
DEC HL 2B
Step HL back to the terminator, the source of the move, so the tail moves up by one byte.
60CC
LDDR ED B8
Move the rest of the line (and its terminator) up one byte, working backward.
60CE
POP DE D1
Restore Register DE.
60CF
INC D 14
One more character before the cursor (Register D).
60D0
INC E 1C
The line is one character longer (Register E).
60D1
POP AF F1
Restore the key into Register A.
60D2
INC HL 23
Point HL at the gap that the move opened up.
60D3
LD (HL),A 77
Store the new character in the gap.
60D4
INC HL 23
Advance the edit position past it.
60D5
GOSUB to 5939H to display the new character.
60D8
LOOP BACK to 608CH for the next key.
60DA
CP 53H FE 53
Compare the key against 53H (S, search: move to the Nth occurrence of a character).
60DC
If S, JUMP to 60E3H with the CARRY FLAG clear.
60DE
CP 4BH FE 4B
Compare the key against 4BH (K, kill: delete up to the Nth occurrence of a character).
60E0
If neither, JUMP to 6101H.
60E2
SCF 37
K: set the CARRY FLAG to select deleting instead of moving.
60E3
PUSH AF F5
Save the S/K choice (the CARRY FLAG) on the stack.
60E4
GOSUB to 5834H to wait for the character to search for.
60E7
LD C,A 4F
Keep the search character in Register C.
60E8
LD A,(HL) 7E
Search Loop
Load Register A with the character at the edit position.
60E9
OR A B7
Test for the 00H terminator.
60EA
If the end of the line is reached, JUMP to 60FFH.
60EC
POP AF F1
Get the S/K choice back ...
60ED
PUSH AF F5
... and save it again.
60EE
LD A,(HL) 7E
Load Register A with the character at the edit position.
60EF
S (NO CARRY): GOSUB to 5939H to display the character being passed over.
60F2
K (CARRY): GOSUB to 60A1H to delete it (60A1H returns with the CARRY FLAG set).
60F5
For K, JUMP to 60F9H: the next character has moved into this position.
60F7
INC HL 23
For S, advance the edit position ...
60F8
INC D 14
... and count one more character before the cursor.
60F9
LD A,(HL) 7E
Load Register A with the character now at the edit position.
60FA
CP C B9
Compare it with the search character in Register C.
60FB
If it does not match, LOOP BACK to 60E8H.
60FD
A match: decrement the repeat count in Register B and LOOP BACK to 60E8H until the Nth match is reached.
60FF
POP AF F1
Discard the saved S/K choice.
6100
RET C9
RETURN to 5FE5H for the next subcommand.
6101
CP 08H FE 08
Compare the key against 08H (backspace).
6103
RET NZ C0
Any other key is ignored: RETURN to 5FE5H.
6104
JUMP to 5B89H to move the edit position back one character (5B89H returns to 5FE5H).
6107H - Read a File Name
Used by W, L (5F1FH, 5F47H) and the assembler command (63FDH). Clears the name length (53ADH), then takes the next word on the command line as the file name if it is an identifier (type 00H from 61D6H) of at most six characters: 53ABH = its address, 53ADH = its length. Anything else is put back for the caller to reject; seven or more characters give BAD PARAMETER(S).
6107
LD HL,53ADH 21 AD 53
Point HL to 53ADH, the file name length.
610A
LD (HL),00H 36 00
Set it to 00H (no name).
610C
GOSUB to 61A8H to skip spaces and classify the next word (Register A = type, C = length, DE = its address; Z FLAG at the end of the line).
610F
RET Z C8
Nothing typed: RETURN.
6110
OR A B7
Test the type.
6111
Not an identifier: JUMP to 5BF4H, which puts the character back and returns.
6114
LD A,C 79
Load Register A with the length.
6115
CP 07H FE 07
Compare with 07H.
6117
Seven or more characters: JUMP to 5D24H for BAD PARAMETER(S).
611A
LD (HL),A 77
Store the length into 53ADH.
611B
EX DE,HL EB
Exchange: HL = the name's address.
611C
LD (53ABH),HL 22 AB 53
Store it into 53ABH, the file name pointer.
611F
EX DE,HL EB
Exchange back.
6121H - Write a File Header
Register C = the header byte (D3H for source text, 55H for object code). Shows READY CASSETTE and waits (cassette only), writes the cassette leader (7079H, cassette only), then writes the header byte, the file name and spaces up to six characters. Every byte goes through 710CH (tape, or the appendage's disk file).
6121
GOSUB to 586BH: READY CASSETTE and wait for a key, unless a disk file is open.
6124
LD A,(53ADH) 3A AD 53
Load Register A with the name length from 53ADH ...
6127
LD E,A 5F
... into Register E.
6128
LD A,06H 3E 06
Load Register A with 06H.
612A
SUB E 93
Subtract the name length.
612B
LD B,A 47
Register B = the number of padding spaces.
612C
LD HL,(53ABH) 2A AB 53
Load Register HL with the file name pointer from 53ABH.
612F
PUSH BC C5
Save Register BC (the header byte and the padding count).
6130
GOSUB to 7079H: for cassette it starts the tape and writes the leader (ROM 0284H); for a disk file it returns at once.
6133
POP BC C1
Restore Register BC.
6134
LD A,C 79
Load Register A with the header byte from Register C.
6135
GOSUB to 710CH to write the header byte in Register A (55H for object code, D3H for source text) to the tape or disk file.
6138
DEC E 1D
Name Loop
Count one name character.
6139
LD A,(HL) 7E
Load Register A with the next name character.
613B
Characters remain (count not negative): GOSUB to 710CH to write it.
613E
LOOP BACK to 6138H while characters remain.
6141
LD A,20H 3E 20
Padding Loop
Load Register A with 20H (space).
6143
DEC B 05
Count one space.
6144
Spaces remain: GOSUB to 710CH to write one.
6147
LOOP BACK to 6141H while spaces remain.
614BH - Report an Assembler Error
Register DE = the message. Adds one to the error count (53B8H) and, in pass 2 only, displays the message (and prints it when LP is set) and sets 53BFH (the WE switch pauses on it).
614BH
Also displays the source line and then abandons it: 6496H (the next source line) is pushed as the return address, and Register A = AFH selects printing the line.
6150H
The second byte of the LD A,AFH at 614FH, so it runs AFH = XOR A: the message only, and the routine returns to its caller so assembly of the line continues. Registers BC and HL are preserved.
614B
LD BC,6496H 01 96 64
Load Register BC with 6496H, the assembler's next-line entry ...
614E
PUSH BC C5
... and push it as the return address.
614F
LD A,AFH 3E AF
Load Register A with AFH (non-zero: print the source line too). This instruction exists for the 6150H entry: its operand AFH is XOR A.
6151
PUSH BC C5
Save Register BC.
6152
PUSH HL E5
Save Register HL.
6153
LD HL,(53B8H) 2A B8 53
Load Register HL with the error count from 53B8H.
6157
LD (53B8H),HL 22 B8 53
Store it back.
615A
EX DE,HL EB
Exchange: HL = the message, DE = the error count.
615B
LD B,A 47
Keep the line flag (Register A) in Register B.
615C
LD A,(53C0H) 3A C0 53
Load Register A with the pass number from 53C0H.
615F
CP 02H FE 02
Compare with 02H.
6161
Not pass 2: JUMP to 617BH without displaying anything.
6163
GOSUB to 617FH to display the message (and print it when LP is set).
6166
LD A,B 78
Load Register A with the line flag.
6168
00H (6150H entry): JUMP to 6176H.
616A
LD BC,0001H 01 01 00
Load Register BC with 0001H: one line.
616D
LD DE,5E4FH 11 4F 5E
Load Register DE with 5E4FH, the "show one line" routine.
6170
LD HL,(5311H) 2A 11 53
Load Register HL with the current source line from 5311H.
6173
GOSUB to 6182H to show the source line (and print it when LP is set).
6176
LD A,01H 3E 01
Load Register A with 01H ...
6178
LD (53BFH),A 32 BF 53
... and store it into 53BFH: this line had an error.
617B
EX DE,HL EB
Exchange: HL = the error count again (DE = the message).
617C
POP HL E1
Restore Register HL.
617D
POP BC C1
Restore Register BC.
617FH - Display on the Screen, and Print When LP Is Set
617FH
Loads DE with 592FH (display a message) and continues at 6182H.
6182H
Calls the routine whose address is in DE with HL and BC as given. Then, unless the NL switch is set, and if the LP switch is set, turns the printer flag (53BCH) on, calls the routine a second time and turns the flag off again.
617F
LD DE,592FH 11 2F 59
Load Register DE with 592FH, the message display routine.
6182
PUSH DE D5
Save the routine address.
6183
PUSH BC C5
Save Register BC.
6184
PUSH HL E5
Save Register HL.
6185
PUSH HL E5
Push HL again.
6186
LD HL,618CH 21 8C 61
Load Register HL with 618CH ...
6189
EX (SP),HL E3
... and exchange with the stack: 618CH is the return address and HL is restored.
618A
PUSH DE D5
Push the routine address.
618B
RET C9
RETURN into the routine (it returns to 618CH).
618C
POP HL E1
Restore Register HL.
618D
POP BC C1
Restore Register BC.
618E
POP DE D1
Restore the routine address into DE.
618F
LD A,(5876H) 3A 76 58
Load Register A with the NL switch flag from 5876H.
6193
RET NZ C0
No listing: RETURN.
6194
LD A,(587EH) 3A 7E 58
Load Register A with the LP switch flag from 587EH.
6198
RET Z C8
No printer copy: RETURN.
6199
LD (53BCH),A 32 BC 53
Store the non-zero flag into 53BCH: output goes to the printer.
619D
LD HL,61A3H 21 A3 61
Load Register HL with 61A3H ...
61A0
EX (SP),HL E3
... and exchange with the stack: 61A3H is the return address and HL is restored.
61A1
PUSH DE D5
Push the routine address.
61A2
RET C9
RETURN into the routine (it returns to 61A3H).
61A3
XOR A AF
Set Register A to 00H ...
61A4
LD (53BCH),A 32 BC 53
... and clear the printer flag (53BCH).
61A8H - Operand Classification
Reads the next word of an operand and reports what it is. Register DE returns its address, Register C its length, Register A its type, Register B the register number for types 03H-09H. The Z FLAG is set only when the line has ended.
Types
00H = an identifier that is not a register name (a symbol), 01H = a word starting with a digit (a number), 02H = any other single character (for example (, ', $, +), 03H = 8-bit register, 04H = register pair, 05H = IX or IY, 06H = condition, 07H = AF, 08H = I or R, 09H = ON or OFF (see the table at 621AH).
Entries
61A8H skips spaces first (5BBBH). 61D6H does not. 61B5H, 61B3H, 61B0H and 61ADH also check the type against an expected value (in A, or 03H, 04H, 05H) and return the Z FLAG if it matches; a missing operand gives MISSING INFORMATION.
61A8
GOSUB to 5BBBH to get the next non-space character.
61AB
JUMP to 61D9H to classify the word that starts with it.
61AD
LD A,05H 3E 05
Expect IX or IY
Load Register A with 05H.
61AF
LD BC,043EH 01 3E 04
Load Register BC with 043EH. This instruction exists for the 61B0H entry: its operand bytes 3EH 04H are LD A,04H. From 61ADH it only changes BC.
61B2
LD BC,033EH 01 3E 03
Load Register BC with 033EH. This instruction exists for the 61B3H entry: its operand bytes 3EH 03H are LD A,03H.
61B5
PUSH HL E5
Expect the Type in A
Save Register HL.
61B6
LD L,A 6F
Keep the expected type in Register L.
61B7
GOSUB to 61D6H to classify the next word.
61BA
Nothing there: JUMP to 61D0H for MISSING INFORMATION.
61BC
PUSH BC C5
Save Register BC (register number and length).
61BD
LD B,A 47
Keep the type in Register B.
61BE
LD A,(DE) 1A
Load Register A with the word's first character.
61BF
CP 3BH FE 3B
Compare with 3BH (semicolon).
61C1
A comment: JUMP to 61D0H for the error.
61C3
CP 09H FE 09
Compare with 09H (tab).
61C5
A tab: JUMP to 61D0H for the error.
61C7
CP 20H FE 20
Compare with 20H (space).
61C9
LD A,B 78
Load Register A with the type (the flags are kept).
61CA
POP BC C1
Restore Register BC.
61CB
A space: JUMP to 61D0H for the error.
61CD
CP L BD
Compare the type with the expected type. The Z FLAG is set if they match.
61CE
POP HL E1
Restore Register HL.
61D0
LD DE,5A18H 11 18 5A
Missing Information
Point DE to MISSING INFORMATION at 5A18H.
61D3
JUMP to 614BH to report the error and abandon the line.
61D6
Classify
GOSUB to 5BBEH to get the next character.
61D9
PUSH HL E5
Save Register HL.
61DA
LD HL,(53A8H) 2A A8 53
Load Register HL with the input scan pointer from 53A8H.
61DD
DEC HL 2B
Step back to the character just read.
61DE
EX DE,HL EB
Exchange: DE = the word's address.
61DF
POP HL E1
Restore Register HL.
61E0
LD C,01H 0E 01
Register C = 01H character so far.
61E2
RET Z C8
The line has ended: RETURN with the Z FLAG.
61E3
A digit: JUMP to 6206H, which counts the word and returns type 01H.
61E5
GOSUB to 5BEDH: the CARRY FLAG is set if the character is not a letter.
61E8
LD A,02H 3E 02
Load Register A with 02H (the flags are kept).
61EA
RET C D8
Not a letter: RETURN with type 02H and the NZ FLAG.
61EB
GOSUB to 6206H to count the word's letters and digits (Register C).
61EE
PUSH HL E5
Save Register HL.
61EF
LD HL,621AH 21 1A 62
Point HL to the register name table at 621AH.
61F2
LD B,01H 06 01
Load Register B with 01H: each entry has one data byte after the name.
61F4
GOSUB to 627CH to look the word up. HL returns at the entry's data byte, or at the 00H end marker.
61F7
LD A,(HL) 7E
Load Register A with the data byte.
61F8
AND 0FH E6 0F
Keep bits 0-3 ...
61FA
LD B,A 47
... as the register number in Register B.
61FB
LD A,(HL) 7E
Load Register A with the data byte again.
61FC
RRCA 0F
Rotate right: bits 4-7 move down one place ...
61FD
RRCA 0F
... two places ...
61FE
RRCA 0F
... three places ...
61FF
RRCA 0F
... four places, into bits 0-3.
6200
AND 0FH E6 0F
Keep them: the type (00H if the word is not a register name).
6202
POP HL E1
Restore Register HL.
6203
CP 10H FE 10
Compare with 10H: this clears the Z FLAG.
6205
RET C9
RETURN with the type in Register A.
6206
INC C 0C
Count the Word
Count one more character.
6207
GOSUB to 5BBEH for the next character.
620A
The line has ended: JUMP to 6216H.
620C
A digit: LOOP BACK to 6206H.
620E
GOSUB to 5BEDH to test for a letter.
6211
A letter: LOOP BACK to 6206H.
6213
Anything else ends the word: GOSUB to 5BF4H to put it back.
6216
DEC C 0D
Do not count the character that ended the word.
6217
LD A,01H 3E 01
Load Register A with 01H (type 01H for a number; the NZ FLAG comes from the DEC C).
621A-621C
DEFB 01H, 41H, 37H 01 41 37
Register Name Table (Data)
Each entry: name length, name, data byte (bits 4-7 = type, bits 0-3 = register number). "A": type 3, register 7.
621D-621F
DEFB 01H, 42H, 30H 01 42 30
"B": type 3, register 0.
6220-6222
DEFB 01H, 43H, 31H 01 43 31
"C": type 3, register 1.
6223-6225
DEFB 01H, 44H, 32H 01 44 32
"D": type 3, register 2.
6226-6228
DEFB 01H, 45H, 33H 01 45 33
"E": type 3, register 3.
6229-622B
DEFB 01H, 48H, 34H 01 48 34
"H": type 3, register 4.
622C-622E
DEFB 01H, 4CH, 35H 01 4C 35
"L": type 3, register 5.
622F-6232
DEFB 02H, 42H, 43H, 40H 02 42 43 40
"BC": type 4, pair 0.
6233-6236
DEFB 02H, 44H, 45H, 41H 02 44 45 41
"DE": type 4, pair 1.
6237-623A
DEFB 02H, 48H, 4CH, 42H 02 48 4C 42
"HL": type 4, pair 2.
623B-623E
DEFB 02H, 53H, 50H, 43H 02 53 50 43
"SP": type 4, pair 3.
623F-6242
DEFB 02H, 49H, 58H, 50H 02 49 58 50
"IX": type 5, 0.
6243-6246
DEFB 02H, 49H, 59H, 51H 02 49 59 51
"IY": type 5, 1.
6247-624A
DEFB 02H, 4EH, 5AH, 60H 02 4E 5A 60
"NZ": type 6, condition 0.
624B-624D
DEFB 01H, 5AH, 61H 01 5A 61
"Z": type 6, condition 1.
624E-6251
DEFB 02H, 4EH, 43H, 62H 02 4E 43 62
"NC": type 6, condition 2.
6252-6255
DEFB 02H, 50H, 4FH, 64H 02 50 4F 64
"PO": type 6, condition 4.
6256-6259
DEFB 02H, 50H, 45H, 65H 02 50 45 65
"PE": type 6, condition 5.
625A-625C
DEFB 01H, 50H, 66H 01 50 66
"P": type 6, condition 6.
625D-625F
DEFB 01H, 4DH, 67H 01 4D 67
"M": type 6, condition 7.
6260-6263
DEFB 02H, 41H, 46H, 73H 02 41 46 73
"AF": type 7, 3.
6264-6266
DEFB 01H, 49H, 80H 01 49 80
"I": type 8, 0.
6267-6269
DEFB 01H, 52H, 88H 01 52 88
"R": type 8, 8.
626A-626D
DEFB 02H, 4FH, 4EH, 90H 02 4F 4E 90
"ON": type 9, 0.
626E-6272
DEFB 03H, 4FH, 46H, 46H, 91H 03 4F 46 46 91
"OFF": type 9, 1.
6273
DEFB 00H 00
End of the table.
6274H - Table Search
Searches a table of entries [length byte (bits 0-4)][name][B data bytes] for the word at DE whose length is in Register C. Returns NO CARRY with HL at the matching entry's data bytes, or the CARRY FLAG with HL at the 00H end byte. Used for the register names (621AH), the assembler switches (5873H) and the mnemonics (6BD9H). Registers BC and DE are preserved.
6274
LD A,C 79
Skip to the Next Entry
Load Register A with the name characters not yet compared (Register C).
6275
ADD A,B 80
Add the number of data bytes (Register B).
6276
LD C,A 4F
Register C = the bytes to skip.
6277
LD B,00H 06 00
Register B = 00H.
6279
ADD HL,BC 09
HL = the next entry.
627A
POP DE D1
Restore the word's address.
627B
POP BC C1
Restore Register BC (the length and the data byte count).
627C
LD A,(HL) 7E
Entry Loop
Load Register A with the entry's length byte. Main entry.
627D
AND 1FH E6 1F
Keep bits 0-4.
627F
SCF 37
Set the CARRY FLAG (not found).
6280
RET Z C8
A length of 0 ends the table: RETURN with the CARRY FLAG.
6281
INC HL 23
Point HL at the entry's name.
6282
PUSH BC C5
Save Register BC.
6283
PUSH DE D5
Save the word's address.
6284
CP C B9
Compare the entry's length with the word's length.
6285
Different: JUMP to 6275H to skip the whole name and data.
6287
LD A,(DE) 1A
Compare Characters
Load Register A with the next character of the word.
6289
CP (HL) BE
Compare with the entry's character.
628A
Different: JUMP to 6274H to skip the rest.
628D
DEC C 0D
Count one character.
628E
More characters: LOOP BACK to 6287H.
6290
POP DE D1
Found: restore the word's address.
6291
POP BC C1
Restore Register BC.
6292
RET C9
RETURN with NO CARRY and HL at the data bytes.
6293H - Evaluate an Expression
Returns the value of the operand expression in Register DE (Registers BC and HL are preserved).
62A0H
The normal entry: classifies the first term itself.
6293H
Used when the caller has already called 61D6H (Register A = the type, DE = the word): END (6B9CH).
A term is a symbol (its value from 65A6H), a number (635AH), a character constant 'c' (63A0H) or $ (the location counter, 53B6H); a term may be preceded by + or -. Terms are combined left to right, with no precedence, by +, -, & (AND) and < (shift left by the term, or right if it is negative). The result is kept in 53C1H. The expression ends at a space, tab, the end of the line, or (put back for the caller) at ;, , or ). Anything else is EXPRESSION ERROR.
6293
PUSH BC C5
Save Register BC.
6294
PUSH HL E5
Save Register HL.
6295
LD HL,0000H 21 00 00
Load Register HL with 0000H ...
6298
PUSH HL E5
... and push it: no operator is pending (Register B = 00H) and no minus sign (Register C = 00H).
6299
LD B,A 47
Keep the type in Register B.
629A
LD A,(DE) 1A
Load Register A with the word's first character.
629B
CP 0DH FE 0D
Compare with 0DH: the Z FLAG is set at the end of the line.
629D
LD A,B 78
Restore the type into Register A.
62A0
PUSH BC C5
Main Entry
Save Register BC.
62A1
PUSH HL E5
Save Register HL.
62A2
LD HL,0000H 21 00 00
Load Register HL with 0000H ...
62A5
LD (53C1H),HL 22 C1 53
... and clear the result at 53C1H.
62A8
LD B,H 44
Register B = 00H: no operator is pending.
62A9
LD C,H 4C
Register C = 00H: no minus sign.
62AA
PUSH BC C5
Next Term
Push the pending operator (B) and the minus flag (C).
62AB
GOSUB to 61D6H to classify the next word.
62AE
A word is there: JUMP to 62BDH.
62B0
POP BC C1
End of the Expression
Restore the pending operator and minus flag.
62B1
INC B 04
Test Register B ...
62B3
No term was read at all: JUMP to 61D0H for MISSING INFORMATION.
62B6
LD HL,(53C1H) 2A C1 53
Load Register HL with the result from 53C1H ...
62B9
EX DE,HL EB
... into DE.
62BA
POP HL E1
Restore Register HL.
62BB
POP BC C1
Restore Register BC.
62BC
RET C9
RETURN with the value in DE.
62BD
OR A B7
Test the type.
62BE
00H, a symbol: JUMP to 6305H.
62C0
DEC A 3D
Subtract one.
62C1
01H, a number: JUMP to 635AH.
62C4
LD A,(DE) 1A
Load Register A with the character.
62C5
CP 27H FE 27
Compare with 27H (apostrophe).
62C7
A character constant: JUMP to 63A0H.
62CA
LD HL,(53B6H) 2A B6 53
Load Register HL with the location counter from 53B6H.
62CD
CP 24H FE 24
Compare with 24H ($).
62CF
$: JUMP to 6308H with the location counter as the term.
62D1
GOSUB to 62E8H: ends the expression at a delimiter, otherwise returns.
62D4
CP 2BH FE 2B
Compare with 2BH (+).
62D6
A leading plus sign: LOOP BACK to 62AAH for the term.
62D8
CP 2DH FE 2D
Compare with 2DH (-).
62DA
Anything else: JUMP to 62E2H for the error.
62DC
LD A,C 79
A minus sign: load the minus flag ...
62DD
CPL 2F
... and complement it (00H becomes FFH).
62E0
First minus sign: LOOP BACK to 62AAH for the term. A second one falls into the error.
62E2
LD DE,5AA4H 11 A4 5A
Expression Error
Point DE to EXPRESSION ERROR at 5AA4H.
62E5
JUMP to 614BH to report it and abandon the line.
62E8
POP DE D1
Delimiter Check
Pop the return address into DE.
62E9
CP 20H FE 20
Compare the character with 20H (space).
62EB
A space ends the expression: JUMP to 62B0H.
62ED
CP 09H FE 09
Compare with 09H (tab).
62EF
A tab ends the expression: JUMP to 62B0H.
62F1
POP BC C1
Restore the pending operator and minus flag into BC.
62F2
CP 3BH FE 3B
Compare with 3BH (semicolon).
62F4
A comment: JUMP to 6300H.
62F6
CP 2CH FE 2C
Compare with 2CH (comma).
62F8
A comma: JUMP to 6300H.
62FA
CP 29H FE 29
Compare with 29H ()).
62FC
A closing parenthesis: JUMP to 6300H.
62FE
PUSH DE D5
Anything else: push the return address ...
62FF
RET C9
... and RETURN to the caller with the character in Register A.
6300
GOSUB to 5BF4H to put the character back for the caller.
6303
JUMP to 62B6H to return the result.
6305
Symbol
GOSUB to 65A6H to look the symbol up. HL = its value.
6308
POP BC C1
Apply the Term
Restore the pending operator (B) and the minus flag (C).
6309
INC C 0C
Add one to the minus flag: it becomes 00H (Z FLAG) only if it was FFH.
630A
LD C,00H 0E 00
Clear the minus flag for the next term (the flags are kept).
630C
No minus sign: JUMP to 6314H.
630E
XOR A AF
Negate HL: set Register A to 00H.
630F
SUB L 95
Subtract the low byte.
6310
LD L,A 6F
Register L = the negated low byte.
6311
SBC A,H 9C
Subtract the high byte with the borrow (A = -L - H - borrow).
6312
SUB L 95
Subtract Register L, which holds -L (A = -H - borrow).
6313
LD H,A 67
Register H = the negated high byte.
6314
PUSH BC C5
Push the pending operator.
6315
LD DE,63D4H 11 D4 63
Load Register DE with 63D4H ...
6318
PUSH DE D5
... and push it: the operator code below returns to 63D4H.
6319
LD A,B 78
Load Register A with the pending operator.
631B
An operator is pending: JUMP to 6321H.
631D
LD (53C1H),HL 22 C1 53
The first term: store it as the result in 53C1H.
6320
RET C9
RETURN to 63D4H.
6321
CP 2BH FE 2B
Compare the operator with 2BH (+).
6323
JUMP to 63C0H to add.
6326
CP 2DH FE 2D
Compare with 2DH (-).
6328
JUMP to 63BAH to subtract.
632B
CP 26H FE 26
Compare with 26H (&).
632D
JUMP to 63C9H for AND.
6330
CP 3CH FE 3C
Compare with 3CH (<).
6332
Anything else: JUMP to 62E2H for EXPRESSION ERROR.
6334
EX DE,HL EB
Shift
Move the shift count (the term) into DE.
6335
LD HL,(53C1H) 2A C1 53
Load Register HL with the result from 53C1H.
6338
LD A,D 7A
Load Register A with the count's high byte.
6339
RLA 17
Rotate its sign bit into the CARRY FLAG.
633A
A negative count: JUMP to 6349H to shift right.
633C
INC DE 13
Add one to the count.
633D
LD (53C1H),HL 22 C1 53
Shift Left Loop
Store the value into 53C1H.
6340
LD B,H 44
Copy the high byte into Register B ...
6341
LD C,L 4D
... and the low byte into Register C.
6342
ADD HL,BC 09
Add: HL = value x 2.
6344
LD A,D 7A
Load Register A with the count's high byte ...
6345
OR E B3
... OR the low byte.
6346
Not finished: LOOP BACK to 633DH. The value stored last has been doubled the requested number of times.
6348
RET C9
RETURN to 63D4H.
6349
DEC DE 1B
Take one off the negative count.
634A
LD (53C1H),HL 22 C1 53
Shift Right Loop
Store the value into 53C1H.
634D
XOR A AF
Clear the CARRY FLAG.
634E
LD A,H 7C
Load Register A with the high byte.
634F
RRA 1F
Shift it right (a 0 enters bit 7).
6350
LD H,A 67
Store it back into Register H.
6351
LD A,L 7D
Load Register A with the low byte.
6352
RRA 1F
Shift it right (bit 0 of the high byte enters bit 7).
6353
LD L,A 6F
Store it back into Register L.
6355
LD A,D 7A
Load Register A with the count's high byte ...
6356
OR E B3
... OR the low byte.
6357
Not finished: LOOP BACK to 634AH.
6359
RET C9
RETURN to 63D4H.
635AH - Number and Character Constants
635AH
A number. The last character selects the base: H = 16, O or Q = 8, D or a digit = 10. Each character must be a digit (0-9, A-F) below the base, otherwise EXPRESSION ERROR. Register DE = the word, Register C = its length.
63A0H
A character constant: exactly one character between apostrophes; its value is the character code.
635A
LD HL,0000H 21 00 00
Set the value (HL) to 0000H.
635D
LD B,0AH 06 0A
Load Register B with 0AH: base 10.
635F
GOSUB to 5BF4H to step the input back to the last character of the word.
6362
GOSUB to 5BBEH to read that character.
6365
A digit: JUMP to 637DH with base 10.
6367
DEC C 0D
The last character is a suffix, not a digit: one character fewer to convert.
6368
CP 44H FE 44
Compare with 44H (D).
636A
Decimal: JUMP to 637DH.
636C
LD B,08H 06 08
Load Register B with 08H: base 8.
636E
CP 4FH FE 4F
Compare with 4FH (O).
6370
Octal: JUMP to 637DH.
6372
CP 51H FE 51
Compare with 51H (Q).
6374
Octal: JUMP to 637DH.
6376
LD B,10H 06 10
Load Register B with 10H: base 16.
6378
CP 48H FE 48
Compare with 48H (H).
637A
Any other suffix: JUMP to 62E2H for EXPRESSION ERROR.
637D
LD A,(DE) 1A
Digit Loop
Load Register A with the next character of the word.
637F
GOSUB to 5BE4H: NO CARRY for 0-9.
6382
A digit: JUMP to 6386H.
6384
SUB 07H D6 07
A letter: subtract 07H so that A-F follow 9.
6386
SUB 30H D6 30
Subtract 30H: the digit's value.
6388
CP B B8
Compare it with the base.
6389
Too large for the base: JUMP to 62E2H for the error.
638C
PUSH BC C5
Save Register BC.
638D
PUSH DE D5
Save Register DE.
638E
LD D,H 54
Copy the value's high byte into Register D ...
638F
LD E,L 5D
... and the low byte into Register E.
6390
DEC B 05
Register B = base - 1, the number of additions.
6391
ADD HL,DE 19
Multiply
Add the original value.
6392
Decrement Register B and LOOP BACK to 6391H: HL = value x base.
6394
LD E,A 5F
Register E = the digit.
6395
LD D,00H 16 00
Register D = 00H.
6397
ADD HL,DE 19
Add the digit.
6398
POP DE D1
Restore Register DE.
6399
POP BC C1
Restore Register BC.
639A
DEC C 0D
Count one character.
639B
More characters: LOOP BACK to 637DH.
639D
JUMP to 6308H to apply the term.
63A0
Character Constant
GOSUB to 61D6H to classify the word after the apostrophe.
63A3
The line has ended: JUMP to 62E2H for the error.
63A6
DEC C 0D
Count one character ...
63A7
... more than one: JUMP to 62E2H for the error.
63AA
LD A,(DE) 1A
Load Register A with the character.
63AB
LD L,A 6F
Register L = the character.
63AC
LD H,00H 26 00
Register H = 00H: HL = the character's value.
63AE
GOSUB to 61B5H to classify the next word (the closing apostrophe).
63B1
LD A,(DE) 1A
Load Register A with its first character.
63B2
CP 27H FE 27
Compare with 27H (apostrophe).
63B4
Not closed: JUMP to 62E2H for the error.
63B7
JUMP to 6308H to apply the term.
63BAH - Expression Operators
Each is reached from 6321H-632DH with HL = the new term; each returns to 63D4H. 63BAH subtracts, 63C0H adds and 63C9H ANDs, working on the result at 53C1H. 63D4H reads the character after a term: the end of the line finishes the expression; otherwise it becomes the pending operator after the delimiter check at 62E8H.
63BA
XOR A AF
Subtract
Negate the term: set Register A to 00H.
63BB
SUB L 95
Subtract the low byte.
63BC
LD L,A 6F
Register L = the negated low byte.
63BD
SBC A,H 9C
Subtract the high byte with the borrow (A = -L - H - borrow).
63BE
SUB L 95
Subtract Register L, which holds -L (A = -H - borrow).
63BF
LD H,A 67
Register H = the negated high byte; the add below completes the subtraction.
63C0
EX DE,HL EB
Add
Move the term into DE.
63C1
LD HL,(53C1H) 2A C1 53
Load Register HL with the result from 53C1H.
63C4
ADD HL,DE 19
Add the term.
63C5
LD (53C1H),HL 22 C1 53
Store the new result.
63C9
LD DE,53C1H 11 C1 53
AND
Point DE to the result at 53C1H.
63CC
LD A,(DE) 1A
Load Register A with its low byte.
63CD
AND L A5
AND it with the term's low byte.
63CE
LD (DE),A 12
Store it back.
63CF
INC DE 13
Point DE at the high byte.
63D0
LD A,(DE) 1A
Load Register A with it.
63D1
AND H A4
AND it with the term's high byte.
63D2
LD (DE),A 12
Store it back.
63D4
After a Term
GOSUB to 5BBEH for the next character.
63D7
POP BC C1
Restore the pending operator and minus flag.
63D8
LD B,A 47
The character becomes the pending operator (Register B).
63D9
The line has ended: JUMP to 62B1H to return the result.
63DC
PUSH BC C5
Push the operator and minus flag.
63DD
GOSUB to 62E8H: a delimiter ends the expression; otherwise it returns.
63E0
JUMP to 62AAH for the next term.
63E3H - A Command: Assemble
A name /switch/switch.... Empties the symbol table (bottom = top = 5313H, with a 00H end byte), clears the pass number and the five switch flags, reads the object file name (default NONAME) and then each / switch (NL, NO, LP, NS, WE; table at 5873H). When the command line has been used up, the appendage (6F22H) asks where the object code goes and starts pass 1 at 6427H. An unknown switch gives BAD PARAMETER(S).
63E3
LD HL,(5313H) 2A 13 53
Load Register HL with the symbol table top from 5313H.
63E6
LD (53C3H),HL 22 C3 53
Store it into 53C3H, the symbol table bottom: the table is empty.
63E9
XOR A AF
Set Register A to 00H.
63EA
LD (HL),A 77
Store 00H at the top: the end marker of the table (a length of 0).
63EB
LD (53C0H),A 32 C0 53
Clear the pass number (53C0H).
63EE
LD (587AH),A 32 7A 58
Clear the NO switch flag (587AH).
63F1
LD (5876H),A 32 76 58
Clear the NL switch flag (5876H).
63F4
LD (587EH),A 32 7E 58
Clear the LP switch flag (587EH).
63F7
LD (5882H),A 32 82 58
Clear the NS switch flag (5882H).
63FA
LD (5886H),A 32 86 58
Clear the WE switch flag (5886H).
63FD
GOSUB to 6107H to read the object file name. HL returns pointing to 53ADH, the name length.
6400
INC (HL) 34
Increment the name length ...
6401
DEC (HL) 35
... and decrement it: the Z FLAG is set if no name was typed.
6402
A name was typed: JUMP to 640CH.
6404
LD (HL),06H 36 06
Set the name length to 06H ...
6406
LD HL,5AFFH 21 FF 5A
... and point HL to NONAME at 5AFFH ...
6409
LD (53ABH),HL 22 AB 53
... as the file name (53ABH).
640C
Switch Loop
GOSUB to 5BBBH to get the next non-space character.
640F
NOP 00
Patch Space
NOP (unused byte).
6410
GOSUB to 6F22H in the appendage: if the command line has ended it starts the assembly (after asking where the object code goes); otherwise it returns Z for /.
6413
Not a /: JUMP to 5D24H for BAD PARAMETER(S).
6416
GOSUB to 61A8H to read the switch name (Register C = its length, DE = its address).
6419
LD HL,5873H 21 73 58
Point HL to the switch table at 5873H.
641C
LD B,01H 06 01
Load Register B with 01H: one flag byte per entry.
641E
GOSUB to 627CH to look the switch up. HL returns at its flag byte.
6421
Unknown switch: JUMP to 5D24H for BAD PARAMETER(S).
6424
INC (HL) 34
Set the switch by incrementing its flag byte.
6425
LOOP BACK to 640CH for the next switch.
6427H - Start the Next Assembler Pass, or Finish After Pass 2
Reached when a pass ends: from the appendage at 6F31H when the A command line has been parsed, from the END handler at 6B8BH, and from 6B86H when the text ends without END. It resets the source line pointer and the per-line variables and increments the pass number at 53C0H. Passes 1 and 2 continue at 6496H. When the pass number reaches 03H, the error total and free memory are displayed, the symbol table (with cross-references) is listed unless the NS switch was given, and pass 3 (object code) starts through 6486H.
6427
LD HL,7700H 21 00 77
Load Register HL with 7700H, the start of the text buffer.
642A
LD (531DH),HL 22 1D 53
Store 7700H into 531DH: the next source line to assemble is the first line of the text.
642D
LD HL,(53B8H) 2A B8 53
Load Register HL with the error count from 53B8H (it is cleared by the loop below).
6430
EX DE,HL EB
Move the error count into Register DE.
6431
LD B,0CH 06 0C
Load Register B with 0CH (12), the number of bytes to clear.
6433
XOR A AF
Set Register A to 00H.
6434
LD HL,53B4H 21 B4 53
Point HL to 53B4H, the first per-line assembler variable.
6437
LD (HL),A 77
Clear Loop
Store 00H at HL.
6439
Decrement Register B and LOOP BACK to 6437H until 53B4H-53BFH (line length, location counter, error count, output flags and error-on-line flag) are all 00H. HL is left at 53C0H.
643B
INC (HL) 34
Increment the pass number at 53C0H.
643C
LD A,(HL) 7E
Load Register A with the new pass number.
643D
CP 03H FE 03
Compare it against 03H.
643F
If this is pass 1 or 2, JUMP to 6496H to assemble the text.
6441
EX DE,HL EB
Pass 2 has finished: move the error count from Register DE into HL.
6442
LD DE,5D75H 11 75 5D
Load Register DE with 5D75H, the routine that displays HL as a 5-digit decimal number.
6445
GOSUB to 6182H, which calls 5D75H to display the error count, and calls it a second time with printer output on when the LP switch is set (587EH).
6448
LD HL,5A88H 21 88 5A
Point HL to the message TOTAL ERRORS at 5A88H.
644B
GOSUB to 617FH to display the message (and print it when LP is set).
644E
GOSUB to 708FH in the appendage. It displays the number of free bytes followed by TEXT AREA BYTES LEFT and returns Register A = the NS switch flag from 5882H.
6451
OR A B7
Test the NS flag in Register A.
6452
If NS was given (A non-zero), JUMP to 6486H and skip the symbol table listing.
6454
LD A,(587EH) 3A 7E 58
Load Register A with the LP switch flag from 587EH.
6457
LD (53BCH),A 32 BC 53
Store it into 53BCH, the printer flag, so the symbol table goes to the printer when LP is set.
645A
LD HL,(53C3H) 2A C3 53
Load Register HL with the contents of 53C3H, the bottom (lowest address) of the symbol table.
645D
GOSUB to 5937H to output a carriage return.
6460
JUMP to 5200H, the sorted symbol table and cross-reference lister. It returns to the assembler through 6486H (52B2H).
6463H - Unreferenced Code: Old Symbol Table Listing
Nothing in EDTASM/CMD jumps or calls into 6463H-6485H. The block is a loop that lists the symbol table in stored order, one symbol per line with its name, a tab and its value in hexadecimal; it would have been reached from the CALL 5937H at 645DH, where the JP 5200H at 6460H now sends the assembler to the sorted lister and cross-reference instead. The byte 53H at 6463H is left over from the instruction that the JP 5200H replaced.
6463
LD D,E 53
Unused byte (53H), which decodes as LD D,E.
6464
Unused Loop
GOSUB to 5856H to check for BREAK or a pause.
6467
LD A,(HL) 7E
Load Register A with the flag byte of the symbol entry at HL ...
6468
AND 1FH E6 1F
... and keep bits 0-4, the name length.
646A
A length of 00H is the end of the table: JUMP to 6486H to start pass 3.
646C
LD B,A 47
Load Register B with the name length as the character count.
646D
INC HL 23
Point HL to the next character of the name.
646E
LD A,(HL) 7E
Load Register A with the character ...
646F
... and GOSUB to 5939H to output it.
6472
Decrement the count in Register B and LOOP BACK to 646DH until the whole name is shown.
6474
LD A,09H 3E 09
Load Register A with 09H, a tab ...
6476
... and GOSUB to 5939H to output it.
6479
INC HL 23
Skip over the low byte of the value ...
647A
INC HL 23
... to the high byte.
647B
GOSUB to 6E4EH to show the high byte as two hexadecimal digits.
647E
DEC HL 2B
Move back to the low byte ...
647F
... and GOSUB to 6E4EH to show it.
6482
INC HL 23
Skip over the high byte ...
6483
INC HL 23
... to the flag byte of the next entry.
6484
JUMP to 645DH to end the output line and continue.
6486H - Start Pass 3 (Object Code)
Reached from the sorted symbol lister at 52B2H, and from 6452H when the NS switch skips the listing. Turns the printer flag off. If the NO switch was given there is no object code, so the assembly ends at 58D7H; otherwise the object file header (55H and the name) is written and the pass continues with the first source line at 6496H.
6486
XOR A AF
Set Register A to 00H ...
6487
LD (53BCH),A 32 BC 53
... and store it into 53BCH, turning the printer off.
648A
LD A,(587AH) 3A 7A 58
Load Register A with the NO (no object) switch flag from 587AH.
648E
NO is set: JUMP to 58D7H to end the assembly and return to the command loop.
6491
LD C,55H 0E 55
Load Register C with 55H, the header byte of a SYSTEM-format object file ...
6493
... and GOSUB to 6121H to write the header and file name.
6496H - Assemble the Next Source Line
The top of the assembler's per-line loop, used by all three passes. Every line handler returns here: 6496H is pushed below the handler's return address, and the error routine at 614BH pushes it too. It resets the stack, checks the keyboard, pauses after an error line if the WE switch is set, and moves the location counter past the bytes of the previous line.
WE Pause
53BFH is set to 01H by the error routine. When it counts down to 00H here and the WE switch is set, the assembler waits for a key. C clears the WE switch (SUB 43H gives 00H), so the assembly then continues without stopping at errors; any other key leaves it set.
6496
LD SP,54FEH 31 FE 54
Set the stack pointer to 54FEH.
6499
GOSUB to 5856H to check for BREAK or a pause.
649C
LD HL,53BFH 21 BF 53
Point HL to 53BFH, the error-on-this-line flag.
649F
DEC (HL) 35
Count it down.
64A0
It was not 01H (no error on the last line): JUMP to 64B0H.
64A2
LD A,(5886H) 3A 86 58
Load Register A with the WE (wait on errors) switch flag from 5886H ...
64A5
OR A B7
... and test it.
64A6
WE is not set: JUMP to 64B0H.
64A8
GOSUB to 5866H to wait for a key.
64AB
SUB 43H D6 43
Subtract 43H (C): the result is 00H only for C ...
64AD
LD (5886H),A 32 86 58
... and store it as the new WE switch flag, so C turns WE off.
64B0
LD (HL),00H 36 00
Clear the error-on-this-line flag.
64B2
LD HL,6496H 21 96 64
Load Register HL with 6496H ...
64B5
PUSH HL E5
... and push it as the return address, so the line handler comes back here.
64B6
XOR A AF
Set Register A to 00H.
64B7
LD (53AAH),A 32 AA 53
Clear 53AAH, the count of input characters left.
64BA
LD HL,(53B4H) 2A B4 53
Load Register HL with the length of the previous line's code from 53B4H-53B5H ...
64BD
EX DE,HL EB
... into Register DE.
64BE
LD HL,(53B6H) 2A B6 53
Load Register HL with the location counter from 53B6H ...
64C1
ADD HL,DE 19
... add the length ...
64C2
LD (53B6H),HL 22 B6 53
... and store the new location counter.
64C5
LD (53AEH),HL 22 AE 53
Store it into 53AEH too, the address shown on the listing line.
64C8
LD H,A 67
Set Register H to 00H ...
64C9
LD L,A 6F
... and Register L to 00H ...
64CA
LD (53B4H),HL 22 B4 53
... and clear the length at 53B4H-53B5H.
64CD
LD (53B0H),A 32 B0 53
Clear the prefix byte at 53B0H.
64D0H - Get the Next Source Line and Look at Its First Word
Takes the text line at 531DH as the current line (5311H), sets the input scan pointer (53A8H) and count (53AAH) to its text, and advances 531DH to the line after it. When the end-of-text marker is reached, the pass ends at 6B80H. The first word decides the kind of line:
Empty Line or ;
Listed only (6DF1H).
Identifier
A label (6539H).
Space or Tab
No label: the opcode follows (654CH).
*
A listing directive (6508H).
Anything Else
BAD LABEL (6533H).
64D0
LD HL,(5315H) 2A 15 53
Load Register HL with the end-of-text pointer from 5315H ...
64D3
EX DE,HL EB
... into Register DE.
64D4
LD HL,(531DH) 2A 1D 53
Load Register HL with the next source line from 531DH.
64D7
GOSUB to 5DC2H to compare it with the end of the text.
64DA
The text has ended: JUMP to 6B80H (no END statement).
64DD
LD (5311H),HL 22 11 53
Store the line's address into 5311H, the current line.
64E0
INC HL 23
Skip the line number ...
64E1
INC HL 23
... two bytes.
64E2
LD A,(HL) 7E
Load Register A with the length of the text ...
64E3
LD (53AAH),A 32 AA 53
... and store it into 53AAH, the count of input characters.
64E6
INC HL 23
Point HL to the text ...
64E7
LD (53A8H),HL 22 A8 53
... and store it into 53A8H, the input scan pointer.
64EA
LD D,00H 16 00
Register D = 00H ...
64EC
LD E,A 5F
... and Register E = the length.
64ED
ADD HL,DE 19
Add the length: HL = the next line.
64EE
LD (531DH),HL 22 1D 53
Store it into 531DH for the next time round.
64F1
GOSUB to 61D6H to classify the first word without skipping spaces: Register DE = its address, Register C = its length, Register A = its type, and the Z FLAG is set for an empty line.
64F4
PUSH DE D5
Save the word's address (it becomes the label address).
64F5
Empty line: JUMP to 652FH to list it.
64F7
OR A B7
Test the type ...
64F8
... for 00H, an identifier: JUMP to 6539H for a label.
64FA
LD A,(DE) 1A
Load Register A with the first character of the word.
64FB
DEC C 0D
Take one from the length: for a single character Register C is now 00H, meaning there is no label.
64FC
CP 20H FE 20
Compare with 20H (space).
64FE
A space: no label, JUMP to 654CH for the opcode.
6500
CP 09H FE 09
Compare with 09H (tab).
6502
A tab: no label, JUMP to 654CH.
6504
CP 2AH FE 2A
Compare with 2AH (*).
6506
Not *: JUMP to 652DH.
6508H - *L ON / OFF: Listing Directive
A line starting with *, a word starting with L (only the first letter is checked, so *LIST works) and ON or OFF. The line itself is listed, and then 53BDH is set to 00H (ON) or 01H (OFF): a non-zero value stops 6E03H from listing later lines. For ON the flag is cleared before the line is listed, so both directive lines appear in the listing.
6508
POP HL E1
Discard the saved word address.
6509
GOSUB to 61B5H to classify the word after the * (Register A = 2AH, a type that never matches, so only the MISSING INFORMATION check matters).
650C
LD A,(DE) 1A
Load Register A with its first character.
650D
CP 4CH FE 4C
Compare it with 4CH (L).
650F
Not L: JUMP to 6569H for ILLEGAL OPCODE.
6511
GOSUB to 61A8H to classify the next word, skipping spaces. Register B = 00H for ON and 01H for OFF.
6514
Nothing follows: JUMP to 61D0H for MISSING INFORMATION.
6517
CP 09H FE 09
Compare the type with 09H (ON or OFF).
6519
Anything else: JUMP to 66E2H for ILLEGAL ADDRESSING MODE.
651C
LD HL,53BDH 21 BD 53
Point HL to 53BDH, the listing off flag ...
651F
PUSH HL E5
... and save it.
6520
PUSH BC C5
Save Register B (00H or 01H).
6521
INC B 04
Increment Register B ...
6522
DEC B 05
... and decrement it: the Z FLAG is set for ON.
6525
LD (HL),B 70
ON: clear the listing off flag now, so this line is listed.
6526
GOSUB to 6DF1H to list the line (no address and no code bytes).
6529
POP BC C1
Restore Register B ...
652A
POP HL E1
... and the flag address.
652B
LD (HL),B 70
Set the listing off flag: 00H for ON, 01H for OFF.
652C
RET C9
RETURN to 6496H for the next line.
652DH - Comment Line, or Bad Label
Continues 64D0H for a first character that is not a space, tab, * or letter. A ; starts a comment line, which is only listed. Anything else gives BAD LABEL.
652FH
Also reached with the Z FLAG set from 64F5H (empty line) and 6557H/655BH (a line with no label and no opcode).
6533H
Also reached from 653CH and 654AH (a bad label), and from the ORG and END handlers at 6B72H and 6B91H (a label is not allowed there).
652D
CP 3BH FE 3B
Compare the character with 3BH (;).
652F
POP DE D1
Discard the saved word address.
6530
A comment or empty line: JUMP to 6DF1H to list it (no address and no code bytes). Its RET goes to 6496H.
6533
LD DE,59D7H 11 D7 59
Point DE to BAD LABEL at 59D7H ...
6536
... and JUMP to 614BH to report it and go on to the next line.
6539H - Check the Label
The first word is an identifier in column 1, so it is a label. Its length (Register C) must be 6 characters or fewer, and it must be followed by a space (or tab) or a colon. A label with nothing after it gives MISSING INFORMATION.
6539
LD A,C 79
Load Register A with the label length.
653A
CP 07H FE 07
Compare it with 07H.
653C
Seven characters or more: JUMP to 6533H for BAD LABEL.
653E
GOSUB to 5BBEH to get the character right after the label (a tab is returned as a space).
6541
The line ends after the label: JUMP to 61D0H for MISSING INFORMATION.
6544
CP 20H FE 20
Compare with 20H (space).
6546
A space: JUMP to 654CH.
6548
CP 3AH FE 3A
Compare with 3AH (:).
654A
Anything else: JUMP to 6533H for BAD LABEL.
654CH - Look Up the Opcode
Reads the opcode word (skipping spaces) and finds it in the mnemonic table at 6BD9H. Register C holds the label length (00H if there is no label). On a line with no label, a ; or the end of the line in place of the opcode means the line is only listed. An unknown word, or a mnemonic followed by anything other than a space, ; or the end of the line, gives ILLEGAL OPCODE.
654C
LD L,C 69
Copy the label length into Register L.
654D
GOSUB to 61A8H to classify the opcode word, skipping spaces. Register DE = its address, Register C = its length.
6550
INC L 2C
Increment Register L ...
6551
DEC L 2D
... and decrement it to test the label length.
6552
There is a label: JUMP to 655DH.
6554
LD A,(DE) 1A
Load Register A with the first character of the word.
6555
CP 3BH FE 3B
Compare with 3BH (;).
6557
A comment only: JUMP to 652FH to list the line.
6559
CP 0DH FE 0D
Compare with 0DH (end of line).
655B
Nothing on the line: JUMP to 652FH to list it.
655D
PUSH HL E5
Save the label length (Register L).
655E
LD HL,6BD9H 21 D9 6B
Point HL to the mnemonic table at 6BD9H.
6561
LD B,02H 06 02
Load Register B with 02H: two data bytes (type and base opcode) per entry.
6563
GOSUB to 627CH to look the word up. HL returns at the entry's type byte.
6566
POP BC C1
Restore the label length into Register C.
6567
Found: JUMP to 656FH.
6569
LD DE,5A0AH 11 0A 5A
Illegal Opcode
Point DE to ILLEGAL OPCODE at 5A0AH ...
656C
... and JUMP to 614BH to report it and go on to the next line.
656F
GOSUB to 5BBEH to get the character right after the mnemonic.
6572
The line ends: JUMP to 657CH.
6574
CP 3BH FE 3B
Compare with 3BH (;).
6576
A comment: JUMP to 657CH.
6578
CP 20H FE 20
Compare with 20H (space).
657A
Anything else (for example LDX): JUMP to 6569H for ILLEGAL OPCODE.
657CH - Call the Opcode Handler
Positions the input at the first operand, stores the base opcode into 53B1H and fetches the handler for the mnemonic's type from the dispatch table at 6DA7H. The stack is arranged as handler, 6DDFH (end-of-line check and listing), 6496H (next line), so the handler's RET goes to the listing routine and the listing's RET to the next line.
Label Handling
With no label the handler is entered at once (Register A = the type). For types 18H and above (ORG, END, EQU, DEFL) the handler is entered with Register A = 01H, Register HL = the location counter and Register DE/C = the label, and deals with the label itself. For every other type the label is defined first as the location counter by falling into 65A6H with Register A = 01H; the RET at the end of 65A6H then enters the handler.
657C
GOSUB to 5BBBH to skip spaces.
657F
If the line has not ended, GOSUB to 5BF4H to put back the first character of the operand.
6582
LD E,(HL) 5E
Load Register E with the type from the mnemonic's entry.
6583
INC HL 23
Point HL to the base opcode ...
6584
LD A,(HL) 7E
... load it into Register A ...
6585
LD (53B1H),A 32 B1 53
... and store it into 53B1H, the first instruction byte.
6588
LD HL,6DA7H 21 A7 6D
Point HL to the dispatch table at 6DA7H.
658B
LD D,00H 16 00
Register D = 00H, so DE = the type.
658D
ADD HL,DE 19
Add the type ...
658E
ADD HL,DE 19
... twice: two bytes per entry.
658F
LD A,(HL) 7E
Load Register A with the low byte of the handler address ...
6590
INC HL 23
... move to the high byte ...
6591
LD H,(HL) 66
... load it into Register H ...
6592
LD L,A 6F
... and the low byte into Register L. HL = the handler.
6593
LD A,E 7B
Load Register A with the type.
6594
LD DE,6DDFH 11 DF 6D
Load Register DE with 6DDFH, the end-of-line check and listing routine.
6597
EX DE,HL EB
Exchange: HL = 6DDFH, DE = the handler.
6598
EX (SP),HL E3
Exchange with the stack: 6DDFH goes on the stack and HL = the word address saved at 64F4H (the label).
6599
EX DE,HL EB
Exchange: HL = the handler, DE = the label address.
659A
PUSH HL E5
Push the handler address as the return address.
659B
INC C 0C
Increment Register C (the label length) ...
659C
DEC C 0D
... and decrement it.
659D
RET Z C8
No label: RETURN into the handler.
659E
CP 18H FE 18
Compare the type with 18H.
65A0
LD A,01H 3E 01
Load Register A with 01H (define) without changing the flags.
65A2
LD HL,(53B6H) 2A B6 53
Load Register HL with the location counter from 53B6H.
65A5
RET NC D0
Types 18H and above: RETURN into the handler, which handles the label.
65A6H - Look Up or Define a Symbol
Register DE = the symbol name, Register C = its length, Register HL = the value (when defining), Register A = the mode: 00H looks the symbol up (from the expression evaluator at 6305H), 01H defines it (labels, from 657CH, and EQU), 02H defines it as a DEFL symbol (6BC6H). A symbol that is not in the table is added first, below the current bottom (53C3H), with a flag byte holding only the length and a value of 0000H.
Lookup (Mode 0)
Returns Register HL = the value and Register DE = the HL passed in. A symbol that has never been defined gives UNDEFINED SYMBOL, and one that was defined twice gives MULTIPLY DEFINED SYMBOL; both are reported through 6150H, so the line is still assembled.
Define (Modes 1 and 2)
Sets bit 7 of the flag byte (and bit 5 for DEFL) and stores the value. If the symbol is already defined with a different value, it is only changed when it was defined by DEFL and this is DEFL again; otherwise bit 6 is set and MULTIPLE DEFINITION is reported. The same value again (every label in pass 2) is not an error.
Symbol Table Overflow
If a new entry would reach the end of the text (5315H), SYMBOL TABLE OVERFLOW is shown through 592BH and the assembly is abandoned.
65A6
PUSH HL E5
Save the value.
65A7
PUSH AF F5
Save the mode.
65A8
LD HL,(53C3H) 2A C3 53
Load Register HL with the symbol table bottom from 53C3H.
65AB
LD B,02H 06 02
Load Register B with 02H: two value bytes per entry.
65AD
GOSUB to 627CH to search the table for the name. On a match HL returns at the value's low byte.
65B0
Found: JUMP to 65E0H.
65B2
PUSH DE D5
Add a New Entry
Save the name address.
65B3
PUSH BC C5
Save the length (Register C) and 02H (Register B).
65B4
LD HL,(5315H) 2A 15 53
Load Register HL with the end-of-text pointer from 5315H ...
65B7
EX DE,HL EB
... into Register DE.
65B8
LD HL,(53C3H) 2A C3 53
Load Register HL with the symbol table bottom from 53C3H.
65BB
LD A,C 79
Load Register A with the name length ...
65BC
ADD A,B 80
... plus 2 ...
65BD
CPL 2F
... and complement it: A = -(length + 3), the size of the new entry as a negative number.
65BE
LD C,A 4F
Store it into Register C ...
65BF
LD B,FFH 06 FF
... with Register B = FFH, so BC = -(length + 3).
65C1
ADD HL,BC 09
Add it: HL = the new bottom of the table.
65C2
GOSUB to 5DC2H to compare the new bottom with the end of the text.
65C5
It is still above the text: JUMP to 65CDH.
65C7
LD HL,5A73H 21 73 5A
Point HL to SYMBOL TABLE OVERFLOW at 5A73H ...
65CA
... and JUMP to 592BH to display it and return to the command loop.
65CD
LD (53C3H),HL 22 C3 53
Store the new bottom into 53C3H.
65D0
POP BC C1
Restore the length into Register C.
65D1
POP DE D1
Restore the name address into Register DE.
65D2
PUSH BC C5
Save the length again.
65D3
LD (HL),C 71
Store the length as the flag byte: not defined yet.
65D4
EX DE,HL EB
Exchange: HL = the name, DE = the flag byte.
65D5
INC DE 13
Point DE to where the name goes.
65D6
LD B,00H 06 00
Register B = 00H, so BC = the length.
65D8
LDIR ED B0
Copy the name into the entry.
65DA
EX DE,HL EB
Exchange: HL = the byte after the name, the value.
65DB
LD (HL),B 70
Set the value's low byte to 00H ...
65DC
INC HL 23
... move to the high byte ...
65DD
LD (HL),B 70
... and set it to 00H.
65DE
DEC HL 2B
Move back to the low byte.
65DF
POP BC C1
Restore the length into Register C.
65E0
POP DE D1
Entry Found or Added
Restore the mode into Register D.
65E1
PUSH HL E5
Save the address of the value.
65E2
LD A,C 79
Load Register A with the name length ...
65E3
CPL 2F
... and complement it: -(length + 1) ...
65E4
LD C,A 4F
... in Register C ...
65E5
LD B,FFH 06 FF
... with Register B = FFH.
65E7
ADD HL,BC 09
Add it: HL = the entry's flag byte.
65E8
INC D 14
Increment Register D (the mode) ...
65E9
DEC D 15
... and decrement it.
65EA
Mode 1 or 2: JUMP to 6605H to define the symbol.
65EC
LD A,(HL) 7E
Lookup
Load Register A with the flag byte ...
65ED
AND 80H E6 80
... and keep bit 7, the defined flag.
65EF
LD DE,5A94H 11 94 5A
Point DE to UNDEFINED SYMBOL at 5A94H.
65F2
If it has never been defined, GOSUB to 6150H to report the error and continue.
65F5
LD A,(HL) 7E
Load Register A with the flag byte again ...
65F6
AND 40H E6 40
... and keep bit 6, the multiply defined flag.
65F8
LD DE,5A5CH 11 5C 5A
Point DE to MULTIPLY DEFINED SYMBOL at 5A5CH.
65FB
If it was defined more than once, GOSUB to 6150H to report the error and continue.
65FE
POP HL E1
Restore the address of the value.
65FF
LD A,(HL) 7E
Load Register A with its low byte ...
6600
INC HL 23
... move to the high byte ...
6601
LD H,(HL) 66
... load it into Register H ...
6602
LD L,A 6F
... and the low byte into Register L. HL = the symbol's value.
6603
POP DE D1
Restore the HL that was passed in into Register DE.
6605
LD A,(HL) 7E
Define
Load Register A with the flag byte ...
6606
OR A B7
... and test bit 7.
6607
Not defined yet: JUMP to 662FH.
660A
LD A,D 7A
Already defined: load Register A with the mode.
660B
EX (SP),HL E3
Exchange with the stack: HL = the address of the value, and the flag byte address goes on the stack ...
660C
POP BC C1
... and is taken off into Register BC.
660D
POP DE D1
Restore the new value into Register DE ...
660E
PUSH DE D5
... and save it again.
660F
PUSH HL E5
Save the address of the value.
6610
PUSH AF F5
Save the mode.
6611
LD A,(HL) 7E
Load Register A with the old value's low byte ...
6612
INC HL 23
... move to the high byte ...
6613
LD H,(HL) 66
... load it into Register H ...
6614
LD L,A 6F
... and the low byte into Register L.
6615
GOSUB to 5DC2H to compare the old value with the new one.
6618
POP DE D1
Restore the mode into Register D.
6619
The same value: JUMP to 6637H (no error).
661B
LD A,(BC) 0A
Load Register A with the flag byte ...
661C
AND 20H E6 20
... and keep bit 5, the DEFL flag.
661E
Not a DEFL symbol: JUMP to 6623H for the error.
6620
DEC D 15
Decrement the mode: it is 00H for mode 1 (EQU or a label).
6621
Mode 2 (DEFL again): JUMP to 6637H to store the new value.
6623
LD A,(BC) 0A
Multiple Definition
Load Register A with the flag byte ...
6624
OR 40H F6 40
... set bit 6, the multiply defined flag ...
6626
LD (BC),A 02
... and store it.
6627
POP HL E1
Discard the address of the value ...
6628
POP HL E1
... and the new value.
6629
LD DE,5A3BH 11 3B 5A
Point DE to MULTIPLE DEFINITION at 5A3BH ...
662C
... and JUMP to 6150H to report it. Its RET goes to this routine's caller, so the line is still assembled.
662F
OR 80H F6 80
First Definition
Set bit 7 of the flag byte, the defined flag.
6631
DEC D 15
Decrement the mode: it is 00H for mode 1.
6632
Mode 1: JUMP to 6636H.
6634
OR 20H F6 20
Mode 2 (DEFL): set bit 5 too.
6636
LD (HL),A 77
Store the flag byte.
6637
POP HL E1
Store the Value
Restore the address of the value.
6638
POP DE D1
Restore the new value into Register DE.
6639
LD (HL),E 73
Store its low byte ...
663A
INC HL 23
... move to the high byte ...
663B
LD (HL),D 72
... and store its high byte.
663DH - ADD, ADC and SBC: Check for the A, Prefix
Called by the ADC/SBC handler (6714H) and the ADD handler (6735H). Classifies the first operand (61B5H) and requires a comma after it, else ILLEGAL ADDRESSING MODE. If the first operand is not an 8-bit register, it returns with Register A = its type and Register B = its number, for the 16-bit forms. If it is a register it must be A: the return address is discarded and execution falls into 6654H, so ADD A,s, ADC A,s and SBC A,s are encoded like the single-operand arithmetic group (base 80H, 88H, 98H).
663D
GOSUB to 61B5H to classify the first operand. Register A = its type, Register B = its number.
6640
PUSH AF F5
Save the type and flags.
6641
GOSUB to 5BBEH to get the character after the operand.
6644
CP 2CH FE 2C
Compare it with 2CH (comma).
6646
No comma: JUMP to 66E2H for ILLEGAL ADDRESSING MODE.
6649
POP AF F1
Restore the type.
664A
CP 03H FE 03
Compare it with 03H (8-bit register).
664C
RET NZ C0
Not a register: RETURN to the ADD or ADC/SBC handler for the 16-bit forms.
664D
LD A,B 78
Load Register A with the register number ...
664E
CP 07H FE 07
... and compare it with 07H (register A).
6650
Another register: JUMP to 66E2H for ILLEGAL ADDRESSING MODE.
6653
POP HL E1
Discard the return address, so the second operand is handled by 6654H and its RET ends the handler.
6654
Arithmetic and Logic Group
Type 01H (AND, CP, OR, SUB, XOR), also reached from 6653H and from LD at 6998H. GOSUB to 61B5H to classify the operand.
6657
CP 03H FE 03
Compare the type with 03H (8-bit register). Also reached from 69A2H with the type in Register A.
6659
A register: JUMP to 66A4H to OR it into the opcode.
665B
GOSUB to 6804H to test for (.
665E
(: JUMP to 66A4H for (HL), (IX+d) or (IY+d).
6660H - Immediate Operand and Field Overflow Check
The operand is a value. XOR 46H turns the register form of the opcode at 53B1H into its immediate form: A0H (AND r) becomes E6H (AND n), 80H (ADD A,r) C6H, 88H CEH, 90H D6H, 98H DEH, A8H EEH, B0H F6H, B8H FEH, and 40H+r<<3 (LD r,r') becomes 06H+r<<3 (LD r,n). The value goes into 53B2H and the length becomes 2.
6669H
Also entered from 6A1CH (LD (HL),n and LD (IX+d),n) with Register HL = the byte before the one to fill.
6671H
Reports FIELD OVERFLOW through 6150H (the line is still assembled) when Register D is not 00H. Register DE is preserved. Called from 6690H, 68C8H, 68FAH and 6B5CH; 56F5H jumps to 6672H with Register A already set.
6660
PUSH AF F5
Save the type.
6661
LD HL,53B1H 21 B1 53
Point HL to 53B1H, the opcode.
6664
LD A,(HL) 7E
Load Register A with the opcode ...
6665
XOR 46H EE 46
... XOR it with 46H to make the immediate form ...
6667
LD (HL),A 77
... and store it.
6668
POP AF F1
Restore the type into Register A.
6669
GOSUB to 6293H to evaluate the operand, which has already been classified. Register DE = the value.
666C
INC HL 23
Move to the next instruction byte ...
666D
LD (HL),E 73
... and store the low byte of the value there.
666E
GOSUB to 670BH to add 2 to the length.
6671
LD A,D 7A
Load Register A with the high byte of the value.
6672
OR A B7
Test it for 00H.
6673
PUSH DE D5
Save the value.
6674
LD DE,5A4EH 11 4E 5A
Point DE to FIELD OVERFLOW at 5A4EH.
6677
If the high byte is not 00H, GOSUB to 6150H to report the error and continue.
667A
POP DE D1
Restore the value.
667CH - BIT, SET and RES; 6696H - CB-Prefixed Group
667CH
Type 03H (BIT 40H, RES 80H, SET C0H). Evaluates the bit number; 8 or more forces Register D = 01H so that 6671H reports FIELD OVERFLOW. The bit number goes into bits 3-5 of the base opcode, a comma is required, and execution continues at 6696H.
6696H
Type 02H (RL 10H, RLC 00H, RR 18H, RRC 08H, SLA 20H, SRA 28H, SRL 38H). Moves the opcode to 53B2H, stores CBH at 53B1H, sets the length to 1, classifies the operand and falls into 66A4H, which ORs the register into the second byte.
667C
GOSUB to 62A0H to evaluate the bit number into Register DE.
667F
LD A,E 7B
Load Register A with its low byte.
6680
CP 08H FE 08
Compare it with 08H.
6684
LD D,01H 16 01
8 or more: set Register D to 01H so that 6671H reports FIELD OVERFLOW.
6686
RLCA 07
Rotate the bit number left ...
6689
AND 38H E6 38
... and keep bits 3-5.
668B
LD HL,53B1H 21 B1 53
Point HL to the opcode at 53B1H.
668E
OR (HL) B6
OR the bit number into the opcode ...
668F
LD (HL),A 77
... and store it.
6690
GOSUB to 6671H to report FIELD OVERFLOW if Register D is not 00H.
6693
GOSUB to 67F8H to require a comma.
6696
LD HL,53B1H 21 B1 53
CB Group
Point HL to 53B1H.
6699
LD A,(HL) 7E
Load Register A with the opcode.
669A
LD (HL),CBH 36 CB
Store CBH as the first byte.
669C
INC HL 23
Move to 53B2H ...
669D
LD (HL),A 77
... and store the opcode there.
669E
INC HL 23
Move to 53B3H ...
669F
INC HL 23
... and to 53B4H, the length.
66A0
INC (HL) 34
Set the length to 1 (it was 00H).
66A1
GOSUB to 61B5H to classify the operand, then fall into 66A4H.
66A4H - Encode an 8-Bit Register, (HL) or (IX+d) Operand
Register A = the operand type from 61B5H, Register B = the register number, Register DE = the word. Adds one to the length at 53B4H and ORs the register number into the last instruction byte so far (53B0H + length). (HL), (IX+d) and (IY+d) use register number 6.
Entries
66A4H clears the CARRY FLAG, so the register goes into bits 0-2. 66A5H is entered from the INC/DEC handler (678AH) with the CARRY FLAG set, so the register goes into bits 3-5.
Memory Operands
Any type other than 03H must start with ( and be followed by HL (66DCH then requires )) or by IX or IY (66E8H). Anything else goes to 66E2H.
66A4
OR A B7
Clear the CARRY FLAG: the register goes into bits 0-2.
66A5
PUSH AF F5
Save the type and the CARRY FLAG. Entry from 678AH with the CARRY FLAG set.
66A6
CP 03H FE 03
Compare the type with 03H (8-bit register).
66A8
A register: JUMP to 66ACH with its number in Register B.
66AA
LD B,06H 06 06
Otherwise use register number 06H, the (HL) position.
66AC
POP AF F1
Restore the CARRY FLAG ...
66AD
PUSH AF F5
... and save it again.
66AE
CARRY FLAG clear: JUMP to 66B5H.
66B0
LD A,B 78
Load Register A with the register number ...
66B1
RLCA 07
... and rotate it ...
66B2
RLCA 07
... into bits ...
66B4
LD B,A 47
Store it back into Register B.
66B5
LD HL,53B4H 21 B4 53
Point HL to the length at 53B4H.
66B8
INC (HL) 34
Add one to the length.
66B9
LD A,04H 3E 04
Load Register A with 04H ...
66BB
SUB (HL) 96
... minus the length: the number of bytes to step back.
66BC
DEC HL 2B
Move HL back one byte.
66BD
DEC A 3D
Decrement the count ...
66BE
... and LOOP BACK to 66BCH until HL = 53B0H + the length, the last instruction byte.
66C0
LD A,B 78
Load Register A with the register number ...
66C1
OR (HL) B6
... OR it into that byte ...
66C2
LD (HL),A 77
... and store it.
66C3
POP AF F1
Restore the type.
66C4
CP 03H FE 03
Compare it with 03H.
66C6
RET Z C8
A register: RETURN.
66C7
GOSUB to 6804H to test for (.
66CA
No (: JUMP to 66E2H for ILLEGAL ADDRESSING MODE.
66CC
GOSUB to 61B5H to classify the word inside the bracket.
66CF
CP 05H FE 05
Compare the type with 05H (IX or IY).
66D1
IX or IY: JUMP to 66E8H.
66D3
CP 04H FE 04
Compare the type with 04H (register pair). Also reached from JP at 6830H.
66D5
Not a pair: JUMP to 66E2H for ILLEGAL ADDRESSING MODE.
66D7
LD A,B 78
Load Register A with the pair number ...
66D8
CP 02H FE 02
... and compare it with 02H (HL).
66DA
Not HL: JUMP to 66E2H for ILLEGAL ADDRESSING MODE.
66DC
Require )
GOSUB to 5BBEH to get the next character. Called or jumped to by many handlers.
66DF
CP 29H FE 29
Compare it with 29H ()).
66E1
RET Z C8
Found: RETURN.
66E2H - Illegal Addressing Mode
Points Register DE to ILLEGAL ADDRESSING MODE and jumps to 614BH, which counts and reports the error and goes on to the next source line. About forty operand checks jump here.
66E2
LD DE,59F3H 11 F3 59
Point DE to ILLEGAL ADDRESSING MODE at 59F3H ...
66E5
... and JUMP to 614BH to report it and go on to the next line.
66E8H - (IX+d) and (IY+d) Operands
Sets the DDH or FDH prefix and adds 2 to the length (66FEH), evaluates the displacement, stores it at 53B2H, checks that it is -128 to +127 (56EEH) and requires ). When the length has become 4 the instruction is a CB-prefixed one (DD CB d op), so the opcode is first moved from 53B2H to 53B3H to make room for the displacement. Also called from LD at 69F0H.
66E8
GOSUB to 66FEH to set the prefix and add 2 to the length. HL returns at 53B0H and Register A = the new length.
66EC
INC HL 23
... to 53B2H.
66ED
CP 04H FE 04
Compare the length with 04H.
66EF
Not 4: JUMP to 66F5H.
66F1
LD B,(HL) 46
CB form: load Register B with the opcode at 53B2H ...
66F2
INC HL 23
... move to 53B3H ...
66F3
LD (HL),B 70
... and store it there.
66F4
DEC HL 2B
Move back to 53B2H.
66F5
GOSUB to 62A0H to evaluate the displacement into Register DE.
66F8
LD (HL),E 73
Store it at 53B2H.
66F9
GOSUB to 56EEH to report FIELD OVERFLOW if it is outside -128 to +127.
66FC
JUMP to 66DCH to require ).
66FEH - Set the DDH or FDH Prefix; 670BH - Add 2 to the Length
66FEH
Register B = 00H for IX or 01H for IY. Stores DDH or FDH at 53B0H and sets Register B = 02H, the HL position that IX and IY replace in the opcode, then continues at 670BH. Returns with HL = 53B0H.
670BH
Adds 2 to the length at 53B4H and returns the new length in Register A. Used for a prefix, an immediate byte (666EH), a second opcode byte (67B4H) and DEFW (6B6DH).
66FE
LD HL,53B0H 21 B0 53
Point HL to the prefix byte at 53B0H.
6701
LD (HL),DDH 36 DD
Store DDH (IX).
6703
DEC B 05
Decrement Register B ...
6704
INC B 04
... and increment it: the Z FLAG is set for IX (00H).
6705
LD B,02H 06 02
Load Register B with 02H, the HL position.
6709
LD (HL),FDH 36 FD
IY: store FDH instead.
670B
LD A,(53B4H) 3A B4 53
Load Register A with the length from 53B4H ...
670E
ADD A,02H C6 02
... add 2 ...
6710
LD (53B4H),A 32 B4 53
... and store it.
6714H - ADC and SBC Handler
Type 04H (ADC 88H, SBC 98H). The 8-bit forms (ADC A,s and SBC A,s) are passed to 6654H by 663DH. Otherwise the first operand must be HL, and the instruction is EDH followed by 4AH (ADC) or 42H (SBC) ORed with the second register pair in bits 4-5. Length 2.
6714
GOSUB to 663DH. It only returns for a first operand that is not an 8-bit register.
6717
CP 04H FE 04
Compare the type with 04H (register pair).
6719
Not a pair: JUMP to 66E2H for ILLEGAL ADDRESSING MODE.
671B
LD A,B 78
Load Register A with the pair number ...
671C
CP 02H FE 02
... and compare it with 02H (HL).
671E
Not HL: JUMP to 66E2H for ILLEGAL ADDRESSING MODE.
6720
LD (53B4H),A 32 B4 53
Store 02H as the length.
6723
LD HL,53B1H 21 B1 53
Point HL to 53B1H.
6726
LD A,(HL) 7E
Load Register A with the base opcode (88H or 98H).
6727
RRCA 0F
Rotate it right: 44H or 4CH.
6728
AND 08H E6 08
Keep bit 3: 00H for ADC, 08H for SBC.
672A
XOR 4AH EE 4A
XOR with 4AH: 4AH for ADC, 42H for SBC.
672C
LD (HL),A 77
Store it.
672D
GOSUB to 674DH to OR the second pair into bits 4-5. HL returns at 53B1H and Register A = the finished byte.
6730
LD (HL),EDH 36 ED
Store EDH as the first byte ...
6732
INC HL 23
... move to 53B2H ...
6733
LD (HL),A 77
... and store the second byte there.
6735H - ADD Handler
Type 05H (ADD 80H). ADD A,s is passed to 6654H by 663DH. ADD HL,ss gives 09H ORed with the pair in bits 4-5, length 1. ADD IX,pp and ADD IY,pp are handled at 675DH.
6735
GOSUB to 663DH. It only returns for a first operand that is not an 8-bit register.
6738
LD HL,53B1H 21 B1 53
Point HL to 53B1H ...
673B
LD (HL),09H 36 09
... and store 09H, ADD HL,BC.
673D
CP 05H FE 05
Compare the type with 05H (IX or IY).
673F
IX or IY: JUMP to 675DH.
6741
CP 04H FE 04
Compare the type with 04H (register pair).
6743
Not a pair: JUMP to 66E2H for ILLEGAL ADDRESSING MODE.
6745
LD A,B 78
Load Register A with the pair number ...
6746
CP 02H FE 02
... and compare it with 02H (HL).
6748
Not HL: JUMP to 66E2H for ILLEGAL ADDRESSING MODE.
674A
GOSUB to 688DH to set the length to 1, then fall into 674DH for the second pair.
674DH - Register Pair into Bits 4-5
674DH
Requires the next operand to be a register pair (61B0H), else ILLEGAL ADDRESSING MODE, and falls into 6752H.
6752H
Rotates Register B (the pair number: BC 0, DE 1, HL 2, SP 3, AF 3) into bits 4-5 and ORs it into the opcode at 53B1H. Many handlers end here, and PUSH/POP push 6752H as their return address.
6753H
The same with the number already in Register A (from 6B02H).
674D
GOSUB to 61B0H to classify the operand; the Z FLAG is set for a register pair.
6750
Not a pair: JUMP to 66E2H for ILLEGAL ADDRESSING MODE.
6752
LD A,B 78
Load Register A with the pair number.
6753
RRCA 0F
Rotate it right ...
6755
RRCA 0F
... times, into ...
6757
LD HL,53B1H 21 B1 53
Point HL to 53B1H.
675A
OR (HL) B6
OR the pair into the opcode ...
675B
LD (HL),A 77
... and store it.
675DH - ADD IX,pp and ADD IY,pp
Sets the prefix. The second operand may be BC, DE or SP, or the same index register as the first (ADD IX,IX gives 29H). HL, the other index register and anything else give ILLEGAL ADDRESSING MODE.
675D
LD C,B 48
Keep the index number (00H IX, 01H IY) in Register C.
675E
GOSUB to 66FEH to set the prefix and add 2 to the length.
6761
LD L,C 69
Keep the index number in Register L.
6762
GOSUB to 61B0H to classify the second operand; the Z FLAG is set for a register pair.
6765
Not a pair: JUMP to 676FH.
6767
LD A,B 78
Load Register A with the pair number ...
6768
CP 02H FE 02
... and compare it with 02H (HL).
676A
HL: JUMP to 66E2H for ILLEGAL ADDRESSING MODE.
676D
JUMP to 6752H to OR the pair into 09H.
676F
CP 05H FE 05
Compare the type with 05H (IX or IY).
6771
Anything else: JUMP to 66E2H for ILLEGAL ADDRESSING MODE.
6774
LD A,B 78
Load Register A with the index number ...
6775
CP L BD
... and compare it with the first operand's.
6776
A different index register: JUMP to 66E2H for ILLEGAL ADDRESSING MODE.
6779
LD B,02H 06 02
Use pair number 02H, the HL position ...
677B
... and JUMP to 6752H to make 29H.
677DH - INC and DEC Handler
Type 06H (INC 04H, DEC 05H). A register pair gives 03H (INC) or 0BH (DEC) ORed with the pair in bits 4-5, length 1. IX and IY get the prefix as well (DD 23H, DD 2BH). Any other operand goes to 66A5H with the CARRY FLAG set, so the register (or number 6 for (HL), (IX+d) and (IY+d)) goes into bits 3-5 of 04H or 05H.
677D
GOSUB to 61B0H to classify the operand; the Z FLAG is set for a register pair.
6780
Not a pair: JUMP to 6787H.
6782
GOSUB to 688DH to set the length to 1.
6787
CP 05H FE 05
Compare the type with 05H (IX or IY).
6789
SCF 37
Set the CARRY FLAG: the register goes into bits 3-5.
678A
Not IX or IY: JUMP to 66A5H to encode the 8-bit operand.
678D
GOSUB to 66FEH to set the prefix (length 2, Register B = 02H).
6790
LD HL,53B1H 21 B1 53
Point HL to 53B1H.
6793
LD A,(HL) 7E
Load Register A with the base (04H or 05H).
6794
RLCA 07
Rotate it left ...
6796
RLCA 07
... times: 20H or 28H.
6797
AND 08H E6 08
Keep bit 3: 00H for INC, 08H for DEC.
6799
OR 03H F6 03
OR in 03H: 03H or 0BH.
679B
LD (HL),A 77
Store it.
679C
JUMP to 6752H to OR the pair into bits 4-5.
679EH - IM Handler; 67B0H - Second Byte; 67B7H - ED Group
679EH
Type 07H (IM, base EDH). Evaluates the mode: 0 gives 46H, 1 gives 56H and 2 gives 5EH; 3 or more is ILLEGAL ADDRESSING MODE.
67B0H
Stores Register A at 53B2H and adds 2 to the length. Used by IM, the ED group, JR, DJNZ, IN and OUT.
67B7H
Type 08H (CPD, CPDR, CPI, CPIR, IND, INDR, INI, INIR, LDD, LDDR, LDI, LDIR, NEG, OTDR, OTIR, OUTD, OUTI, RETI, RETN, RLD, RRD). Moves the base opcode to the second byte and stores EDH as the first. Also used for LD A,I/R and LD I/R,A.
679E
GOSUB to 62A0H to evaluate the mode into Register DE.
67A1
LD A,E 7B
Load Register A with its low byte.
67A2
CP 03H FE 03
Compare it with 03H.
67A4
3 or more: JUMP to 66E2H for ILLEGAL ADDRESSING MODE.
67A7
OR A B7
Test for mode 0.
67A8
Mode 0: JUMP to 67AEH to make 46H.
67AA
INC A 3C
Add one: 2 for mode 1, 3 for mode 2 ...
67AB
RLCA 07
... and rotate it left ...
67AD
RLCA 07
... times: 10H or 18H.
67AE
OR 46H F6 46
OR in 46H: 46H, 56H or 5EH.
67B0
LD HL,53B2H 21 B2 53
Point HL to 53B2H. Also reached from 67BDH, 6876H, 68B7H, 68FEH and 690CH.
67B3
LD (HL),A 77
Store the second byte.
67B4
JUMP to 670BH to add 2 to the length.
67B7
LD HL,53B1H 21 B1 53
ED Group
Point HL to 53B1H.
67BA
LD A,(HL) 7E
Load Register A with the base opcode.
67BB
LD (HL),EDH 36 ED
Store EDH as the first byte.
67BD
JUMP to 67B0H to store the base as the second byte, length 2.
67BFH - CALL Handler
Type 09H (CALL CDH). With a condition (67D7H) the opcode becomes C4H ORed with the condition in bits 3-5 and a comma is required. The address is evaluated (62A0H, or 6293H when 67D7H has already classified the word) and stored at 53B2H-53B3H with a length of 3.
67C2H
Also the JP cc,nn path (681DH).
67CCH / 67CFH
67CCH evaluates an already classified word if the Z FLAG is clear; 67CFH stores Register DE after 53B1H (HL = 53B1H) and sets the length to 3. Both are also used by JP and LD.
67BF
GOSUB to 67D7H: the Z FLAG is set if a condition was found and put into the opcode.
67C2
PUSH AF F5
Save the flags.
67C3
With a condition, GOSUB to 67F8H to require a comma.
67C6
POP AF F1
Restore the flags ...
67C7
PUSH AF F5
... and save them again.
67C8
With a condition, GOSUB to 62A0H to classify and evaluate the address.
67CB
POP AF F1
Restore the flags. Also reached from JP at 6823H.
67CC
Without a condition, GOSUB to 6293H to evaluate the word 67D7H already classified.
67CF
INC HL 23
Move to 53B2H ...
67D0
LD (HL),E 73
... store the low byte of the address ...
67D1
INC HL 23
... move to 53B3H ...
67D2
LD (HL),D 72
... store the high byte ...
67D3
INC HL 23
... move to 53B4H ...
67D4
LD (HL),03H 36 03
... and set the length to 3.
67D7H - Condition Operand
Classifies the operand (61B5H; 67DAH uses the type already in Register A, from RET). A condition (type 06H) is put into the opcode at 53B1H: it is ANDed with C6H (which clears bits 0 and 3-5) and ORed with the condition number in bits 3-5, and the routine returns with the Z FLAG set. Register C (type 03H, number 1) is taken as condition 3, carry, because the register table finds C first. Anything else returns with the Z FLAG clear and the word still classified, for the caller to evaluate as an address. Register HL returns at 53B1H.
67D7
GOSUB to 61B5H to classify the operand.
67DA
LD HL,53B1H 21 B1 53
Point HL to 53B1H. Entry from RET at 6813H.
67DD
CP 03H FE 03
Compare the type with 03H (8-bit register).
67DF
Not a register: JUMP to 67E8H.
67E1
LD A,B 78
Load Register A with the register number ...
67E2
DEC A 3D
... and decrement it: 00H only for register C.
67E3
RET NZ C0
Any other register: RETURN with the Z FLAG clear.
67E4
LD B,03H 06 03
Register C: use condition 3 (carry) ...
67E6
LD A,06H 3E 06
... and type 06H.
67E8
CP 06H FE 06
Compare the type with 06H (condition).
67EA
RET NZ C0
Not a condition: RETURN with the Z FLAG clear.
67EB
PUSH AF F5
Save the type and the Z FLAG.
67EC
LD A,B 78
Load Register A with the condition number ...
67ED
RLCA 07
... and rotate it ...
67EE
RLCA 07
... into bits ...
67F0
LD C,A 4F
Keep it in Register C.
67F1
LD A,C6H 3E C6
Load Register A with C6H ...
67F3
AND (HL) A6
... AND it with the opcode (C3H becomes C2H, CDH C4H, C9H C0H, 18H 00H) ...
67F4
OR C B1
... OR in the condition ...
67F5
LD (HL),A 77
... and store it.
67F6
POP AF F1
Restore Register A = 06H and the Z FLAG.
67F7
RET C9
RETURN with the Z FLAG set.
67F8H - Require a Comma; 6801H/6804H - Test for (
67F8H
Reads the next character; anything other than a comma is ILLEGAL ADDRESSING MODE.
6801H
Classifies the next operand (61B5H) and continues at 6804H.
6804H
Tests whether the word at Register DE starts with (: the Z FLAG is set if it does. Registers A and BC are preserved.
67F8
GOSUB to 5BBEH to get the next character.
67FB
CP 2CH FE 2C
Compare it with 2CH (comma).
67FD
Not a comma: JUMP to 66E2H for ILLEGAL ADDRESSING MODE.
6801
GOSUB to 61B5H to classify the next operand.
6804
PUSH BC C5
Save Register BC.
6805
LD B,A 47
Keep the type in Register B.
6806
LD A,(DE) 1A
Load Register A with the first character of the word ...
6807
CP 28H FE 28
... and compare it with 28H ((). The 28H byte at 6808H is also used by LD at 69C4H as a ( character.
6809
LD A,B 78
Restore the type into Register A.
680A
POP BC C1
Restore Register BC.
680CH - RET Handler
Type 0AH (RET C9H). Length 1. With no operand the opcode stays C9H; a condition gives C0H ORed with the condition in bits 3-5. Anything else is put back (5BF4H) so that the end-of-line check at 6DDFH reports it as ILLEGAL ADDRESSING MODE.
680C
GOSUB to 688DH to set the length to 1.
680F
GOSUB to 61D6H to classify the operand.
6812
RET Z C8
Nothing follows: RETURN (C9H).
6813
GOSUB to 67DAH to put a condition into the opcode.
6816
RET Z C8
A condition: RETURN.
6817
Anything else: JUMP to 5BF4H to put back the last character read.
681AH - JP Handler
Type 0BH (JP C3H). JP cc,nn becomes C2H ORed with the condition and continues as CALL at 67C2H. JP nn is evaluated and stored with a length of 3. JP (HL) gives E9H, length 1. JP (IX) and JP (IY) give DD/FD E9H.
681A
GOSUB to 67D7H: the Z FLAG is set if a condition was found.
681D
A condition: JUMP to 67C2H to finish as CALL cc,nn does.
681F
PUSH AF F5
Save the flags.
6820
LD A,(DE) 1A
Load Register A with the first character of the operand ...
6821
CP 28H FE 28
... and compare it with 28H (().
6823
No bracket: JUMP to 67CBH to evaluate and store the address (JP nn).
6825
POP AF F1
Restore the flags.
6826
LD (HL),E9H 36 E9
Store E9H, JP (HL).
6828
GOSUB to 61ADH to classify the word in the bracket; the Z FLAG is set for IX or IY.
682B
PUSH AF F5
Save the result.
682C
Not IX or IY: GOSUB to 688DH to set the length to 1.
682F
POP AF F1
Restore the result.
6830
Not IX or IY: JUMP to 66D3H, which requires HL and ).
6833
GOSUB to 66FEH to set the prefix (length 2).
6836
JUMP to 66DCH to require ).
6839H - JR and DJNZ Handlers
6839H
Type 0CH (JR 18H). A condition must be NZ, Z, NC or C (numbers 0-3); PO, PE, P and M give ILLEGAL ADDRESSING MODE. The opcode becomes 20H, 28H, 30H or 38H and a comma is required before the target.
6850H
Type 0DH (DJNZ 10H). Evaluates the target.
6839
GOSUB to 67D7H: the Z FLAG is set if a condition was put into the opcode (18H AND C6H = 00H, ORed with the condition).
683C
PUSH AF F5
Save the flags.
683D
No condition: GOSUB to 6293H to evaluate the target.
6840
POP AF F1
Restore the flags.
6841
No condition: JUMP to 6853H.
6843
LD A,B 78
Load Register A with the condition number ...
6844
CP 04H FE 04
... and compare it with 04H.
6846
PO, PE, P or M: JUMP to 66E2H for ILLEGAL ADDRESSING MODE.
6849
LD A,(HL) 7E
Load Register A with the opcode ...
684A
OR 20H F6 20
... OR in 20H ...
684C
LD (HL),A 77
... and store it.
684D
GOSUB to 67F8H to require a comma.
6850
DJNZ
GOSUB to 62A0H to evaluate the target into Register DE.
6853H - Relative Jump Offset
Computes the offset target - (location counter + 2). If it is outside -128 to +127, BRANCH OUT OF RANGE is reported through 6150H and the offset FEH (a jump to itself) is used. The offset is stored by 67B0H with a length of 2. The seven bytes at 6867H-686DH are never executed.
6853
LD HL,(53B6H) 2A B6 53
Load Register HL with the location counter from 53B6H.
6856
EX DE,HL EB
Exchange: HL = the target, DE = the location counter.
6857
OR A B7
Clear the CARRY FLAG.
6858
SBC HL,DE ED 52
Subtract: HL = target - location counter.
685A
LD DE,007EH 11 7E 00
Load Register DE with 007EH ...
685D
ADD HL,DE 19
... and add it: H is 00H only when target - (location counter + 2) is -128 to +127.
685E
INC H 24
Increment Register H ...
685F
DEC H 25
... and decrement it.
6860
Out of range: JUMP to 686EH.
6862
LD A,L 7D
Load Register A with the low byte ...
6863
SUB 80H D6 80
... minus 80H: the offset.
6865
JUMP to 6876H to store it.
6867-686D
NOP x 7 00 x 7
Unused
Seven 00H bytes. The JR at 6865H jumps over them.
686E
LD DE,59E0H 11 E0 59
Point DE to BRANCH OUT OF RANGE at 59E0H ...
6871
... and GOSUB to 6150H to report it and continue.
6874
LD A,FEH 3E FE
Use the offset FEH.
6876
JUMP to 67B0H to store the offset at 53B2H, length 2.
6879H - RST Handler; 688DH - Length 1
6879H
Type 0EH (RST C7H). The value must be 00H, 08H, ... 38H, else ILLEGAL ADDRESSING MODE; it is ORed into C7H.
688DH
Type 00H (CCF, CPL, DAA, DI, EI, EXX, HALT, NOP, RLA, RLCA, RRA, RRCA, SCF): sets the length at 53B4H to 1. Many handlers call it.
6879
GOSUB to 62A0H to evaluate the restart address into Register DE.
687C
LD A,D 7A
Load Register A with the high byte ...
687D
OR A B7
... and test it.
687E
Not 00H: JUMP to 66E2H for ILLEGAL ADDRESSING MODE.
6881
LD A,E 7B
Load Register A with the low byte ...
6882
AND C7H E6 C7
... and keep bits 0-2 and 6-7.
6884
Not a multiple of 8 below 40H: JUMP to 66E2H for ILLEGAL ADDRESSING MODE.
6887
LD A,C7H 3E C7
Load Register A with C7H ...
6889
OR E B3
... OR in the address ...
688A
LD (53B1H),A 32 B1 53
... and store it at 53B1H.
688D
LD A,01H 3E 01
Length 1
Load Register A with 01H ...
688F
LD (53B4H),A 32 B4 53
... and store it as the length.
6893H - IN Handler
Type 0FH (IN DBH). The first operand must be a register, followed by a comma and (. IN r,(C) gives EDH and 40H ORed with the register in bits 3-5. IN A,(n) keeps DBH and stores the port, which 6671H checks. A closing ) is required.
6893
GOSUB to 61B3H to classify the first operand; the Z FLAG is set for an 8-bit register.
6896
Not a register: JUMP to 66E2H for ILLEGAL ADDRESSING MODE.
6899
GOSUB to 67F8H to require a comma.
689C
PUSH BC C5
Save the register number (Register B).
689D
GOSUB to 6801H to classify the second operand and test for (.
68A0
No (: JUMP to 66E2H for ILLEGAL ADDRESSING MODE.
68A3
GOSUB to 61B3H to classify the word in the bracket; the Z FLAG is set for a register.
68A6
Not a register: JUMP to 68BDH for a port number.
68A8
DEC B 05
Decrement the register number: 00H only for C.
68A9
Not C: JUMP to 66E2H for ILLEGAL ADDRESSING MODE.
68AC
LD A,EDH 3E ED
Load Register A with EDH ...
68AE
LD (53B1H),A 32 B1 53
... and store it as the first byte.
68B1
POP AF F1
Restore the first register number into Register A.
68B3
RLCA 07
... into bits ...
68B5
OR 40H F6 40
OR in 40H.
68B7
GOSUB to 67B0H to store the second byte, length 2.
68BA
JUMP to 66DCH to require ).
68BD
LD H,A 67
Keep the type in Register H.
68BE
POP AF F1
Restore the first register number into Register A.
68BF
CP 07H FE 07
Compare it with 07H (A).
68C1
LD A,H 7C
Restore the type into Register A.
68C2
Not A: JUMP to 66E2H for ILLEGAL ADDRESSING MODE.
68C5
GOSUB to 6293H to evaluate the port into Register DE.
68C8
GOSUB to 6671H to report FIELD OVERFLOW if it is over FFH.
68CB
LD A,E 7B
Load Register A with the port ...
68CC
... and JUMP to 68B7H to store it (the opcode stays DBH).
68CEH - OUT Handler
Type 10H (OUT D3H). The first operand must start with (. OUT (C),r gives EDH and 41H ORed with the register in bits 3-5. OUT (n),A keeps D3H and stores the port, which 6671H checks. Any register other than A after (n), is ILLEGAL ADDRESSING MODE.
68CE
GOSUB to 6801H to classify the first operand and test for (.
68D1
No (: JUMP to 66E2H for ILLEGAL ADDRESSING MODE.
68D4
GOSUB to 61B3H to classify the word in the bracket; the Z FLAG is set for a register.
68D7
PUSH AF F5
Save the result.
68D8
Not a register: GOSUB to 6293H to evaluate the port into Register DE.
68DB
POP AF F1
Restore the result ...
68DC
PUSH AF F5
... and save it again.
68DD
Not a register: JUMP to 68E3H.
68DF
DEC B 05
Decrement the register number: 00H only for C.
68E0
Not C: JUMP to 66E2H for ILLEGAL ADDRESSING MODE.
68E3
GOSUB to 66DCH to require ).
68E6
GOSUB to 67F8H to require a comma.
68E9
PUSH DE D5
Save the port.
68EA
GOSUB to 61B3H to classify the second operand; the Z FLAG is set for a register.
68ED
POP DE D1
Restore the port.
68EE
Not a register: JUMP to 66E2H for ILLEGAL ADDRESSING MODE.
68F1
POP AF F1
Restore the result for the first operand.
68F2
It was (C): JUMP to 6901H.
68F4
LD A,B 78
Load Register A with the register number ...
68F5
CP 07H FE 07
... and compare it with 07H (A).
68F7
Not A: JUMP to 66E2H for ILLEGAL ADDRESSING MODE.
68FA
GOSUB to 6671H to report FIELD OVERFLOW if the port is over FFH.
68FD
LD A,E 7B
Load Register A with the port ...
68FE
... and JUMP to 67B0H to store it (the opcode stays D3H), length 2.
6901
LD A,EDH 3E ED
Load Register A with EDH ...
6903
LD (53B1H),A 32 B1 53
... and store it as the first byte.
6906
LD A,B 78
Load Register A with the register number ...
6907
RLCA 07
... and rotate it ...
6908
RLCA 07
... into bits ...
690A
OR 41H F6 41
OR in 41H.
690C
JUMP to 67B0H to store the second byte, length 2.
690FH - EX Instruction Handler
Operand handler for the EX mnemonic. The opcode table entry for EX (type 11H) points here through the dispatch table at 6DC9H and has already stored EBH (EX DE,HL) in 53B1H. The handler accepts EX (SP),HL (E3H), EX (SP),IX / EX (SP),IY (DDH/FDH E3H), EX DE,HL (EBH) and EX AF,AF' (08H). Anything else goes to 66E2H (ILLEGAL ADDRESSING MODE) through 697DH.
The operand classifier (61D6H) returns a type in Register A and a register number in Register B: type 03H = 8-bit register, 04H = register pair (BC=0, DE=1, HL=2, SP=3), 05H = index register (IX=0, IY=1), 07H = AF.
690F
GOSUB to 6801H to classify the first operand. Register A returns its type and the Z FLAG is set if the operand begins with (.
6912
If the first operand does not begin with (, JUMP to 6938H.
6914
EX (SP),...
GOSUB to 61B0H, which sets A = 04H and classifies the operand inside the parentheses; the Z FLAG is set if it is a register pair (Register B = pair number).
6917
If it is not a register pair, JUMP to 697DH for ILLEGAL ADDRESSING MODE.
6919
LD A,B 78
Load Register A with the pair number from Register B.
691A
CP 03H FE 03
Compare against 03H (SP).
691C
If the pair is not SP, JUMP to 697DH for the error.
691E
GOSUB to 66DCH, which requires the closing ) (and reports ILLEGAL ADDRESSING MODE if it is missing).
6921
GOSUB to 67F8H, which requires a comma between the operands.
6924
LD A,E3H 3E E3
Load Register A with E3H, the opcode of EX (SP),HL.
6926
LD (53B1H),A 32 B1 53
Store E3H into 53B1H, the opcode byte, replacing the EBH from the opcode table.
6929
GOSUB to 61ADH, which sets A = 05H and classifies the second operand; the Z FLAG is set if it is IX or IY (Register B = 0 for IX, 1 for IY).
692C
If IX or IY, JUMP to 66FEH, which stores the DDH or FDH prefix in 53B0H and makes the instruction 2 bytes long.
692F
CP 04H FE 04
Second Operand Must Be HL
Compare the operand type in Register A against 04H (register pair).
6931
If it is not a register pair, JUMP to 697DH for the error.
6933
LD A,B 78
Load Register A with the pair number from Register B.
6934
CP 02H FE 02
Compare against 02H (HL). The Z FLAG is set for HL.
6936
JUMP to 695FH to finish (error unless the Z FLAG is set).
6938
CP 04H FE 04
EX DE,HL
Compare the first operand type in Register A against 04H (register pair).
693A
If it is not a register pair, JUMP to 6947H to try EX AF,AF'.
693C
DEC B 05
Decrement the pair number in Register B: it becomes 00H only for DE (pair 1).
693D
If the first operand is not DE, JUMP to 697DH for the error.
693F
GOSUB to 67F8H, which requires a comma.
6942
GOSUB to 61B5H to classify the second operand (Register A = the type).
6945
JUMP back to 692FH, which requires the second operand to be HL. The opcode stays EBH.
6947
CP 07H FE 07
EX AF,AF'
Compare the first operand type against 07H (AF).
6949
If it is not AF, JUMP to 697DH for the error.
694B
GOSUB to 67F8H, which requires a comma.
694E
GOSUB to 61B5H to classify the second operand.
6951
CP 07H FE 07
Compare its type against 07H (AF).
6953
If the second operand is not AF, JUMP to 697DH for the error.
6955
LD A,08H 3E 08
Load Register A with 08H, the opcode of EX AF,AF'.
6957
LD (53B1H),A 32 B1 53
Store 08H into 53B1H, the opcode byte.
695A
GOSUB to 5BBEH to read the next character of the source line.
695D
CP 27H FE 27
Compare it against 27H (apostrophe): the second AF must be written AF'.
695F
If the test failed (NZ), JUMP to 697DH for ILLEGAL ADDRESSING MODE.
6961
JUMP to 688DH, which sets the instruction length (53B4H) to 1 and returns.
6964H - PUSH and POP Handler
Type 12H (PUSH C5H, POP C1H). Pushes 6752H as the return address, so the pair number ends up ORed into bits 4-5. IX and IY set the prefix and use the HL position (DD/FD E5H and E1H). AF uses pair number 3 (F5H, F1H). BC, DE and HL give a length of 1. SP and anything else are ILLEGAL ADDRESSING MODE.
6964
LD BC,6752H 01 52 67
Load Register BC with 6752H ...
6967
PUSH BC C5
... and push it as the return address.
6968
GOSUB to 61ADH to classify the operand; the Z FLAG is set for IX or IY.
696B
IX or IY: JUMP to 66FEH to set the prefix (Register B = 02H, the HL position). Its RET goes to 6752H.
696E
CP 07H FE 07
Compare the type with 07H (AF).
6970
AF (pair number 3): JUMP to 688DH to set the length to 1.
6973
CP 04H FE 04
Compare the type with 04H (register pair).
6975
Not a pair: JUMP to 697DH.
6977
LD A,B 78
Load Register A with the pair number ...
6978
CP 03H FE 03
... and compare it with 03H (SP).
697A
BC, DE or HL: JUMP to 688DH to set the length to 1.
697D
SP or anything else: JUMP to 66E2H for ILLEGAL ADDRESSING MODE.
6980H - LD Handler: 8-Bit Register Destination
Type 13H (LD, base 40H). Register HL stays at 53B1H throughout the handler. When the destination is a register r, 40H is ORed with r in bits 3-5 and a comma is required. For any destination other than A the source is handled by 6654H: a register gives 40H+r<<3+r', (HL), (IX+d) and (IY+d) use number 6, and a value is turned into 06H+r<<3 n by the XOR 46H at 6665H.
Destination A
I and R give EDH 57H or 5FH. (HL), (IX+d) and (IY+d) are read again through 66A4H (7EH). (BC) and (DE) give 0AH and 1AH. (nn) gives 3AH nn. Everything else goes to 6657H as for the other registers.
6980
LD HL,53B1H 21 B1 53
Point HL to 53B1H.
6983
GOSUB to 61B3H to classify the destination; the Z FLAG is set for an 8-bit register.
6986
Not a register: JUMP to 69E3H.
6988
PUSH BC C5
Save the register number.
6989
LD C,A 4F
Keep the type (03H) in Register C.
698A
LD A,B 78
Load Register A with the register number ...
698B
RLCA 07
... and rotate it ...
698C
RLCA 07
... into bits ...
698E
OR (HL) B6
OR it into the opcode ...
698F
LD (HL),A 77
... and store it.
6990
GOSUB to 67F8H to require a comma.
6993
LD A,B 78
Load Register A with the register number ...
6994
CP 07H FE 07
... and compare it with 07H (A).
6996
LD A,C 79
Load Register A with the type 03H, the value 6654H's 61B5H call expects.
6997
POP BC C1
Restore the register number into Register B.
6998
Not A: JUMP to 6654H to handle the source.
699B
GOSUB to 6801H to classify the source and test for (.
69A0
CP 08H FE 08
Compare the type with 08H (I or R).
69A2
Anything else: JUMP to 6657H to handle the source as for any register.
69A5
LD A,57H 3E 57
Load Register A with 57H ...
69A7
OR B B0
... OR in the number (00H for I, 08H for R): 57H or 5FH ...
69A8
LD (HL),A 77
... and store it.
69A9
JUMP to 67B7H to put EDH in front, length 2.
69AC
GOSUB to 61ADH to classify the word in the bracket; the Z FLAG is set for IX or IY.
69AF
IX or IY: JUMP to 69BDH.
69B2
CP 04H FE 04
Compare the type with 04H (register pair).
69B4
Not a pair: JUMP to 69DBH for an address.
69B6
PUSH BC C5
Save the pair number.
69B7
DEC B 05
Decrement it ...
69B8
DEC B 05
... twice: 00H only for HL.
69B9
POP BC C1
Restore the pair number.
69BA
Not HL: JUMP to 69CAH.
69BD
GOSUB to 5BF4H to put back the last character ...
69C0
... and GOSUB to 5BF4H to put back the one before it, so the two-letter name (HL, IX or IY) can be read again.
69C3
XOR A AF
Set Register A to 00H (not a register) and clear the CARRY FLAG.
69C4
LD DE,6808H 11 08 68
Point DE to 6808H, a 28H (() byte inside the CP 28H instruction at 6807H, so 66A4H sees an operand starting with (.
69C7
JUMP to 66A4H: it ORs in 06H (7EH), reads HL, IX or IY again and finishes the (HL) or (IX+d) form.
69CA
LD A,B 78
Load Register A with the pair number ...
69CB
CP 03H FE 03
... and compare it with 03H (SP).
69CD
(SP): JUMP to 66E2H for ILLEGAL ADDRESSING MODE.
69D0
LD (HL),0AH 36 0A
Store 0AH, LD A,(BC).
69D2
GOSUB to 6752H to OR in the pair: 0AH or 1AH.
69D5
GOSUB to 688DH to set the length to 1.
69D8
JUMP to 66DCH to require ).
69DB
LD (HL),3AH 36 3A
Store 3AH, LD A,(nn).
69DD
GOSUB to 67CCH to evaluate the address and store it, length 3.
69E0
JUMP to 66DCH to require ).
69E3H - LD Handler: Destination in Brackets
(IX+d) and (IY+d): with a register source DD/FD 70H+r d (length 3), with a value DD/FD 36H d n (length 4). (HL): 70H+r, or 36H n. (BC) and (DE): the source must be A, giving 02H or 12H. Any other bracketed destination is an address, handled at 6A3AH. A destination that is not in brackets goes to 6A78H.
69E3
GOSUB to 6804H to test the destination for (.
69E6
No bracket: JUMP to 6A78H.
69E9
LD (HL),70H 36 70
Store 70H, LD (HL),B.
69EB
GOSUB to 61ADH to classify the word in the bracket; the Z FLAG is set for IX or IY.
69EE
Not IX or IY: JUMP to 6A00H.
69F0
GOSUB to 66E8H to set the prefix and store the displacement at 53B2H.
69F3
GOSUB to 67F8H to require a comma.
69F6
XOR A AF
Set Register A to 00H ...
69F7
LD (53B4H),A 32 B4 53
... and clear the length, so 6A0FH counts the opcode and any value byte from zero.
69FA
GOSUB to 6A0FH to encode the source.
69FD
JUMP to 670BH to add 2 for the prefix and displacement.
6A00
CP 04H FE 04
Compare the type with 04H (register pair).
6A02
Not a pair: JUMP to 6A3AH for an address.
6A04
GOSUB to 66DCH to require ).
6A07
GOSUB to 67F8H to require a comma.
6A0A
LD A,B 78
Load Register A with the pair number ...
6A0B
CP 02H FE 02
... and compare it with 02H (HL).
6A0D
Not HL: JUMP to 6A1FH.
6A0F
Source for (HL) or (IX+d)
GOSUB to 61B3H to classify the source; the Z FLAG is set for a register.
6A12
A register: JUMP to 66A4H to OR it into 70H.
6A15
PUSH AF F5
Save the type.
6A16
LD A,36H 3E 36
Load Register A with 36H, LD (HL),n ...
6A18
LD (53B1H),A 32 B1 53
... and store it.
6A1B
POP AF F1
Restore the type.
6A1C
JUMP to 6669H to evaluate the value and store it in the byte after HL (53B2H for (HL), 53B3H for (IX+d)).
6A1F
CP 03H FE 03
Compare the pair number with 03H (SP).
6A21
(SP): JUMP to 66E2H for ILLEGAL ADDRESSING MODE.
6A24
PUSH BC C5
Save the pair number.
6A25
GOSUB to 61B3H to classify the source; the Z FLAG is set for a register.
6A28
Not a register: JUMP to 66E2H for ILLEGAL ADDRESSING MODE.
6A2B
LD A,B 78
Load Register A with the register number ...
6A2C
CP 07H FE 07
... and compare it with 07H (A).
6A2E
Not A: JUMP to 66E2H for ILLEGAL ADDRESSING MODE.
6A31
LD (HL),02H 36 02
Store 02H, LD (BC),A.
6A33
POP BC C1
Restore the pair number.
6A34
GOSUB to 6752H to OR in the pair: 02H or 12H.
6A37
JUMP to 688DH to set the length to 1.
6A3AH - LD (nn),Source
The address is stored at 53B2H-53B3H (67CCH, length 3) and ) and a comma are required. (nn),HL gives 22H. (nn),BC, (nn),DE and (nn),SP give EDH 43H+pair<<4 with a length of 4. (nn),A gives 32H. (nn),IX and (nn),IY give DD/FD 22H with a length of 4.
6A3A
LD (HL),02H 36 02
Store 02H: with the HL pair (20H) ORed in, it becomes 22H, LD (nn),HL.
6A3C
GOSUB to 67CCH to evaluate the address and store it, length 3. HL returns at 53B4H.
6A3F
GOSUB to 66DCH to require ).
6A42
GOSUB to 67F8H to require a comma.
6A45
GOSUB to 61B0H to classify the source; the Z FLAG is set for a register pair.
6A48
Not a pair: JUMP to 6A5CH.
6A4A
LD A,B 78
Load Register A with the pair number ...
6A4B
CP 02H FE 02
... and compare it with 02H (HL).
6A4D
HL: JUMP to 6752H to make 22H.
6A50
INC (HL) 34
Another pair: add one to the length (HL = 53B4H): 4.
6A51
LD HL,53B0H 21 B0 53
Point HL to 53B0H ...
6A54
LD (HL),EDH 36 ED
... and store EDH there.
6A56
INC HL 23
Move to 53B1H ...
6A57
LD (HL),43H 36 43
... and store 43H.
6A59
JUMP to 6752H to OR in the pair: 43H, 53H or 73H.
6A5C
CP 03H FE 03
Compare the type with 03H (8-bit register).
6A5E
Not a register: JUMP to 6A6CH.
6A60
LD A,B 78
Load Register A with the register number ...
6A61
CP 07H FE 07
... and compare it with 07H (A).
6A63
Not A: JUMP to 66E2H for ILLEGAL ADDRESSING MODE.
6A66
LD A,32H 3E 32
Load Register A with 32H, LD (nn),A ...
6A68
LD (53B1H),A 32 B1 53
... and store it.
6A6C
CP 05H FE 05
Compare the type with 05H (IX or IY).
6A6E
Anything else: JUMP to 66E2H for ILLEGAL ADDRESSING MODE.
6A71
DEC (HL) 35
Take one from the length (HL = 53B4H): 2, so that adding 2 for the prefix gives 4.
6A72
GOSUB to 66FEH to set the prefix and add 2 to the length (Register B = 02H).
6A75
JUMP to 6752H to make 22H.
6A78H - LD Handler: 16-Bit and I/R Destinations
A destination that is not an 8-bit register and not in brackets. The opcode is first set to 2AH.
IX, IY
LD IX,nn gives DD/FD 21H nn; LD IX,(nn) gives DD/FD 2AH nn (length 4).
I, R
LD I,A and LD R,A give EDH 47H or 4FH.
SP
SP,HL gives F9H and SP,IX/IY gives DD/FD F9H; any other source continues at 6ADDH as LD SP,nn or LD SP,(nn).
Other register pairs continue at 6AD9H. Anything else is ILLEGAL ADDRESSING MODE.
6A78
LD (HL),2AH 36 2A
Store 2AH, LD HL,(nn).
6A7A
PUSH AF F5
Save the destination type.
6A7B
GOSUB to 67F8H to require a comma.
6A7E
POP AF F1
Restore the type.
6A7F
CP 05H FE 05
Compare it with 05H (IX or IY).
6A81
Not IX or IY: JUMP to 6AA0H.
6A83
GOSUB to 66FEH to set the prefix (length 2). HL returns at 53B0H.
6A86
INC HL 23
Move to 53B1H.
6A87
GOSUB to 6801H to classify the source and test for (.
6A8A
PUSH AF F5
Save the result.
6A8D
LD (HL),21H 36 21
Store 21H, LD IX,nn.
6A8F
GOSUB to 67CCH to evaluate the value and store it; the length is set to 3.
6A94
GOSUB to 62A0H to evaluate the address in the bracket (the opcode stays 2AH).
6A97
GOSUB to 67CFH to store it; the length is set to 3.
6A9A
INC (HL) 34
Add one to the length (HL = 53B4H): 4.
6A9B
POP AF F1
Restore the result.
6A9C
With a bracket: JUMP to 66DCH to require ).
6AA0
CP 08H FE 08
Compare the type with 08H (I or R).
6AA2
Not I or R: JUMP to 6AB7H.
6AA4
LD A,47H 3E 47
Load Register A with 47H ...
6AA6
OR B B0
... OR in the number (00H for I, 08H for R): 47H or 4FH ...
6AA7
LD (HL),A 77
... and store it.
6AA8
GOSUB to 61B3H to classify the source; the Z FLAG is set for a register.
6AAB
Not a register: JUMP to 66E2H for ILLEGAL ADDRESSING MODE.
6AAE
LD A,B 78
Load Register A with the register number ...
6AAF
CP 07H FE 07
... and compare it with 07H (A).
6AB1
Not A: JUMP to 66E2H for ILLEGAL ADDRESSING MODE.
6AB4
JUMP to 67B7H to put EDH in front, length 2.
6AB7
CP 04H FE 04
Compare the type with 04H (register pair).
6AB9
Not a pair: JUMP to 66E2H for ILLEGAL ADDRESSING MODE.
6ABC
LD A,B 78
Load Register A with the pair number ...
6ABD
CP 03H FE 03
... and compare it with 03H (SP).
6ABF
Not SP: JUMP to 6AD9H.
6AC1
LD (HL),F9H 36 F9
Store F9H, LD SP,HL.
6AC3
GOSUB to 61ADH to classify the source; the Z FLAG is set for IX or IY.
6AC6
IX or IY: JUMP to 66FEH to set the prefix (DD/FD F9H, length 2).
6AC9
CP 04H FE 04
Compare the type with 04H (register pair).
6ACB
PUSH HL E5
Save HL ...
6ACC
LD H,03H 26 03
... load Register H with 03H, the SP pair number ...
6ACE
EX (SP),HL E3
... and exchange with the stack: 03xxH is on the stack in place of the BC that 6AD9H pushes, and HL = 53B1H again.
6ACF
Not a pair: JUMP to 6ADDH (LD SP,nn or LD SP,(nn)).
6AD1
DEC B 05
Decrement the pair number ...
6AD2
DEC B 05
... twice: 00H only for HL.
6AD3
Not HL: JUMP to 6ADDH.
6AD5
POP BC C1
Discard the saved pair number.
6AD6
JUMP to 688DH to set the length to 1 (F9H).
6AD9H - LD rr,nn and LD rr,(nn)
Register B = the destination pair (BC, DE, HL; SP arrives at 6ADDH from 6ACFH). LD rr,nn gives 01H+pair<<4 nn. LD HL,(nn) gives 2AH nn. LD BC,(nn), LD DE,(nn) and LD SP,(nn) give EDH 4BH+pair<<4 nn with a length of 4.
6AD9
PUSH BC C5
Save the pair number.
6ADA
GOSUB to 61B5H to classify the source.
6ADD
GOSUB to 6804H to test it for (.
6AE2
LD (HL),01H 36 01
Store 01H, LD BC,nn.
6AE4
GOSUB to 67CCH to evaluate the value and store it, length 3.
6AE7
POP BC C1
Restore the pair number.
6AE8
JUMP to 6752H to OR in the pair: 01H, 11H, 21H or 31H.
6AEB
LD (HL),2AH 36 2A
Store 2AH, LD HL,(nn).
6AED
GOSUB to 62A0H to evaluate the address in the bracket.
6AF0
GOSUB to 67CFH to store it, length 3.
6AF3
GOSUB to 66DCH to require ).
6AF6
POP AF F1
Restore the pair number into Register A.
6AF7
CP 02H FE 02
Compare it with 02H (HL).
6AF9
RET Z C8
HL: RETURN (2AH nn).
6AFA
LD HL,53B0H 21 B0 53
Point HL to 53B0H ...
6AFD
LD (HL),EDH 36 ED
... and store EDH there.
6AFF
INC HL 23
Move to 53B1H ...
6B00
LD (HL),4BH 36 4B
... and store 4BH.
6B02
GOSUB to 6753H to OR in the pair: 4BH, 5BH or 7BH.
6B05
LD A,04H 3E 04
Load Register A with 04H ...
6B07
LD (53B4H),A 32 B4 53
... and store it as the length.
6B0BH - DEFS Directive Handler
Type 14H in the opcode table (dispatch entry 6DCFH). Reserves space: the location counter advances by the operand value and no code is produced. 62A0H evaluates the operand and returns its value in Register DE.
6B0B
GOSUB to 62A0H to evaluate the DEFS operand. Register DE = the number of bytes to reserve.
6B0E
LD HL,(53B6H) 2A B6 53
Load Register HL with the location counter from 53B6H.
6B11
EX DE,HL EB
Exchange: HL = the DEFS size, DE = the location counter.
6B12
LD (53AEH),HL 22 AE 53
Store the size into 53AEH, the value printed in the address column of the listing line.
6B15
ADD HL,DE 19
Add the location counter: HL = the address after the reserved space.
6B16
LD (53B6H),HL 22 B6 53
Store it as the new location counter in 53B6H.
6B1AH - DEFM Directive Handler
Type 15H in the opcode table (dispatch entry 6DD1H). Emits the characters between the apostrophes one byte at a time: each character is stored as the instruction byte in 53B1H and passed through the pass-dependent output routine at 6DF4H, then the address advances by one. The loop ends at the closing apostrophe or the end of the line. The loop test was changed by the Apparat appendage: 6B56H jumps to 7292H, where pass 2 (listing) advances the address for each further character without listing it, so a DEFM produces one listing line; passes 1 and 3 handle every character through 6B30H.
6B1A
POP BC C1
Discard the return address 6DDFH pushed by the opcode dispatcher (657CH); DEFM does its own end-of-line handling.
6B1B
GOSUB to 5BBEH to get the next character of the operand.
6B1E
CP 27H FE 27
Compare it against 27H (apostrophe).
6B20
If the operand does not start with an apostrophe, JUMP to 66E2H for ILLEGAL ADDRESSING MODE.
6B23
GOSUB to 5BBEH to get the first character of the string.
6B26
If the line ended (Z FLAG set), JUMP to 66E2H for the error.
6B29
CP 27H FE 27
Compare the character against 27H (apostrophe).
6B2B
An empty string ('') is an error: JUMP to 66E2H.
6B2E
LD C,00H 0E 00
Load Register C with 00H.
6B30
LD (53B1H),A 32 B1 53
Emit One Character
Store the character in Register A into 53B1H, the instruction byte. Also entered from 729DH.
6B33
GOSUB to 688DH, which sets the instruction length at 53B4H to 1.
6B36
GOSUB to 6DF4H: pass 1 does nothing, pass 2 lists the line (6EE5H), pass 3 adds the byte to the object record (6E65H).
6B39
LD HL,(53AEH) 2A AE 53
Advance the Address
Load Register HL with the line address from 53AEH. Also entered from 7299H in pass 2.
6B3C
LD A,(53C0H) 3A C0 53
Load Register A with the pass number from 53C0H.
6B3F
CP 03H FE 03
Compare against 03H.
6B41
In pass 3, the object output at 6EB0H has already advanced 53AEH: JUMP to 6B47H.
6B43
INC HL 23
Passes 1 and 2: advance the address by one.
6B44
LD (53AEH),HL 22 AE 53
Store it back into 53AEH.
6B47
LD (53B6H),HL 22 B6 53
Store the address into 53B6H, the location counter.
6B4A
XOR A AF
Set Register A to 00H.
6B4B
LD (53B4H),A 32 B4 53
Set the instruction length at 53B4H to 00H so the main loop (64BAH) does not advance the location counter again.
6B4E
LD C,01H 0E 01
Load Register C with 01H.
6B50
GOSUB to 5BBEH for the next character of the string.
6B53
RET Z C8
If the line ended (Z FLAG set), RETURN: the string is complete.
6B54
CP 27H FE 27
Compare the character against 27H (apostrophe). The Z FLAG is set at the closing apostrophe.
6B56
JUMP to 7292H in the appendage: it RETURNs if the Z FLAG is set; otherwise pass 2 goes back to 6B39H and passes 1 and 3 go back to 6B30H with the character.
6B59H - DEFB Directive Handler
Type 16H in the opcode table (dispatch entry 6DD3H). Produces one byte from the operand expression.
6B59
GOSUB to 62A0H to evaluate the operand. Register DE = its value.
6B5C
GOSUB to 6671H, which reports FIELD OVERFLOW (without stopping) when the high byte in Register D is not 00H.
6B5F
LD A,E 7B
Load Register A with the low byte of the value (Register E).
6B60
LD (53B1H),A 32 B1 53
Store it into 53B1H, the instruction byte.
6B63
JUMP to 688DH to set the instruction length to 1 and return.
6B66H - DEFW Directive Handler
Type 17H in the opcode table (dispatch entry 6DD5H). Produces a 16-bit word, low byte first.
6B66
GOSUB to 62A0H to evaluate the operand. Register DE = its value.
6B69
EX DE,HL EB
Move the value into HL.
6B6A
LD (53B1H),HL 22 B1 53
Store it into 53B1H-53B2H: low byte first, then high byte.
6B6D
JUMP to 670BH, which adds 2 to the instruction length at 53B4H and returns.
6B70H - ORG Directive Handler
Type 18H in the opcode table (dispatch entry 6DD7H). Sets the location counter. A label on an ORG line is not allowed.
6B70
INC C 0C
Increment Register C ...
6B71
DEC C 0D
... and decrement it: the Z FLAG is set if Register C = 00H. Register C is non-zero when the line has a label.
6B72
If the ORG line has a label, JUMP to 6533H for BAD LABEL.
6B75
GOSUB to 62A0H to evaluate the operand. Register DE = the new address.
6B78
EX DE,HL EB
Move the address into HL.
6B79
LD (53B6H),HL 22 B6 53
Store it as the location counter in 53B6H.
6B7C
LD (53AEH),HL 22 AE 53
Store it into 53AEH, the address printed on the listing line.
6B80H - End of Text Without END
Reached from 64DAH when the assembler runs out of source lines before an END statement. Reports NO END STATEMENT. Passes 1 and 2 continue with the next pass; pass 3 falls into the END handler so the object file is finished with a transfer address of 0000H.
6B80
LD DE,5A2BH 11 2B 5A
Point DE to the message NO END STATEMENT at 5A2BH.
6B83
GOSUB to 6150H, the error entry that counts the error and (in pass 2) displays the message, then returns.
6B86
LD A,(53C0H) 3A C0 53
Load Register A with the pass number from 53C0H.
6B89
CP 03H FE 03
Compare against 03H.
6B8B
In passes 1 and 2, JUMP to 6427H to start the next pass. Pass 3 continues at 6B8EH. (The END handler also returns here from 6BADH.)
6B8EH - END Directive Handler
Type 19H in the opcode table (dispatch entry 6DD9H). Records the transfer address (the operand, or 0000H if there is none) and lists the line. Passes 1 and 2 then start the next pass. In pass 3 the last object record is written, followed by the 78H transfer record: 78H, address low byte, address high byte. Each byte goes through 710CH, which writes to tape or, when the appendage has a disk object file open, converts the tape format to a /CMD transfer record.
6B8E
POP HL E1
Discard the return address on the stack (6DDFH from the dispatcher, or 6496H when entered from 6B80H).
6B8F
INC C 0C
Increment Register C ...
6B90
DEC C 0D
... and decrement it: the Z FLAG is set if there is no label on the line.
6B91
If the END line has a label, JUMP to 6533H for BAD LABEL.
6B94
GOSUB to 61D6H to classify the operand field; the Z FLAG is set if there is none.
6B97
LD HL,0000H 21 00 00
Load Register HL with 0000H, the transfer address used when END has no operand.
6B9A
If there is no operand, JUMP to 6BA0H.
6B9C
GOSUB to 6293H to evaluate the operand expression. Register DE = its value.
6B9F
EX DE,HL EB
Move the transfer address into HL.
6BA0
LD (53AEH),HL 22 AE 53
Store the transfer address into 53AEH so it appears on the listing line.
6BA3
PUSH HL E5
Save the transfer address on the stack.
6BA4
GOSUB to 6DDFH to check the end of the line and output the listing line.
6BA7
POP HL E1
Restore the transfer address into HL.
6BA8
LD A,(53C0H) 3A C0 53
Load Register A with the pass number from 53C0H.
6BAB
CP 03H FE 03
Compare against 03H.
6BAD
In passes 1 and 2, JUMP to 6B8BH, which jumps to 6427H to start the next pass.
6BAF
LD A,(53BEH) 3A BE 53
Pass 3: load Register A with the record-open flag from 53BEH.
6BB3
If an object record is still open, GOSUB to 6EC3H to write it.
6BB6
LD A,78H 3E 78
Load Register A with 78H, the transfer record marker.
6BB8
GOSUB to 710CH to write the 78H.
6BBB
LD A,L 7D
Load Register A with the low byte of the transfer address (Register L).
6BBC
GOSUB to 710CH to write it.
6BBF
LD A,H 7C
Load Register A with the high byte of the transfer address (Register H).
6BC0
GOSUB to 710CH to write it.
6BC3
JUMP to 58D7H to output a carriage return and return to the command loop. (The disk object file is closed when the command loop calls 71D5H.)
6BC6H - DEFL and EQU Directive Handlers
Two entries. DEFL (type 1BH, dispatch entry 6DDDH) starts at 6BC6H; EQU (type 1AH, dispatch entry 6DDBH) starts at 6BC7H. When a line has a label and a type of 18H or more, the dispatcher at 659EH-65A5H enters the handler with Register A = 01H, so Register B holds 01H for EQU and 02H for DEFL. That is the mode passed to 65A6H: mode 1 defines the symbol, mode 2 also marks it as set by DEFL (bit 5 of its flag byte) so that it can be given a new value later. Both require a label.
6BC6
INC A 3C
DEFL entry: change the mode in Register A from 01H to 02H.
6BC7
LD B,A 47
EQU entry: keep the mode (01H for EQU, 02H for DEFL) in Register B.
6BC8
INC C 0C
Increment Register C (the label length) ...
6BC9
DEC C 0D
... and decrement it: the Z FLAG is set if there is no label.
6BCA
If there is no label, JUMP to 61D0H for MISSING INFORMATION.
6BCD
EX DE,HL EB
Exchange Registers DE and HL before evaluating the operand.
6BCE
GOSUB to 62A0H to evaluate the operand. Register DE = the value.
6BD1
LD A,B 78
Load Register A with the mode from Register B.
6BD2
EX DE,HL EB
Exchange: HL = the value.
6BD3
LD (53AEH),HL 22 AE 53
Store the value into 53AEH, so the listing shows it in the address column.
6BD6
JUMP to 65A6H to define the label with this value (Register A = 01H for EQU or 02H for DEFL).
6BD9H - Mnemonic Table
One entry per mnemonic and directive, in alphabetical order except that END comes before EI: the length byte, the name, the type (the handler number in the dispatch table at 6DA7H) and the base opcode, which 6585H stores at 53B1H. Searched by 627CH from 6563H with Register B = 02H. The table ends with 00H at 6DA6H. Directives have a base of 00H.
6BD9-6BDE
DEFB 03H, 41H, 44H, 43H, 04H, 88H 03 41 44 43 04 88
Mnemonic Table (Data)
"ADC": type 04H (ADC/SBC, 6714H), base 88H.
6BDF-6BE4
DEFB 03H, 41H, 44H, 44H, 05H, 80H 03 41 44 44 05 80
"ADD": type 05H (ADD, 6735H), base 80H.
6BE5-6BEA
DEFB 03H, 41H, 4EH, 44H, 01H, A0H 03 41 4E 44 01 A0
"AND": type 01H (arithmetic and logic, 6654H), base A0H.
6BEB-6BF0
DEFB 03H, 42H, 49H, 54H, 03H, 40H 03 42 49 54 03 40
"BIT": type 03H (bit operation, 667CH), base 40H.
6BF1-6BF7
DEFB 04H, 43H, 41H, 4CH, 4CH, 09H, CDH 04 43 41 4C 4C 09 CD
"CALL": type 09H (CALL, 67BFH), base CDH.
6BF8-6BFD
DEFB 03H, 43H, 43H, 46H, 00H, 3FH 03 43 43 46 00 3F
"CCF": type 00H (no operand, 688DH), base 3FH.
6BFE-6C02
DEFB 02H, 43H, 50H, 01H, B8H 02 43 50 01 B8
"CP": type 01H (arithmetic and logic, 6654H), base B8H.
6C03-6C08
DEFB 03H, 43H, 50H, 44H, 08H, A9H 03 43 50 44 08 A9
"CPD": type 08H (ED group, 67B7H), base A9H.
6C09-6C0F
DEFB 04H, 43H, 50H, 44H, 52H, 08H, B9H 04 43 50 44 52 08 B9
"CPDR": type 08H (ED group, 67B7H), base B9H.
6C10-6C15
DEFB 03H, 43H, 50H, 49H, 08H, A1H 03 43 50 49 08 A1
"CPI": type 08H (ED group, 67B7H), base A1H.
6C16-6C1C
DEFB 04H, 43H, 50H, 49H, 52H, 08H, B1H 04 43 50 49 52 08 B1
"CPIR": type 08H (ED group, 67B7H), base B1H.
6C1D-6C22
DEFB 03H, 43H, 50H, 4CH, 00H, 2FH 03 43 50 4C 00 2F
"CPL": type 00H (no operand, 688DH), base 2FH.
6C23-6C28
DEFB 03H, 44H, 41H, 41H, 00H, 27H 03 44 41 41 00 27
"DAA": type 00H (no operand, 688DH), base 27H.
6C29-6C2E
DEFB 03H, 44H, 45H, 43H, 06H, 05H 03 44 45 43 06 05
"DEC": type 06H (INC/DEC, 677DH), base 05H.
6C2F-6C35
DEFB 04H, 44H, 45H, 46H, 42H, 16H, 00H 04 44 45 46 42 16 00
"DEFB": type 16H (DEFB, 6B59H), base 00H.
6C36-6C3C
DEFB 04H, 44H, 45H, 46H, 4CH, 1BH, 00H 04 44 45 46 4C 1B 00
"DEFL": type 1BH (DEFL, 6BC6H), base 00H.
6C3D-6C43
DEFB 04H, 44H, 45H, 46H, 4DH, 15H, 00H 04 44 45 46 4D 15 00
"DEFM": type 15H (DEFM, 6B1AH), base 00H.
6C44-6C4A
DEFB 04H, 44H, 45H, 46H, 53H, 14H, 00H 04 44 45 46 53 14 00
"DEFS": type 14H (DEFS, 6B0BH), base 00H.
6C4B-6C51
DEFB 04H, 44H, 45H, 46H, 57H, 17H, 00H 04 44 45 46 57 17 00
"DEFW": type 17H (DEFW, 6B66H), base 00H.
6C52-6C56
DEFB 02H, 44H, 49H, 00H, F3H 02 44 49 00 F3
"DI": type 00H (no operand, 688DH), base F3H.
6C57-6C5D
DEFB 04H, 44H, 4AH, 4EH, 5AH, 0DH, 10H 04 44 4A 4E 5A 0D 10
"DJNZ": type 0DH (DJNZ, 6850H), base 10H.
6C5E-6C63
DEFB 03H, 45H, 4EH, 44H, 19H, 00H 03 45 4E 44 19 00
"END": type 19H (END, 6B8EH), base 00H.
6C64-6C68
DEFB 02H, 45H, 49H, 00H, FBH 02 45 49 00 FB
"EI": type 00H (no operand, 688DH), base FBH.
6C69-6C6E
DEFB 03H, 45H, 51H, 55H, 1AH, 00H 03 45 51 55 1A 00
"EQU": type 1AH (EQU, 6BC7H), base 00H.
6C6F-6C73
DEFB 02H, 45H, 58H, 11H, EBH 02 45 58 11 EB
"EX": type 11H (EX, 690FH), base EBH.
6C74-6C79
DEFB 03H, 45H, 58H, 58H, 00H, D9H 03 45 58 58 00 D9
"EXX": type 00H (no operand, 688DH), base D9H.
6C7A-6C80
DEFB 04H, 48H, 41H, 4CH, 54H, 00H, 76H 04 48 41 4C 54 00 76
"HALT": type 00H (no operand, 688DH), base 76H.
6C81-6C85
DEFB 02H, 49H, 4DH, 07H, EDH 02 49 4D 07 ED
"IM": type 07H (IM, 679EH), base EDH.
6C86-6C8A
DEFB 02H, 49H, 4EH, 0FH, DBH 02 49 4E 0F DB
"IN": type 0FH (IN, 6893H), base DBH.
6C8B-6C90
DEFB 03H, 49H, 4EH, 43H, 06H, 04H 03 49 4E 43 06 04
"INC": type 06H (INC/DEC, 677DH), base 04H.
6C91-6C96
DEFB 03H, 49H, 4EH, 44H, 08H, AAH 03 49 4E 44 08 AA
"IND": type 08H (ED group, 67B7H), base AAH.
6C97-6C9D
DEFB 04H, 49H, 4EH, 44H, 52H, 08H, BAH 04 49 4E 44 52 08 BA
"INDR": type 08H (ED group, 67B7H), base BAH.
6C9E-6CA3
DEFB 03H, 49H, 4EH, 49H, 08H, A2H 03 49 4E 49 08 A2
"INI": type 08H (ED group, 67B7H), base A2H.
6CA4-6CAA
DEFB 04H, 49H, 4EH, 49H, 52H, 08H, B2H 04 49 4E 49 52 08 B2
"INIR": type 08H (ED group, 67B7H), base B2H.
6CAB-6CAF
DEFB 02H, 4AH, 50H, 0BH, C3H 02 4A 50 0B C3
"JP": type 0BH (JP, 681AH), base C3H.
6CB0-6CB4
DEFB 02H, 4AH, 52H, 0CH, 18H 02 4A 52 0C 18
"JR": type 0CH (JR, 6839H), base 18H.
6CB5-6CB9
DEFB 02H, 4CH, 44H, 13H, 40H 02 4C 44 13 40
"LD": type 13H (LD, 6980H), base 40H.
6CBA-6CBF
DEFB 03H, 4CH, 44H, 44H, 08H, A8H 03 4C 44 44 08 A8
"LDD": type 08H (ED group, 67B7H), base A8H.
6CC0-6CC6
DEFB 04H, 4CH, 44H, 44H, 52H, 08H, B8H 04 4C 44 44 52 08 B8
"LDDR": type 08H (ED group, 67B7H), base B8H.
6CC7-6CCC
DEFB 03H, 4CH, 44H, 49H, 08H, A0H 03 4C 44 49 08 A0
"LDI": type 08H (ED group, 67B7H), base A0H.
6CCD-6CD3
DEFB 04H, 4CH, 44H, 49H, 52H, 08H, B0H 04 4C 44 49 52 08 B0
"LDIR": type 08H (ED group, 67B7H), base B0H.
6CD4-6CD9
DEFB 03H, 4EH, 45H, 47H, 08H, 44H 03 4E 45 47 08 44
"NEG": type 08H (ED group, 67B7H), base 44H.
6CDA-6CDF
DEFB 03H, 4EH, 4FH, 50H, 00H, 00H 03 4E 4F 50 00 00
"NOP": type 00H (no operand, 688DH), base 00H.
6CE0-6CE4
DEFB 02H, 4FH, 52H, 01H, B0H 02 4F 52 01 B0
"OR": type 01H (arithmetic and logic, 6654H), base B0H.
6CE5-6CEA
DEFB 03H, 4FH, 52H, 47H, 18H, 00H 03 4F 52 47 18 00
"ORG": type 18H (ORG, 6B70H), base 00H.
6CEB-6CF1
DEFB 04H, 4FH, 54H, 44H, 52H, 08H, BBH 04 4F 54 44 52 08 BB
"OTDR": type 08H (ED group, 67B7H), base BBH.
6CF2-6CF8
DEFB 04H, 4FH, 54H, 49H, 52H, 08H, B3H 04 4F 54 49 52 08 B3
"OTIR": type 08H (ED group, 67B7H), base B3H.
6CF9-6CFE
DEFB 03H, 4FH, 55H, 54H, 10H, D3H 03 4F 55 54 10 D3
"OUT": type 10H (OUT, 68CEH), base D3H.
6CFF-6D05
DEFB 04H, 4FH, 55H, 54H, 44H, 08H, ABH 04 4F 55 54 44 08 AB
"OUTD": type 08H (ED group, 67B7H), base ABH.
6D06-6D0C
DEFB 04H, 4FH, 55H, 54H, 49H, 08H, A3H 04 4F 55 54 49 08 A3
"OUTI": type 08H (ED group, 67B7H), base A3H.
6D0D-6D12
DEFB 03H, 50H, 4FH, 50H, 12H, C1H 03 50 4F 50 12 C1
"POP": type 12H (PUSH/POP, 6964H), base C1H.
6D13-6D19
DEFB 04H, 50H, 55H, 53H, 48H, 12H, C5H 04 50 55 53 48 12 C5
"PUSH": type 12H (PUSH/POP, 6964H), base C5H.
6D1A-6D1F
DEFB 03H, 52H, 45H, 53H, 03H, 80H 03 52 45 53 03 80
"RES": type 03H (bit operation, 667CH), base 80H.
6D20-6D25
DEFB 03H, 52H, 45H, 54H, 0AH, C9H 03 52 45 54 0A C9
"RET": type 0AH (RET, 680CH), base C9H.
6D26-6D2C
DEFB 04H, 52H, 45H, 54H, 49H, 08H, 4DH 04 52 45 54 49 08 4D
"RETI": type 08H (ED group, 67B7H), base 4DH.
6D2D-6D33
DEFB 04H, 52H, 45H, 54H, 4EH, 08H, 45H 04 52 45 54 4E 08 45
"RETN": type 08H (ED group, 67B7H), base 45H.
6D34-6D38
DEFB 02H, 52H, 4CH, 02H, 10H 02 52 4C 02 10
"RL": type 02H (CB rotate and shift, 6696H), base 10H.
6D39-6D3E
DEFB 03H, 52H, 4CH, 41H, 00H, 17H 03 52 4C 41 00 17
"RLA": type 00H (no operand, 688DH), base 17H.
6D3F-6D44
DEFB 03H, 52H, 4CH, 43H, 02H, 00H 03 52 4C 43 02 00
"RLC": type 02H (CB rotate and shift, 6696H), base 00H.
6D45-6D4B
DEFB 04H, 52H, 4CH, 43H, 41H, 00H, 07H 04 52 4C 43 41 00 07
"RLCA": type 00H (no operand, 688DH), base 07H.
6D4C-6D51
DEFB 03H, 52H, 4CH, 44H, 08H, 6FH 03 52 4C 44 08 6F
"RLD": type 08H (ED group, 67B7H), base 6FH.
6D52-6D56
DEFB 02H, 52H, 52H, 02H, 18H 02 52 52 02 18
"RR": type 02H (CB rotate and shift, 6696H), base 18H.
6D57-6D5C
DEFB 03H, 52H, 52H, 41H, 00H, 1FH 03 52 52 41 00 1F
"RRA": type 00H (no operand, 688DH), base 1FH.
6D5D-6D62
DEFB 03H, 52H, 52H, 43H, 02H, 08H 03 52 52 43 02 08
"RRC": type 02H (CB rotate and shift, 6696H), base 08H.
6D63-6D69
DEFB 04H, 52H, 52H, 43H, 41H, 00H, 0FH 04 52 52 43 41 00 0F
"RRCA": type 00H (no operand, 688DH), base 0FH.
6D6A-6D6F
DEFB 03H, 52H, 52H, 44H, 08H, 67H 03 52 52 44 08 67
"RRD": type 08H (ED group, 67B7H), base 67H.
6D70-6D75
DEFB 03H, 52H, 53H, 54H, 0EH, C7H 03 52 53 54 0E C7
"RST": type 0EH (RST, 6879H), base C7H.
6D76-6D7B
DEFB 03H, 53H, 42H, 43H, 04H, 98H 03 53 42 43 04 98
"SBC": type 04H (ADC/SBC, 6714H), base 98H.
6D7C-6D81
DEFB 03H, 53H, 43H, 46H, 00H, 37H 03 53 43 46 00 37
"SCF": type 00H (no operand, 688DH), base 37H.
6D82-6D87
DEFB 03H, 53H, 45H, 54H, 03H, C0H 03 53 45 54 03 C0
"SET": type 03H (bit operation, 667CH), base C0H.
6D88-6D8D
DEFB 03H, 53H, 4CH, 41H, 02H, 20H 03 53 4C 41 02 20
"SLA": type 02H (CB rotate and shift, 6696H), base 20H.
6D8E-6D93
DEFB 03H, 53H, 52H, 41H, 02H, 28H 03 53 52 41 02 28
"SRA": type 02H (CB rotate and shift, 6696H), base 28H.
6D94-6D99
DEFB 03H, 53H, 52H, 4CH, 02H, 38H 03 53 52 4C 02 38
"SRL": type 02H (CB rotate and shift, 6696H), base 38H.
6D9A-6D9F
DEFB 03H, 53H, 55H, 42H, 01H, 90H 03 53 55 42 01 90
"SUB": type 01H (arithmetic and logic, 6654H), base 90H.
6DA0-6DA5
DEFB 03H, 58H, 4FH, 52H, 01H, A8H 03 58 4F 52 01 A8
"XOR": type 01H (arithmetic and logic, 6654H), base A8H.
6DA6
DEFB 00H 00
End of the table.
6DA7H - Handler Dispatch Table
28 handler addresses, two bytes each, indexed by the type from the mnemonic table (6588H-6592H). 657CH pushes the selected address as the return address, with 6DDFH (end-of-line check and listing) and 6496H (next line) below it.
6DA7-6DA8
DEFW 688DH 8D 68
Dispatch Table (Data)
Type 00H: no operand (CCF, CPL, DAA, DI, EI, EXX, HALT, NOP, RLA, RLCA, RRA, RRCA, SCF).
6DA9-6DAA
DEFW 6654H 54 66
Type 01H: arithmetic and logic (AND, CP, OR, SUB, XOR).
6DAB-6DAC
DEFW 6696H 96 66
Type 02H: CB rotate and shift (RL, RLC, RR, RRC, SLA, SRA, SRL).
6DAD-6DAE
DEFW 667CH 7C 66
Type 03H: bit operation (BIT, RES, SET).
6DAF-6DB0
DEFW 6714H 14 67
Type 04H: ADC and SBC.
6DB1-6DB2
DEFW 6735H 35 67
Type 05H: ADD.
6DB3-6DB4
DEFW 677DH 7D 67
Type 06H: INC and DEC.
6DB5-6DB6
DEFW 679EH 9E 67
Type 07H: IM.
6DB7-6DB8
DEFW 67B7H B7 67
Type 08H: ED group (CPD, CPDR, CPI, CPIR, IND, INDR, INI, INIR, LDD, LDDR, LDI, LDIR, NEG, OTDR, OTIR, OUTD, OUTI, RETI, RETN, RLD, RRD).
6DB9-6DBA
DEFW 67BFH BF 67
Type 09H: CALL.
6DBB-6DBC
DEFW 680CH 0C 68
Type 0AH: RET.
6DBD-6DBE
DEFW 681AH 1A 68
Type 0BH: JP.
6DBF-6DC0
DEFW 6839H 39 68
Type 0CH: JR.
6DC1-6DC2
DEFW 6850H 50 68
Type 0DH: DJNZ.
6DC3-6DC4
DEFW 6879H 79 68
Type 0EH: RST.
6DC5-6DC6
DEFW 6893H 93 68
Type 0FH: IN.
6DC7-6DC8
DEFW 68CEH CE 68
Type 10H: OUT.
6DC9-6DCA
DEFW 690FH 0F 69
Type 11H: EX.
6DCB-6DCC
DEFW 6964H 64 69
Type 12H: PUSH and POP.
6DCD-6DCE
DEFW 6980H 80 69
Type 13H: LD.
6DCF-6DD0
DEFW 6B0BH 0B 6B
Type 14H: DEFS.
6DD1-6DD2
DEFW 6B1AH 1A 6B
Type 15H: DEFM.
6DD3-6DD4
DEFW 6B59H 59 6B
Type 16H: DEFB.
6DD5-6DD6
DEFW 6B66H 66 6B
Type 17H: DEFW.
6DD7-6DD8
DEFW 6B70H 70 6B
Type 18H: ORG.
6DD9-6DDA
DEFW 6B8EH 8E 6B
Type 19H: END.
6DDB-6DDC
DEFW 6BC7H C7 6B
Type 1AH: EQU.
6DDD-6DDE
DEFW 6BC6H C6 6B
Type 1BH: DEFL.
6DDFH - End of the Line, Then List It
Every opcode handler returns here (657CH pushes 6DDFH under the handler's address). After the operands only spaces, a ; comment or the end of the line may follow; anything else is ILLEGAL ADDRESSING MODE.
6DF0H
Loads Register A with AFH: the listing shows the address.
6DF1H
The second byte of that instruction, so it runs AFH = XOR A: no address. Used for comment lines, empty lines and *L directives (6526H, 6530H).
6DDF
GOSUB to 5BBEH to get the next character. Also called from END at 6BA4H.
6DE2
CP 20H FE 20
Compare it with 20H (space).
6DE4
A space: GOSUB to 5BBBH to skip the spaces.
6DE7
CP 0DH FE 0D
Compare with 0DH (end of line).
6DE9
The line has ended: JUMP to 6DF0H.
6DEB
CP 3BH FE 3B
Compare with 3BH (;).
6DED
Anything else: JUMP to 66E2H for ILLEGAL ADDRESSING MODE.
6DF0
LD A,AFH 3E AF
Load Register A with AFH (non-zero: show the address). 6DF1H is the XOR A entry.
6DF2
LD C,00H 0E 00
Register C = 00H: this is not a DEFM continuation line.
6DF4H - Route the Line by Pass
Register A = 00H (no address) or non-zero (show the address); Register C bit 0 is set for a DEFM continuation line (the call from 6B36H). Pass 1 produces no output and returns. Pass 2 goes through 6EE5H to the listing at 6E03H. Pass 3 goes to the object output at 6E65H.
6DF4
LD B,A 47
Keep the address flag in Register B.
6DF5
LD HL,53C0H 21 C0 53
Point HL to the pass number at 53C0H.
6DF8
LD A,(HL) 7E
Load Register A with the pass number.
6DF9
DEC A 3D
Decrement it.
6DFA
RET Z C8
Pass 1: RETURN.
6DFB
DEC A 3D
Decrement it again.
6DFC
Pass 3: JUMP to 6E65H to add the bytes to the object record.
6DFE
Pass 2: JUMP to 6EE5H, which points HL at 53BDH, loads the NL switch and jumps to 6E03H.
6E01H - Listing Line (Pass 2)
6E01H-6E02H are two NOPs that are never executed. 6E03H is entered from 6EEBH with Register HL = 53BDH (the listing off flag), Register A = the NL switch and Register B = the address flag. It returns without listing when either flag is set. Otherwise it copies the LP switch into the printer flag (53BCH), prints the address from 53AEH-53AFH as four hex digits and a space (6E42H) or five spaces, then the code bytes (the prefix at 53B0H if non-zero, then 53B1H onward, 53B4H bytes in all) padded with spaces to nine characters, and then the source line through 5E4FH. For a DEFM continuation (Register C bit 0 set) only a carriage return is printed after the bytes. The printer flag is cleared at the end.
6E01-6E02
NOP x 2 00 x 2
Unused
Two 00H bytes. The JP 6EE5H at 6DFEH ends before them, and 6EE5H jumps back to 6E03H.
6E03
OR (HL) B6
OR the NL switch with the listing off flag.
6E04
RET NZ C0
Either is set: RETURN without listing.
6E05
LD A,(587EH) 3A 7E 58
Load Register A with the LP switch from 587EH.
6E08
DEC HL 2B
Point HL to 53BCH, the printer flag ...
6E09
LD (HL),A 77
... and copy the LP switch into it, so the line is also printed.
6E0A
EX DE,HL EB
Keep the printer flag address in Register DE.
6E0B
LD HL,53AFH 21 AF 53
Point HL to 53AFH, the high byte of the line address.
6E0E
INC B 04
Increment Register B ...
6E0F
DEC B 05
... and decrement it to test the address flag.
6E10
Show the address: JUMP to 6E42H.
6E12
LD B,05H 06 05
Load Register B with 05H ...
6E14
... and GOSUB to 5D9AH to print a space. Also reached from 6E4CH with Register B = 01H.
6E17
Decrement Register B and LOOP BACK to 6E14H: five spaces in place of the address.
6E19
INC HL 23
Move HL to the prefix byte at 53B0H.
6E1A
LD A,(HL) 7E
Load Register A with it ...
6E1B
OR A B7
... and test it.
6E1C
No prefix: JUMP to 6E1FH, so the loop starts at 53B1H.
6E1E
DEC HL 2B
A prefix: move back one byte, so the loop starts at 53B0H.
6E1F
LD B,09H 06 09
Load Register B with 09H, the width of the code field in characters.
6E21
PUSH BC C5
Save Register BC (Register C bit 0 = the DEFM continuation flag).
6E22
LD A,(53B4H) 3A B4 53
Load Register A with the length from 53B4H ...
6E25
LD C,A 4F
... into Register C.
6E26
INC HL 23
Move to the next code byte.
6E27
DEC C 0D
Count one byte.
6E28
No bytes left (Register C has gone negative): GOSUB to 5D9AH to print a space.
6E2B
A byte is left: GOSUB to 6E4EH to print it as two hex digits (it takes one extra count from Register B).
6E2E
Decrement Register B and LOOP BACK to 6E26H until the nine characters are done.
6E30
LD BC,0001H 01 01 00
Load Register BC with 0001H for 5E4FH.
6E33
LD HL,(5311H) 2A 11 53
Load Register HL with the current source line from 5311H.
6E36
POP AF F1
Restore the saved Register BC into AF: the flags are the old Register C, so the CARRY FLAG = bit 0, the DEFM continuation flag.
6E37
PUSH AF F5
Save it again.
6E38
Not a continuation: GOSUB to 5E4FH to print the line number and the source text.
6E3B
POP AF F1
Restore the flags.
6E3C
EX DE,HL EB
Exchange: HL = 53BCH, the printer flag.
6E3D
LD (HL),B 70
Clear the printer flag (Register B = 00H).
6E3E
A continuation: GOSUB to 5937H to end the output line.
6E42H - Print the Line Address
Entered from 6E10H with Register HL = 53AFH. Prints 53AFH and then 53AEH as four hexadecimal digits and continues at 6E14H with Register B = 01H for one space.
6E42
GOSUB to 6E4EH to print the high byte.
6E45
DEC HL 2B
Move to the low byte at 53AEH ...
6E46
... and GOSUB to 6E4EH to print it.
6E49
INC HL 23
Move back to 53AFH.
6E4A
LD B,01H 06 01
Load Register B with 01H ...
6E4C
... and JUMP to 6E14H to print one space.
6E4EH - Print a Byte as Two Hex Digits
Prints the byte at Register HL as two hexadecimal digits through 5939H. It first decrements Register B, because the code field loop at 6E26H-6E2EH counts two character positions for each byte. 6E58H prints the low four bits of Register A as one digit. Also called from the symbol lister (55C5H, 55C9H).
6E4E
DEC B 05
Count one extra character position.
6E4F
LD A,(HL) 7E
Load Register A with the byte.
6E50
RRCA 0F
Rotate it right ...
6E52
RRCA 0F
... times, moving ...
6E53
RRCA 0F
... the high four bits down.
6E54
GOSUB to 6E58H to print the high digit.
6E57
LD A,(HL) 7E
Load Register A with the byte again for the low digit.
6E58
AND 0FH E6 0F
Keep the low four bits.
6E5A
ADD A,30H C6 30
Add 30H to make 0-9 ...
6E5C
CP 3AH FE 3A
... and compare with 3AH.
6E60
ADD A,07H C6 07
A-F: add 7 more.
6E62
JUMP to 5939H to output the digit.
6E65H - Pass 3: Add the Line's Bytes to the Object Record
Reached from 6DFCH in pass 3. Each byte of the assembled instruction (prefix at 53B0H if non-zero, then 53B1H onward; the count is at 53B4H) is added to an object record kept in memory in cassette SYSTEM-tape form: checksum at 5323H, byte count at 5324H, load address at 5325H-5326H and up to 128 data bytes from 5327H. A byte whose address does not follow the last byte output (531FH), or a 129th byte, first causes the current record to be written by 6EC3H.
6E65
LD BC,53B0H 01 B0 53
Point BC to 53B0H, the prefix byte of the assembled instruction.
6E68
LD A,(53B4H) 3A B4 53
Load Register A with the instruction length from 53B4H.
6E6B
PUSH AF F5
Save the length on the stack.
6E6C
LD A,(BC) 0A
Load Register A with the prefix byte.
6E6E
If there is a prefix, JUMP to 6E71H and output it first.
6E70
INC BC 03
No prefix: point BC to 53B1H, the first opcode byte.
6E71
POP AF F1
Byte Loop
Restore the count of bytes left into Register A.
6E72
DEC A 3D
Count this byte.
6E73
RET M F8
If no bytes are left (the count went negative), RETURN.
6E74
PUSH AF F5
Save the updated count.
6E75
LD HL,(531FH) 2A 1F 53
Load Register HL with the contents of 531FH, the address of the last object byte output.
6E78
INC HL 23
Add one: HL = the address that would continue the current record.
6E79
EX DE,HL EB
Move that address into DE.
6E7A
LD HL,(53AEH) 2A AE 53
Load Register HL with the contents of 53AEH, the address of this byte.
6E7D
LD (531FH),HL 22 1F 53
Store this byte's address into 531FH for the next comparison.
6E80
LD A,(53BEH) 3A BE 53
Load Register A with the record-open flag from 53BEH.
6E84
If no record is open, JUMP to 6E8EH to start one.
6E86
GOSUB to 5DC2H to compare HL (this byte's address) with DE (the continuation address). The Z FLAG is set if they are equal.
6E89
If the byte continues the record, JUMP to 6EA5H to add it.
6E8B
GOSUB to 6EC3H to write the current record (also reached from 6EACH when the record is full).
6E8E
EX DE,HL EB
Start a New Record
Move this byte's address into DE.
6E8F
LD HL,5323H 21 23 53
Point HL to 5323H, the record checksum.
6E92
LD A,E 7B
Load Register A with the address low byte (Register E) ...
6E93
ADD A,D 82
... plus the high byte (Register D).
6E94
LD (HL),A 77
Start the checksum with that sum.
6E95
XOR A AF
Set Register A to 00H.
6E96
INC HL 23
Point HL to 5324H.
6E97
LD (HL),A 77
Set the record byte count to 00H.
6E98
CPL 2F
Register A = FFH.
6E99
LD (53BEH),A 32 BE 53
Store FFH into 53BEH: a record is open.
6E9C
INC HL 23
Point HL to 5325H.
6E9D
LD (HL),E 73
Store the load address low byte.
6E9E
INC HL 23
Point HL to 5326H.
6E9F
LD (HL),D 72
Store the load address high byte.
6EA0
INC HL 23
Point HL to 5327H, where the first data byte goes.
6EA1
LD (5321H),HL 22 21 53
Store 5327H into 5321H, the record write pointer.
6EA4
EX DE,HL EB
Exchange: HL = this byte's address.
6EA5
LD DE,5324H 11 24 53
Add the Byte
Point DE to 5324H, the record byte count.
6EA8
LD A,(DE) 1A
Load Register A with the count.
6EA9
INC A 3C
Add one for this byte.
6EAA
CP 81H FE 81
Compare against 81H (129).
6EAC
If the record already holds 128 bytes, JUMP to 6E8BH to write it and start a new one.
6EAE
LD (DE),A 12
Store the new count.
6EAF
INC HL 23
Advance HL to the address of the next byte.
6EB0
LD (53AEH),HL 22 AE 53
Store it into 53AEH.
6EB3
LD HL,(5321H) 2A 21 53
Load Register HL with the record write pointer from 5321H.
6EB6
LD A,(BC) 0A
Load Register A with the instruction byte at BC.
6EB7
LD (HL),A 77
Store it into the record.
6EB8
INC HL 23
Advance the write pointer.
6EB9
GOSUB to 728BH in the appendage, which stores HL into 5321H (the write pointer) and returns with Register A and the flags unchanged. It also reads the floppy disk controller status register at 37ECH; that value is discarded.
6EBC
INC BC 03
Advance BC to the next instruction byte.
6EBD
EX DE,HL EB
Exchange: HL = 5324H.
6EBE
DEC HL 2B
Point HL to 5323H, the checksum.
6EBF
ADD A,(HL) 86
Add this byte to the checksum ...
6EC0
LD (HL),A 77
... and store the new checksum.
6EC1
LOOP BACK to 6E71H for the next byte.
6EC3H - Write the Object Record
Writes the record built at 5323H-53A6H in cassette SYSTEM-tape form: 3CH, byte count, load address low, load address high, the data bytes, and the checksum. Every byte goes through 710CH: to the cassette, or, when the appendage has a disk object file open, into its tape-to-/CMD converter. Registers BC and HL are preserved.
6EC3
PUSH HL E5
Save Register HL.
6EC4
PUSH BC C5
Save Register BC.
6EC5
LD A,(5324H) 3A 24 53
Load Register A with the record byte count from 5324H.
6EC8
ADD A,04H C6 04
Add 04H: the 3CH marker, the count byte and the two address bytes.
6ECA
LD B,A 47
Register B = the number of bytes to write before the checksum.
6ECB
LD HL,5323H 21 23 53
Point HL to 5323H.
6ECE
LD C,(HL) 4E
Load Register C with the checksum (it is written last).
6ECF
LD A,3CH 3E 3C
Load Register A with 3CH, the record marker.
6ED1
JUMP to 6ED4H so the 3CH is written first.
6ED3
LD A,(HL) 7E
Write Loop
Load Register A with the next record byte.
6ED4
INC HL 23
Advance HL (the first pass moves it from 5323H to 5324H, the count).
6ED5
GOSUB to 710CH to write the byte in Register A.
6ED8
Decrement Register B and LOOP BACK to 6ED3H until the count, address and data bytes have been written.
6EDA
LD A,C 79
Load Register A with the checksum from Register C.
6EDB
GOSUB to 710CH to write it.
6EDE
XOR A AF
Set Register A to 00H.
6EDF
LD (53BEH),A 32 BE 53
Store 00H into 53BEH: no record is open.
6EE2
POP BC C1
Restore Register BC.
6EE3
POP HL E1
Restore Register HL.
6EE5H - Pass 2: Listing Hook
Reached by the JP 6EE5H at 6DFEH in pass 2 (Register HL = 53C0H, Register B = the value passed to 6DF4H). It performs the three DEC HL and the load of the NL switch that the listing routine at 6E03H expects, then jumps there. The two bytes at 6E01H-6E02H (NOP, NOP) that lie between 6DFEH and 6E03H are never executed.
6EE5
DEC HL 2B
Step HL back from 53C0H ...
6EE6
DEC HL 2B
... to 53BFH ...
6EE7
DEC HL 2B
... to 53BDH, the listing off flag.
6EE8
LD A,(5876H) 3A 76 58
Load Register A with the NL (no listing) switch flag from 5876H.
6EEB
JUMP to 6E03H, which ORs in the listing off flag at 53BDH and returns without listing if either is set.
6EEEH - Unreferenced Bytes
Nothing in EDTASM/CMD refers to 6EEEH-6EFFH. The loaded bytes are eleven 00H bytes followed by 54H 49H 4EH 45H 82H 2DH 0EH; the first four are the ASCII letters "TINE". The program entry point 6F00H is the byte after them.
6EEE-6EF8
NOP x 11 00 x 11
Eleven 00H bytes.
6EF9-6EFF
DEFB 54H, 49H, 4EH, 45H, 82H, 2DH, 0EH 54 49 4E 45 82 2D 0E
Seven unreferenced bytes; 54H-45H spell "TINE".
6F00H - Program Entry Point
The transfer address of EDTASM/CMD. It writes a RET opcode over the first byte of the DOS BREAK key vector (4312H-4314H holds a JP instruction), so the BREAK key no longer enters the DOS while the editor/assembler is running, and then starts the editor/assembler at 588AH. The B command (56F8H) puts the JP opcode (C3H) back before returning to the DOS.
6F00
LD A,C9H 3E C9
Load Register A with C9H, the RET opcode.
6F02
LD (4312H),A 32 12 43
Store it at 4312H, the first byte of the DOS BREAK key vector.
6F05
JUMP to 588AH to initialize the editor/assembler and show its banner.
6F08H - L Command (Load Text) Entry
The L entry in the command table at 5B05H points here. Syntax handled by the appendage: L D=filespec loads source text from a disk file; L T=name loads from cassette through the original handler at 5F47H.
6F08
GOSUB to 6F34H to save Registers HL, DE, BC and IX on the stack and point IX at the FCB at 72B6H.
6F0B
GOSUB to 72A7H to show the appendage banner (only the first time).
6F0E
GOSUB to 6F4EH to ask about concatenation if the buffer holds text, then parse the D= or T= parameter and, for D=, open the file. It returns only if the load should continue.
6F11
JUMP to 5F47H, the load handler. With a disk file open, its byte reads go to the disk through 70B6H and 70C6H.
6F14H - W Command (Write Text) Entry
The W entry in the command table points here. W D=filespec writes the text to a disk file; W T=name writes to cassette through the original handler at 5F1FH.
6F14
GOSUB to 6F34H to save the registers and point IX at the FCB at 72B6H.
6F17
GOSUB to 72A7H to show the appendage banner (only the first time).
6F1A
LD A,01H 3E 01
Load Register A with 01H, the file mode for writing text.
6F1C
GOSUB to 6F72H to store the mode in 762DH, parse the D= or T= parameter and, for D=, open or create the file.
6F1F
JUMP to 5F1FH, the write handler. With a disk file open, its byte writes go to the disk through 710CH.
6F22H - A Command: End of Switches
Called at 6410H from the assembler command's switch loop, after 5BBBH has read the next non-space character. If the command line is used up, the appendage takes over (6F27H). Otherwise it returns Z if the character is / (another switch follows) and NZ otherwise (6413H then reports BAD PARAMETER(S)).
6F22
If the command line has ended (Z FLAG set by 5BBBH), JUMP to 6F27H.
6F24
CP 2FH FE 2F
Compare the character against 2FH (/).
6F26
RET C9
RETURN with the Z FLAG set for /.
6F27
POP AF F1
Discard the return address to 6413H.
6F28
GOSUB to 6F34H to save the registers and point IX at the FCB at 72B6H.
6F2B
GOSUB to 72A7H to show the appendage banner (only the first time).
6F2E
GOSUB to 723BH to set file mode 2 and, unless the NO switch was given, ask whether the object code goes to disk or tape (opening the disk file if needed).
6F31
JUMP to 6427H to start assembler pass 1.
6F34H - Save Registers, Point IX at the FCB
Pushes HL, DE, BC and IX under the caller's return address and loads IX with 72B6H, the appendage's File Control Block. The matching exit is 6F3FH, which must be reached with one extra return address on the stack (the routines that end at 6F3FH are always CALLed after a CALL 6F34H).
6F34
EX (SP),HL E3
Exchange HL with the top of the stack: HL = the return address to the caller, and the caller's HL is now saved on the stack.
6F35
PUSH DE D5
Save Register DE.
6F36
PUSH BC C5
Save Register BC.
6F37
PUSH IX DD E5
Save Register IX.
6F39
PUSH HL E5
Push the return address back on top.
6F3A
LD IX,72B6H DD 21 B6 72
Load Register IX with 72B6H, the File Control Block used for all appendage disk files.
6F3E
RET C9
RETURN to the caller.
6F3FH - Restore Registers and Return with A
The common exit of the appendage's disk routines. Returns the value in Register A with the Z FLAG set, and restores HL, DE, BC and IX from the frame built by 6F34H.
6F3F
LD (7631H),A 32 31 76
Save the result in Register A at 7631H.
6F42
POP AF F1
Pop the return address of the routine that jumped here (for example 70D3H) into AF.
6F43
POP IX DD E1
Restore Register IX.
6F45
POP BC C1
Restore Register BC.
6F46
POP DE D1
Restore Register DE.
6F47
POP HL E1
Restore Register HL.
6F48
PUSH AF F5
Push the return address back on the stack.
6F49
XOR A AF
Set the Z FLAG (and clear Register A).
6F4A
LD A,(7631H) 3A 31 76
Reload the result from 7631H into Register A (the flags are not changed).
6F4EH - L: Keep or Clear the Text in the Buffer
Called from 6F0EH. If the text buffer is not empty, asks TEXT IN BUFFER. ARE YOU CONCATENATING???? (Y OR N). Y keeps the text (the loaded file is added after it); N empties the buffer. Then falls into 6F71H with file mode 0 (read).
6F4E
LD HL,(5315H) 2A 15 53
Load Register HL with the end-of-text pointer from 5315H.
6F51
LD DE,(588BH) ED 5B 8B 58
Load Register DE with 7700H, read from the operand of the LD HL,7700H at 588AH (the start of the text buffer).
6F55
GOSUB to 5DC2H to compare HL with DE. The Z FLAG is set if the buffer is empty.
6F58
If the buffer is empty, JUMP to 6F71H.
6F5A
LD HL,755CH 21 5C 75
Ask
Point HL to the message TEXT IN BUFFER. ARE YOU CONCATENATING???? (Y OR N) at 755CH.
6F5D
LD BC,72B6H 01 B6 72
Load Register BC with 72B6H, the buffer that receives the typed reply.
6F60
GOSUB to 727AH to display the question, read a reply line, and return its first character in Register A.
6F63
CP 59H FE 59
Compare the reply against 59H (Y).
6F65
If Y, JUMP to 6F71H and keep the text.
6F67
CP 4EH FE 4E
Compare the reply against 4EH (N).
6F69
Anything else: LOOP BACK to 6F5AH and ask again.
6F6B
LD HL,(588BH) 2A 8B 58
N: load Register HL with 7700H (again read from 588BH).
6F6E
LD (5315H),HL 22 15 53
Store it into 5315H, the end-of-text pointer. The buffer is now empty (the old FFH FFH marker remains at 7700H).
6F71
XOR A AF
Register A = 00H, file mode 0 (read).
6F72H - Parse D=filespec or T=name
Entered with Register A = the file mode: 00H (read, from 6F71H) or 01H (write text, from 6F1CH). Looks at the rest of the command line (pointer at 53A8H, count at 53AAH). The first non-space character and the = after it are replaced by spaces so the original cassette code later sees only the name. D continues at 6FB0H to copy the filespec into the FCB and open the file. T exits through 6F3FH so the original cassette code runs. Anything else is BAD PARAMETER(S).
6F72
LD (762DH),A 32 2D 76
Store the file mode into 762DH.
6F75
LD HL,(53A8H) 2A A8 53
Load Register HL with the input scan pointer from 53A8H (the text after the command letter).
6F78
LD A,(53AAH) 3A AA 53
Load Register A with the number of characters left from 53AAH.
6F7B
LD B,A 47
Keep that count in Register B.
6F7C
LD A,(HL) 7E
Skip Spaces
Load Register A with the character at HL.
6F7D
CP 20H FE 20
Compare it against 20H (space).
6F7F
If it is not a space, JUMP to 6F86H.
6F82
Decrement Register B and LOOP BACK to 6F7CH while characters remain.
6F84
Only spaces were typed: JUMP to 6FAAH for BAD PARAMETER(S).
6F86
LD (HL),20H 36 20
Replace the device letter with a space.
6F89
LD C,A 4F
Keep the device letter in Register C.
6F8A
DEC B 05
One character fewer remains.
6F8B
If nothing follows the letter, JUMP to 6FAAH for the error.
6F8D
LD A,(HL) 7E
Load Register A with the next character.
6F8E
CP 3DH FE 3D
Compare it against 3DH (=).
6F90
If it is not =, JUMP to 6FAAH for the error.
6F92
LD (HL),20H 36 20
Replace the = with a space.
6F94
INC HL 23
Advance HL to the file name.
6F95
DEC B 05
One character fewer remains.
6F96
If nothing follows the =, JUMP to 6FAAH for the error.
6F98
LD A,C 79
Load Register A with the device letter from Register C.
6F99
CP 44H FE 44
Compare it against 44H (D, disk).
6F9B
If D, JUMP to 6FB0H to copy the filespec.
6F9D
CP 54H FE 54
Compare it against 54H (T, tape).
6F9F
If T, JUMP to 6F3FH: restore the registers and return, so the original cassette handler continues with the name.
6FA1
Any other letter: JUMP to 6FAAH for the error.
6FA3
LD A,(HL) 7E
Copy One Filespec Character
Load Register A with the character at HL.
6FA5
LD (DE),A 12
Store the character into the FCB area at DE.
6FA7
CP 20H FE 20
Compare the character against 20H (space).
6FA9
RET NZ C0
If it is not a space, RETURN. A space inside the filespec falls through to the error exit below.
6FAA
Error Exit
GOSUB to 72A0H to clear the output-to-file flag at 53BAH (Register A is preserved).
6FAD
JUMP to 5D24H to display BAD PARAMETER(S) and return to the command loop (58DAH resets the stack).
6FB0
LD DE,72B6H 11 B6 72
Copy the Filespec (D=)
Point DE to 72B6H, the FCB. The filespec is copied into it for the DOS open call.
6FB3
LD C,06H 0E 06
Load Register C with 06H, the number of name characters to copy before the extension part.
6FB5
GOSUB to 6FA3H to copy one character (a space is an error).
6FB8
CP 30H FE 30
Compare the character against 30H (0).
6FBA
Below 0 (for example / or .): JUMP to 6FD1H.
6FBC
CP 3AH FE 3A
Compare against 3AH.
6FBE
A digit: JUMP to 6FC8H.
6FC0
CP 41H FE 41
Compare against 41H (A).
6FC2
3AH-40H (for example :): JUMP to 6FD1H.
6FC4
CP 5BH FE 5B
Compare against 5BH.
6FC6
Above Z: JUMP to 6FD1H.
6FC8
A letter or digit: decrement the characters remaining (Register B); if some remain, JUMP to 6FCCH.
6FCA
The line has ended: JUMP to 6FE1H to terminate the filespec.
6FCC
DEC C 0D
Decrement the name character count in Register C.
6FCD
If fewer than six have been copied, LOOP BACK to 6FB5H.
6FCF
Six name characters copied: JUMP to 6FD3H.
6FD1
DEC HL 2B
A separator: step HL back ...
6FD2
DEC DE 1B
... and DE back, so the separator is copied again by the loop below.
6FD3
LD A,(53AAH) 3A AA 53
Load Register A with the count at 53AAH.
6FD6
SUB B 90
Subtract the characters still unread (Register B).
6FD7
LD (53AAH),A 32 AA 53
Store the result back into 53AAH.
6FDA
LD C,0FH 0E 0F
Load Register C with 0FH (15), the most characters allowed after the name.
6FDC
Copy the Rest
GOSUB to 6FA3H to copy one character (a space is an error).
6FDF
Decrement the characters remaining (Register B); if some remain, JUMP to 6FE6H.
6FE1
LD A,0DH 3E 0D
The line has ended: load Register A with 0DH ...
6FE3
LD (DE),A 12
... and store it after the filespec in the FCB as its terminator.
6FE4
JUMP to 6FF4H to open the file.
6FE6
DEC C 0D
Decrement the character limit in Register C.
6FE7
If the limit is not reached, LOOP BACK to 6FDCH.
6FE9
More than 15 characters after the name: JUMP to 6FAAH for the error.
6FEB
File Exists
GOSUB to 727AH to display FILE ALREADY EXISTS. USE IT???? (Y OR N) (Register HL = 75CCH) and read the reply into 72E8H (Register BC).
6FEE
CP 59H FE 59
Compare the reply against 59H (Y).
6FF0
If Y, JUMP to 703EH: the opened file will be overwritten.
6FF2
Otherwise JUMP to 6FAAH, which ends the command with BAD PARAMETER(S).
6FF4
LD DE,72B6H 11 B6 72
Open the File
Point DE to 72B6H, the FCB. Also entered from 726CH for the object file.
6FF7
LD HL,72E8H 21 E8 72
Point HL to 72E8H, the 512-byte disk buffer.
6FFA
LD (7658H),HL 22 58 76
Store 72E8H into 7658H, the buffer position pointer.
6FFD
LD (765AH),HL 22 5A 76
Store 72E8H into 765AH, the buffer end. With both equal the buffer is empty.
7000
LD B,00H 06 00
Load Register B with 00H, the logical record length (256).
7002
LD A,(762DH) 3A 2D 76
Load Register A with the file mode from 762DH.
7006
Mode 0 (read): JUMP to 7038H to open an existing file.
7008
INC H 24
Write: advance H ...
7009
INC H 24
... twice: HL = 74E8H, the end of the two-sector buffer.
700A
LD (765AH),HL 22 5A 76
Store 74E8H into 765AH: bytes are collected until the buffer holds 512.
700D
LD HL,72E8H 21 E8 72
Point HL back to 72E8H, the buffer for the DOS call.
7010
GOSUB to the DOS at 4424H to OPEN the existing file (DE = FCB, HL = buffer, B = record length). The Z FLAG is set if it was found and opened.
7013
LD HL,75CCH 21 CC 75
Point HL to the message FILE ALREADY EXISTS. USE IT???? (Y OR N) at 75CCH, for 6FEBH.
7016
LD BC,72E8H 01 E8 72
Load Register BC with 72E8H, where 727AH puts the reply.
7019
If the file exists, JUMP to 6FEBH to ask whether to use it.
701B
CP 18H FE 18
Compare the DOS error code in Register A against 18H (file not in directory).
701D
Any other error: JUMP to 726FH to display it.
7020
LD HL,7591H 21 91 75
Point HL to the message ************** FILE NON-EXISTENT. REPLY "C" TO CREATE IT at 7591H.
7023
GOSUB to 727AH to display it and read the reply.
7026
CP 43H FE 43
Compare the reply against 43H (C).
7028
Anything else: JUMP to 6FAAH, ending the command with BAD PARAMETER(S).
702B
LD DE,72B6H 11 B6 72
Point DE to 72B6H, the FCB.
702E
LD HL,72E8H 21 E8 72
Point HL to 72E8H, the buffer.
7031
LD B,00H 06 00
Load Register B with 00H, the record length (256).
7033
GOSUB to the DOS at 4420H to create (INIT) the file.
7036
JUMP to 703BH to check the result.
7038
Read mode: GOSUB to the DOS at 4424H to OPEN the existing file.
703B
If the DOS reported an error, JUMP to 726FH to display it.
703E
LD HL,762CH 21 2C 76
Point HL to 762CH, the disk-file-active flag.
7041
LD (HL),01H 36 01
Set it to 01H: byte input and output now go to the disk file.
7043
JUMP to 6F3FH to restore the registers and return.
7046H - Show a Cassette Prompt Unless a Disk File Is Open
Called from 586EH with HL pointing to READY CASSETTE. For cassette it displays the message and returns to 5871H, which waits for a key. For disk it drops its own return address and returns straight to the caller of 586BH, so there is no prompt and no wait.
7046
LD A,(762CH) 3A 2C 76
Load Register A with the disk-file-active flag from 762CH.
704A
No disk file: JUMP to 592FH to display the message at HL; 592FH returns to 5871H.
704D
POP AF F1
Disk file active: discard the return address to 5871H.
704E
RET C9
RETURN to the caller of 586BH.
704FH - Header Name Compare Setup for L
Called at 5F63H with Register A = the length of the name typed after L T=. The load code compares that many header characters with the name and then skips the rest of the header. For a disk file the compare count is set to zero so any name in the file header is accepted.
704F
LD C,A 4F
Copy the name length into Register C, the number of header characters to compare.
7050
LD B,07H 06 07
Load Register B with 07H.
7052
LD A,(762CH) 3A 2C 76
Load Register A with the disk-file-active flag from 762CH.
7056
RET Z C8
Cassette: RETURN with Register C = the name length.
7057
LD C,00H 0E 00
Disk: Register C = 00H, so no header characters are compared.
705AH - Down Arrow Command
The down arrow (0AH) entry of the command table points here. It sends 1BH (the video code that moves the cursor up one line) through the ROM display routine at 0033H, then jumps into the up/down arrow line display at 5E74H. 5E74H is the second byte of the LD B,AFH at 5E73H, so it runs AFH = XOR A (NO CARRY), which selects the next line instead of the previous one.
705A
LD A,1BH 3E 1B
Load Register A with 1BH, the cursor-up video code.
705C
GOSUB to the Level II ROM display routine at 0033H to output it.
705F
JUMP to 5E74H to display the next line.
7062H - Convert Lower Case to Upper Case
Called from 5849H with a key code of 1AH or more in Register A. Codes below 61H are returned unchanged; 61H-7AH (a-z) are returned as 41H-5AH (A-Z). For 7BH-7FH the routine does not return: it jumps back to the key loop at 5836H to wait for another key.
7062
CP 61H FE 61
Compare the key against 61H (a).
7064
RET C D8
Below a: RETURN with the key unchanged.
7065
SUB 20H D6 20
Subtract 20H to make the upper case code.
7067
CP 5BH FE 5B
Compare against 5BH.
7069
RET C D8
A letter A-Z: RETURN with it.
706A
Codes 7BH-7FH: JUMP to 5836H to wait for another key.
706DH - Cassette Read Start (Skipped for Disk)
Called at 5F53H before a load. For cassette it turns interrupts off and jumps to the ROM routine at 0293H, which starts the cassette and finds the leader and sync byte. For disk it returns at once.
706D
LD A,(762CH) 3A 2C 76
Load Register A with the disk-file-active flag from 762CH.
7071
RET NZ C0
Disk file active: RETURN.
7072
GOSUB to 7085H (a RET, see below).
7075
DI F3
Disable interrupts for the cassette timing loops.
7076
JUMP to the Level II ROM at 0293H to read the cassette leader and sync byte.
7079H - Cassette Write Start (Skipped for Disk)
Called at 6130H before a file header is written. For cassette it turns interrupts off and jumps to the ROM routine at 0284H, which starts the cassette and writes the leader and sync byte. For disk it returns at once.
7079
LD A,(762CH) 3A 2C 76
Load Register A with the disk-file-active flag from 762CH.
707D
RET NZ C0
Disk file active: RETURN.
707E
GOSUB to 7085H (a RET).
7081
DI F3
Disable interrupts for the cassette timing loops.
7082
JUMP to the Level II ROM at 0284H to write the cassette leader and sync byte.
7085
RET C9
A lone RET, called from 7072H and 707EH. It does nothing.
7086H - Blink the Load Indicator
Called at 5FA2H once for each line loaded. Changes the character at 3C3FH (top line of the screen) between 2AH (*) and 20H (space), the way the ROM cassette routines blink an asterisk there; it runs for disk loads as well.
7086
LD A,(3C3FH) 3A 3F 3C
Load Register A with the character on the screen at 3C3FH.
7089
XOR 0AH EE 0A
Exclusive-OR with 0AH: 2AH becomes 20H and 20H becomes 2AH.
708B
LD (3C3FH),A 32 3F 3C
Store it back on the screen.
708FH - Display Free Memory and Return the NS Flag
Called at 644EH after pass 2. Displays the number of bytes between the end of the text and the bottom of the symbol table, followed by TEXT AREA BYTES LEFT, then returns Register A = the NS switch flag from 5882H.
708F
LD HL,(53C3H) 2A C3 53
Load Register HL with the bottom of the symbol table from 53C3H.
7092
LD DE,(5315H) ED 5B 15 53
Load Register DE with the end-of-text pointer from 5315H.
7096
OR A B7
Clear the CARRY FLAG.
7097
SBC HL,DE ED 52
HL = the number of free bytes between them.
7099
LD DE,5D75H 11 75 5D
Load Register DE with 5D75H, the routine that displays HL as a 5-digit decimal number.
709C
GOSUB to 6182H to display the number (and print it when the LP switch is set).
709F
LD HL,7616H 21 16 76
Point HL to the message TEXT AREA BYTES LEFT at 7616H.
70A2
GOSUB to 617FH to display the message (and print it when LP is set).
70A5
LD A,(5882H) 3A 82 58
Load Register A with the NS switch flag from 5882H.
70A9H - Store the Object Record Pointer and Read the FDC Status
70A9H is reached only from 728CH, which the object output calls at 6EB9H. 70ACH is also called from 71A5H. The status value is discarded by both callers.
70A9
LD (5321H),HL 22 21 53
Store HL into 5321H, the object record write pointer.
70AC
LD A,(37ECH) 3A EC 37
Read the floppy disk controller status register at 37ECH.
70AF
AND 80H E6 80
Keep bit 7 (the not-ready bit).
70B2
LD (37E1H),A 32 E1 37
Store Register A into 37E1H, the Model I disk drive select latch. Unreferenced: nothing in EDTASM/CMD calls 70B2H.
70B6H - L: Read the Header Byte
Called at 5F56H in the load code, which looks for the D3H byte that starts a source file. For cassette it reads bytes (70C6H) until the load code finds D3H. For disk it reads the first byte: if it is D3H it returns normally; otherwise it goes straight to the line reader at 5F79H with that byte, so a disk file without a header is accepted.
70B6
LD A,(762CH) 3A 2C 76
Load Register A with the disk-file-active flag from 762CH.
70BA
Cassette: JUMP to 70C6H to read a byte from the tape.
70BC
Disk: GOSUB to 70C6H to read the first byte of the file.
70BF
CP D3H FE D3
Compare it against D3H, the source file header byte.
70C1
RET Z C8
A header: RETURN to 5F59H, which checks for D3H and continues with the name.
70C2
POP BC C1
No header: discard the return address to 5F59H.
70C3
JUMP to 5F79H to treat the byte as the start of the text.
70C6H - Read One Byte (Tape or Disk)
Replaces the ROM cassette read. Returns the next byte in Register A. For cassette it jumps to the ROM at 0235H; for disk it reads from the buffer through 70D4H with all other registers preserved.
70C6
LD A,(762CH) 3A 2C 76
Load Register A with the disk-file-active flag from 762CH.
70CA
Cassette: JUMP to the Level II ROM at 0235H to read a byte from the tape.
70CD
Disk: GOSUB to 6F34H to save the registers and point IX at the FCB.
70D0
GOSUB to 70D4H to fetch the byte; it ends at 6F3FH.
70D3
RET C9
RETURN with the byte in Register A.
70D4H - Fetch a Byte from the Disk Buffer
Returns the next byte from the 512-byte buffer at 72E8H, reading two more sectors when it is used up. Register IX = 72B6H, the FCB. Exits through 6F3FH.
70D4
LD HL,(7658H) 2A 58 76
Load Register HL with the buffer position from 7658H.
70D7
LD A,(765AH) 3A 5A 76
Load Register A with the low byte of the buffer end from 765AH.
70DA
CP L BD
Compare it with the low byte of the position.
70DB
If different, bytes remain: JUMP to 7104H.
70DD
LD A,(765BH) 3A 5B 76
Load Register A with the high byte of the buffer end from 765BH.
70E0
CP H BC
Compare it with the high byte of the position.
70E1
If different, bytes remain: JUMP to 7104H.
70E3
LD DE,72B6H 11 B6 72
Refill the Buffer
Point DE to 72B6H, the FCB.
70E6
GOSUB to the DOS at 4436H to READ the next sector into 72E8H.
70E9
If the read failed, JUMP to 726FH to display the DOS error.
70EC
INC (IX+04H) DD 34 04
Add 1 to FCB+04H, the high byte of the FCB's buffer address, so the next sector goes to 73E8H.
70EF
GOSUB to the DOS at 4436H to READ the following sector into 73E8H.
70F2
LD HL,74E8H 21 E8 74
Load Register HL with 74E8H, the buffer end when both sectors were read.
70F5
If the second read succeeded, JUMP to 70FBH.
70F7
DEC H 25
The second read failed (for example at the end of the file): the buffer end is 73E8H ...
70F8
DEC (IX+0AH) DD 35 0A
... and FCB+0AH, the low byte of the next record number, is decreased by 1.
70FB
LD (765AH),HL 22 5A 76
Store the buffer end into 765AH.
70FE
DEC (IX+04H) DD 35 04
Subtract 1 from FCB+04H: the FCB buffer address is 72E8H again.
7101
LD HL,72E8H 21 E8 72
Load Register HL with 72E8H, the start of the refilled buffer.
7104
LD A,(HL) 7E
Return the Byte
Load Register A with the byte at the buffer position.
7105
INC HL 23
Advance the position.
7106
LD (7658H),HL 22 58 76
Store it back into 7658H.
7109
JUMP to 6F3FH to restore the registers and return the byte.
710CH - Write One Byte (Tape or Disk)
Replaces the ROM cassette write. Every byte that EDTASM sends to tape comes here: the source text during W (5F41H and 5939H), the file headers (6135H-6144H), and the object code (6BB8H-6BC0H, 6ED5H, 6EDBH). For cassette it jumps to the ROM at 0264H. For disk it saves the registers and passes the byte to 711FH.
710C
PUSH AF F5
Save the byte (Register A) and the flags.
710D
LD A,(762CH) 3A 2C 76
Load Register A with the disk-file-active flag from 762CH.
7111
Disk file active: JUMP to 7117H.
7113
POP AF F1
Cassette: restore the byte.
7114
JUMP to the Level II ROM at 0264H to write it to tape.
7117
POP AF F1
Restore the byte into Register A.
7118
GOSUB to 6F34H to save the registers and point IX at the FCB.
711B
GOSUB to 711FH to store the byte; it ends at 6F3FH.
711FH - Store a Byte, Converting Object Code to /CMD Format
Register A = the byte. In file mode 1 (text) the byte is stored unchanged. In file mode 2 (object code) the cassette SYSTEM-tape stream from EDTASM is converted, one byte at a time, into DOS load-module (/CMD) records. 762FH holds the state and 7630H a count:
Bit 0
Skip bytes. Set with a count of 7 by 7262H-7269H to drop the 55H header byte and the six-character name; later set with a count of 1 to drop a record checksum.
Bit 1
Expect a record type. 3CH (data record) is written as 01H (load record); 78H (transfer record) is written as 02H, 02H.
Bit 2
Expect the data record's byte count. It is written increased by 2, because a /CMD load record's length includes the two address bytes.
Bit 7
Copy the address and data bytes.
Bit 6
Copy the two transfer address bytes.
A byte that does not fit the current state stops with INTERNAL ERROR.
711F
LD B,A 47
Keep the byte in Register B.
7120
LD A,(762DH) 3A 2D 76
Load Register A with the file mode from 762DH.
7123
CP 02H FE 02
Compare against 02H.
7125
Mode 1 (text): JUMP to 71A2H to store the byte unchanged.
7128
LD HL,762FH 21 2F 76
Point HL to 762FH, the conversion state flags.
712B
LD A,(7630H) 3A 30 76
Load Register A with the state count from 7630H.
712E
BIT 0,(HL) CB 46
Test bit 0 (skip bytes).
7130
If not skipping, JUMP to 713FH.
7132
DEC A 3D
Count this skipped byte.
7133
LD (7630H),A 32 30 76
Store the new count into 7630H.
7136
If more bytes are to be skipped, JUMP to 713CH.
7138
RES 0,(HL) CB 86
Done skipping: clear bit 0 ...
713A
SET 1,(HL) CB CE
... and set bit 1: the next byte is a record type.
713C
JUMP to 6F3FH: the byte is dropped.
713F
BIT 7,(HL) CB 7E
Test bit 7 (copy address and data bytes).
7141
If not copying, JUMP to 7151H.
7143
DEC A 3D
Count this byte.
7144
If more bytes remain, JUMP to 714BH to store the count and copy the byte.
7146
RES 7,(HL) CB BE
Last data byte: clear bit 7 ...
7148
SET 0,(HL) CB C6
... set bit 0 ...
714A
INC A 3C
... and make the count 1, so the record's checksum byte that follows is dropped.
714B
LD (7630H),A 32 30 76
Store the count into 7630H.
714E
JUMP to 71A2H to store the byte in Register B.
7151
BIT 6,(HL) CB 76
Test bit 6 (transfer address).
7153
If not, JUMP to 715CH.
7155
DEC A 3D
Count this address byte.
7156
If the second byte is still to come, JUMP to 714BH to store the count and copy this one.
7158
RES 6,(HL) CB B6
Second address byte: clear bit 6.
715A
JUMP to 714BH to copy it.
715C
BIT 1,(HL) CB 4E
Test bit 1 (record type expected).
715E
If not, JUMP to 7184H.
7160
LD A,B 78
Load Register A with the byte.
7161
CP 3CH FE 3C
Compare it against 3CH, the data record marker.
7163
If not 3CH, JUMP to 716EH.
7165
RES 1,(HL) CB 8E
Data record: clear bit 1 ...
7167
SET 2,(HL) CB D6
... and set bit 2: the count byte is next.
7169
LD B,01H 06 01
Load Register B with 01H, the /CMD load record type.
716B
JUMP to 71A2H to store the 01H in place of the 3CH.
716E
CP 78H FE 78
Compare the byte against 78H, the transfer record marker.
7170
Anything else: JUMP to 7199H for INTERNAL ERROR.
7172
LD A,02H 3E 02
Load Register A with 02H.
7174
LD B,A 47
Register B = 02H, the /CMD transfer record type.
7175
LD (7630H),A 32 30 76
Store 02H into 7630H: two address bytes follow.
7178
RES 1,(HL) CB 8E
Clear bit 1 ...
717A
SET 6,(HL) CB F6
... and set bit 6: copy the transfer address.
717C
GOSUB to 71ABH to store the 02H type byte.
717F
LD B,02H 06 02
Load Register B with 02H, the record length (two address bytes).
7181
JUMP to 71A2H to store it.
7184
BIT 2,(HL) CB 56
Test bit 2 (count byte expected).
7186
If not, JUMP to 7199H for INTERNAL ERROR.
7188
LD A,B 78
Load Register A with the tape record's byte count.
7189
ADD A,02H C6 02
Add 2 for the two address bytes.
718B
LD B,A 47
Register B = the /CMD record length.
718C
A count of FEH makes 00H (256 bytes): JUMP to 7193H.
718E
CP 03H FE 03
Compare the length against 03H.
7190
A tape count of 00H or FFH gives a length below 3: JUMP to 7199H for INTERNAL ERROR.
7193
RES 2,(HL) CB 96
Clear bit 2 ...
7195
SET 7,(HL) CB FE
... and set bit 7: copy the address and data bytes.
7197
JUMP to 714BH to store the length as the count and write it.
7199
Internal Error
GOSUB to 72A0H to clear the output-to-file flag.
719C
LD HL,754DH 21 4D 75
Point HL to the message INTERNAL ERROR at 754DH.
719F
JUMP to 592BH to display it and return to the command loop.
71A2
Store Register B
GOSUB to 71ABH to put the byte in the buffer (writing the buffer when it is full).
71A5
GOSUB to 70ACH, which reads the disk controller status; the value is not used.
71A8
JUMP to 6F3FH to restore the registers and return.
71ABH - Put a Byte in the Disk Buffer
Stores Register B at the buffer position (7658H). When the buffer reaches 74E8H (512 bytes), both sectors are written with the DOS WRITE call and the position goes back to 72E8H.
71AB
LD HL,(7658H) 2A 58 76
Load Register HL with the buffer position from 7658H.
71AE
LD (HL),B 70
Store the byte from Register B.
71AF
INC HL 23
Advance the position.
71B0
LD (7658H),HL 22 58 76
Store the position into 7658H.
71B3
LD DE,(765AH) ED 5B 5A 76
Load Register DE with the buffer end from 765AH.
71B7
OR A B7
Clear the CARRY FLAG.
71B8
SBC HL,DE ED 52
Compare the position with the end.
71BA
RET NZ C0
Not full: RETURN.
71BB
LD DE,72B6H 11 B6 72
Point DE to 72B6H, the FCB.
71BE
GOSUB to the DOS at 4439H to WRITE the first sector from 72E8H.
71C1
If the write failed, JUMP to 726FH.
71C4
INC (IX+04H) DD 34 04
Add 1 to FCB+04H so the FCB buffer address is 73E8H.
71C7
GOSUB to the DOS at 4439H to WRITE the second sector.
71CA
If the write failed, JUMP to 726FH.
71CD
DEC (IX+04H) DD 35 04
Subtract 1 from FCB+04H: the buffer address is 72E8H again.
71D0
LD HL,72E8H 21 E8 72
Load Register HL with 72E8H.
71D3
JUMP to 71B0H to store it as the position (the compare then gives NZ and the routine returns).
71D5H - Close the Disk File on Return to the Command Loop
Called at 58DDH every time the command loop starts (after each command, error or BREAK). With no disk file open it jumps to 5708H (clear the error flag, turn the cassette off). Otherwise 71E4H writes any buffered bytes and closes the file.
71D5
EI FB
Enable interrupts (the cassette routines leave them off).
71D6
LD A,(762CH) 3A 2C 76
Load Register A with the disk-file-active flag from 762CH.
71DA
No disk file: JUMP to 5708H.
71DD
GOSUB to 6F34H to save the registers and point IX at the FCB.
71E0
GOSUB to 71E4H to finish the file; it ends at 6F3FH.
71E4H - Finish and Close the Disk File
After a DOS error (762EH non-zero) or a read (mode 0) the flags are simply cleared. After writing, the bytes left in the buffer are written (the last sector with its byte count in FCB+05H), the file is read back from the start until the DOS reports end of file, and then it is closed.
71E4
LD A,(762EH) 3A 2E 76
Load Register A with the DOS error flag from 762EH.
71E8
After a DOS error: JUMP to 7231H and only clear the flags.
71EA
LD A,(762DH) 3A 2D 76
Load Register A with the file mode from 762DH.
71EE
Read mode: JUMP to 7231H.
71F0
LD DE,72B6H 11 B6 72
Point DE to 72B6H, the FCB.
71F3
LD HL,(7658H) 2A 58 76
Load Register HL with the buffer position from 7658H.
71F6
LD BC,72E8H 01 E8 72
Load Register BC with 72E8H, the start of the buffer.
71F9
OR A B7
Clear the CARRY FLAG.
71FA
SBC HL,BC ED 42
HL = the number of bytes in the buffer (0-511).
71FC
Empty: JUMP to 7217H.
71FE
DEC H 25
Decrement H: it becomes 00H only if there are 256 or more bytes.
71FF
Fewer than 256 bytes: JUMP to 720EH.
7203
Exactly 256 bytes: JUMP to 720EH and write the first sector as the last one.
7205
257-511 bytes: GOSUB to the DOS at 4439H to WRITE the full first sector.
7208
If the write failed, JUMP to 726FH.
720B
INC (IX+04H) DD 34 04
Add 1 to FCB+04H so the second sector is written from 73E8H.
720E
LD (IX+05H),L DD 75 05
Store Register L, the number of bytes used in the last sector (00H = all 256), into FCB+05H.
7211
GOSUB to the DOS at 4439H to WRITE the last sector.
7214
If the write failed, JUMP to 726FH.
7217
GOSUB to the DOS at 443FH to position the file at its first record.
721A
If that failed, JUMP to 726FH.
721D
Read-Back Loop
GOSUB to the DOS at 4436H to READ the next sector.
7220
While the reads succeed, LOOP BACK to 721DH.
7222
CP 1CH FE 1C
Compare the error code against 1CH (end of file encountered).
7224
End of file: JUMP to 722BH.
7226
CP 1DH FE 1D
Compare the error code against 1DH (record number out of range).
7228
Any other error: JUMP to 726FH.
722B
GOSUB to the DOS at 4428H to CLOSE the file.
722E
If the close failed, JUMP to 726FH.
7231
XOR A AF
Set Register A to 00H.
7232
LD (762CH),A 32 2C 76
Clear the disk-file-active flag at 762CH: byte input and output go to the cassette again.
7235
LD (762EH),A 32 2E 76
Clear the DOS error flag at 762EH.
7238
JUMP to 6F3FH to restore the registers and return.
723BH - A: Object Code to Disk or Tape
Called from 6F2EH. Sets file mode 2. Unless the NO switch was given, asks OBJECT FILE TO DISK OR TAPE? (D OR T). T leaves the object code going to cassette. D asks OBJECT FILESPEC?, reads the filespec straight into the FCB, arms the /CMD converter to skip the 7-byte tape header, and opens or creates the file through 6FF4H.
723B
LD A,02H 3E 02
Load Register A with 02H, the file mode for object code.
723D
LD (762DH),A 32 2D 76
Store it into 762DH.
7240
LD A,(587AH) 3A 7A 58
Load Register A with the NO switch flag from 587AH.
7244
NO given: JUMP to 6F3FH; no object code is written.
7247
LD HL,7513H 21 13 75
Point HL to the message OBJECT FILE TO DISK OR TAPE? (D OR T) at 7513H.
724A
LD BC,72B6H 01 B6 72
Load Register BC with 72B6H, where the reply is typed.
724D
GOSUB to 727AH to display the question and read the reply.
7250
CP 54H FE 54
Compare the reply against 54H (T).
7255
CP 44H FE 44
Compare the reply against 44H (D).
7257
Anything else: LOOP BACK to 7247H and ask again.
7259
LD HL,753BH 21 3B 75
Point HL to the message OBJECT FILESPEC? at 753BH.
725C
LD BC,72B6H 01 B6 72
Load Register BC with 72B6H: the filespec is typed directly into the FCB.
725F
GOSUB to 727AH to display the prompt and read the filespec (the ROM line input ends it with 0DH).
7262
LD A,07H 3E 07
Load Register A with 07H ...
7264
LD (7630H),A 32 30 76
... and store it into 7630H: 7 bytes (55H and the six-character name) will be skipped.
7267
LD A,01H 3E 01
Load Register A with 01H ...
7269
LD (762FH),A 32 2F 76
... and store it into 762FH: conversion state bit 0 (skip bytes).
726C
JUMP to 6FF4H to open or create the file.
726FH - DOS Error Handler
Reached from every appendage DOS call that returns NZ, with Register A = the DOS error code. Sets the DOS error flag (so 71E4H will not try to finish the file), sets bits 7 and 6 of the code, calls the DOS error display at 4409H and, when it returns, jumps to the command loop.
726F
LD (762EH),A 32 2E 76
Store the error code into 762EH, the DOS error flag.
7272
OR C0H F6 C0
Set bits 7 and 6 of the error code.
7274
GOSUB to the DOS at 4409H to display the error.
7277
JUMP to 58DAH, the command loop (which calls 71D5H and clears the flags).
727AH - Display a Prompt and Read a Reply
Register HL = the prompt message (bit-7 terminated), Register BC = where the reply goes. Displays the prompt, reads a line of up to 31 characters with the ROM line input at 0040H, and returns the first character typed in Register A. BREAK goes back to the command loop. Register DE is preserved.
727A
PUSH DE D5
Save Register DE.
727B
PUSH BC C5
Save the reply buffer address (Register BC).
727C
GOSUB to 592FH to display the prompt at HL (followed by a carriage return).
727F
POP HL E1
Load Register HL with the reply buffer address.
7280
LD B,1FH 06 1F
Load Register B with 1FH (31), the most characters that can be typed.
7282
GOSUB to the Level II ROM line input at 0040H (Register HL = buffer, Register B = maximum). The CARRY FLAG is set if BREAK was pressed.
7285
BREAK: JUMP to 58D7H, a carriage return and the command loop.
7288
POP DE D1
Restore Register DE.
7289
LD A,(HL) 7E
Load Register A with the first character of the reply.
728BH - Object Record Pointer Hook
Called at 6EB9H in place of a store into 5321H. Keeps Register A and the flags.
728B
PUSH AF F5
Save Register A and the flags.
728C
GOSUB to 70A9H to store HL into 5321H (and read the disk controller status).
728F
POP AF F1
Restore Register A and the flags.
7291
RET C9
A RET that nothing in EDTASM/CMD reaches.
7292H - DEFM: End Test and Pass 2 Shortcut
Reached from 6B56H with the Z FLAG set if the character in Register A is the closing apostrophe. Pass 2 goes back to 6B39H (advance the address only); passes 1 and 3 go back to 6B30H to emit the character.
7292
RET Z C8
Closing apostrophe: RETURN; the DEFM line is finished.
7293
LD B,A 47
Keep the character in Register B.
7294
LD A,(53C0H) 3A C0 53
Load Register A with the pass number from 53C0H.
7297
CP 02H FE 02
Compare against 02H.
7299
Pass 2: JUMP to 6B39H to advance the address without listing another line.
729C
LD A,B 78
Restore the character into Register A.
729D
Passes 1 and 3: JUMP to 6B30H to emit the character.
72A0H - Clear the Output-to-File Flag
Clears 53BAH so that character output goes to the screen again. Register A and the flags are preserved. Called before the appendage shows an error message (6FAAH, 7199H).
72A0
PUSH AF F5
Save Register A and the flags.
72A1
XOR A AF
Set Register A to 00H.
72A2
LD (53BAH),A 32 BA 53
Clear the output-to-file flag at 53BAH.
72A5
POP AF F1
Restore Register A and the flags.
72A7H - Show the Appendage Banner Once
Called at the start of L, W and A. The first time, displays APPARAT ASSEMBLER APPENDAGE, VERSION 3.0; 7632H remembers that it has been shown.
72A7
LD A,(7632H) 3A 32 76
Load Register A with the banner-shown flag from 7632H.
72AB
RET NZ C0
Already shown: RETURN.
72AC
INC A 3C
Set Register A to 01H.
72AD
LD (7632H),A 32 32 76
Store it into 7632H.
72B0
LD HL,74E8H 21 E8 74
Point HL to the banner at 74E8H.
72B3
JUMP to 592FH to display it; 592FH returns to the caller.
72B6H - Appendage FCB and Disk Buffer (Not in the File)
Not Loaded
EDTASM/CMD has no load record for 72B6H-74E7H; the second load block ends at 72B5H and the next starts at 74E8H. The appendage uses this space for its one File Control Block and a two-sector disk buffer. IX = 72B6H inside the disk routines (set by 6F34H).
72B6-72E7
DEFS 50
File Control Block
The filespec for L D= / W D= is copied here by 6FB0H-6FE3H, or typed here at the OBJECT FILESPEC? prompt (725CH), ending with 0DH; the DOS OPEN (4424H) or INIT (4420H) call at 7010H, 7033H or 7038H then turns it into an open FCB. The routines change FCB+04H (buffer address high byte), FCB+05H (bytes in the last sector) and FCB+0AH (next record number low byte). Also used as the reply buffer for the questions at 6F5DH and 724AH.
72E8-74E7
DEFS 512
Disk Buffer
Two 256-byte sectors (72E8H-73E7H and 73E8H-74E7H). Reads fill both (70E3H-70F5H) and writes empty both (71BBH-71CDH) through the DOS READ and WRITE calls. The replies to the W file questions are also typed at 72E8H (7016H).
74E8H - Appendage Messages (Data)
Data
Messages used by the appendage and by the symbol table lister. Most end with a character that has bit 7 set and are displayed by 592FH (through 727AH for the questions); the two cross-reference texts end with 03H and are printed by 56BEH.
74E8-7512
DEFM 0DH, "APPARAT ASSEMBLER APPENDAGE, VERSION 3.0", 0DH, A0H 0D 41 50 50 41 52 41 54 20 41 53 53 45 4D 42 4C 45 52 20 41 50 50 45 4E 44 41 47 45 2C 20 56 45 52 53 49 4F 4E 20 33 2E 30 0D A0
Appendage banner, shown once by 72A7H (72B0H). Starts and ends with a carriage return (0DH); the final A0H is a space with bit 7 set.
7513-753A
DEFM "OBJECT FILE TO DISK OR TAPE? (D OR T) ", A0H 4F 42 4A 45 43 54 20 46 49 4C 45 20 54 4F 20 44 49 53 4B 20 4F 52 20 54 41 50 45 3F 20 20 28 44 20 4F 52 20 54 29 20 A0
Object destination question, 7247H.
753B-754C
DEFM "OBJECT FILESPEC? ", A0H 4F 42 4A 45 43 54 20 46 49 4C 45 53 50 45 43 3F 20 A0
Object filespec prompt, 7259H.
754D-755B
DEFM "INTERNAL ERROR", A0H 49 4E 54 45 52 4E 41 4C 20 45 52 52 4F 52 A0
Converter error message, 719CH.
755C-7590
DEFM "TEXT IN BUFFER. ARE YOU CONCATENATING???? (Y OR N) ", A0H 54 45 58 54 20 49 4E 20 42 55 46 46 45 52 2E 20 41 52 45 20 59 4F 55 20 43 4F 4E 43 41 54 45 4E 41 54 49 4E 47 3F 3F 3F 3F 20 20 28 59 20 4F 52 20 4E 29 20 A0
Concatenation question for L, 6F5AH.
7591-75CB
DEFM "************** FILE NON-EXISTENT. REPLY ", 22H, "C", 22H, " TO CREATE IT ", A0H 2A 2A 2A 2A 2A 2A 2A 2A 2A 2A 2A 2A 2A 2A 20 46 49 4C 45 20 4E 4F 4E 2D 45 58 49 53 54 45 4E 54 2E 20 20 52 45 50 4C 59 20 22 43 22 20 54 4F 20 43 52 45 41 54 45 20 49 54 20 A0
Shown by 7020H when a file for W or object output is not on the disk. 22H is the quote character.
75CC-75F7
DEFM "FILE ALREADY EXISTS. USE IT???? (Y OR N) ", A0H 46 49 4C 45 20 41 4C 52 45 41 44 59 20 45 58 49 53 54 53 2E 20 20 55 53 45 20 49 54 3F 3F 3F 3F 20 20 28 59 20 4F 52 20 4E 29 20 A0
Shown by 7013H/6FEBH when the output file already exists.
75F8-760C
DEFM "MULTIPLY DEFINED AT ", 03H 4D 55 4C 54 49 50 4C 59 20 44 45 46 49 4E 45 44 20 41 54 20 03
Printed by 562EH through 56BEH (which stops at the 03H) in the symbol table listing for a symbol whose flag byte has bit 6 set (multiply defined; tested at 55EBH).
760D-7615
DEFM "UNDEF***", 03H 55 4E 44 45 46 2A 2A 2A 03
Printed by 55D6H through 56BEH in the symbol table listing in place of the value of a symbol whose flag byte has bit 7 clear (undefined; tested at 55D2H).
7616-762B
DEFM " TEXT AREA BYTES LEFT", A0H 20 54 45 58 54 20 41 52 45 41 20 42 59 54 45 53 20 4C 45 46 54 A0
Printed after the free byte count by 709FH.
762CH - Appendage and Symbol Lister Variables
Loaded as 00H bytes. 762CH-7632H belong to the appendage; 7633H-763CH are used by the symbol table and cross-reference lister at 5200H-56EDH.
762C
DEFB 00H 00
Disk File Active
01H while an appendage disk file is open (set at 7041H, cleared at 7232H). Every tape-byte hook (7046H, 704FH, 706DH, 7079H, 70B6H, 70C6H, 710CH, 71D5H) tests it.
762D
DEFB 00H 00
File Mode
00H = read text (L), 01H = write text (W), 02H = object code. Set at 6F72H and 723DH; read at 7002H, 7120H and 71EAH.
762E
DEFB 00H 00
DOS Error Flag
The last DOS error code, stored by 726FH. 71E4H skips writing and closing when it is non-zero. Cleared at 5709H and 7235H.
762F
DEFB 00H 00
Object Converter State
Bit 0 = skip bytes, bit 1 = record type next, bit 2 = byte count next, bit 6 = transfer address, bit 7 = copy data (see 711FH). Set to 01H at 7269H.
7630
DEFB 00H 00
Object Converter Count
Bytes left in the current converter state. Set to 07H at 7264H; changed at 7133H, 714BH and 7175H.
7631
DEFB 00H 00
Saved Result
Register A is kept here while 6F3FH restores the other registers.
7632
DEFB 00H 00
Banner Shown
Set to 01H by 72ADH after the appendage banner is displayed.
7633
DEFB 00H 00
Lister Column Count
References left on the current output line of the symbol table listing (set at 55F2H, 5640H and 56E4H; read at 56D3H).
7634-7635
DEFW 0000H 00 00
Lister Pointer
Written at 524CH, 5517H and 5624H; read at 5279H, 5299H, 55A0H, 55A9H, 55DEH, 565EH and 566FH.
7636
DEFB 00H 00
Lister Overflow Count
Cleared at 52CEH, set at 5676H, read at 5618H.
7637-7638
DEFW 0000H 00 00
Lister pointer saved at 5672H, reloaded at 5621H.
7639-763A
DEFW 0000H 00 00
Lister pointer saved at 566CH, reloaded at 5627H.
763B-763C
DEFW 0000H 00 00
Reference List Pointer
Next free entry in the list at 763DH. Set to 763DH at 52D4H-52D7H, advanced at 5666H.
763DH - Reference List (Not in the File)
Not Loaded
EDTASM/CMD has no load record for 763DH-764CH (the third load block ends at 763CH and the fourth starts at 764DH).
763D-764C
DEFS 16
Reference List
Up to eight 2-byte entries stored by 5662H-5666H; 5654H limits the count at 764DH to eight. Read back by 55F5H-560CH when the references are printed.
764DH - Symbol Lister Work Area and Disk Buffer Pointers
Loaded. 7654H-7657H hold two constant one-character dummy symbol entries used by the sorted listing at 5200H: a length byte of 01H followed by the name 00H (lower than any symbol) and by the name FFH (higher than any symbol). 7658H-765BH are the appendage's disk buffer position and end. The rest is unreferenced zero fill. The text buffer starts right after this block at 7700H (588AH).
764D
DEFB 00H 00
Reference Count
Entries in the list at 763DH (cleared at 52D1H, incremented at 5650H-5658H, read at 55F8H).
764E-764F
DEFW 0000H 00 00
Previous Symbol
Pointer to the name of the symbol printed last; set at 521FH, read at 5257H.
7650-7651
DEFW 0000H 00 00
Next Symbol
Pointer to the name of the symbol being chosen; set at 520EH and 5235H, read at 521CH, 5285H, 52A7H, 52DAH, 55AFH and 5684H.
7652-7653
DEFW 0000H 00 00
Scan Start
Text line where the next reference scan starts; set at 55ACH, read at 5503H.
7654-7655
DEFB 01H, 00H 01 00
Lowest Dummy Symbol
Length byte 01H and the name 00H. 520BH points 7650H at 7655H before the first symbol is chosen.
7656-7657
DEFB 01H, FFH 01 FF
Highest Dummy Symbol
Length byte 01H and the name FFH. 522EH starts each search with 7657H as the best candidate.
7658-7659
DEFW 0000H 00 00
Disk Buffer Position
Next byte to read or write in 72E8H-74E7H. Set at 6FFAH, 7106H and 71B0H; read at 70D4H, 71ABH and 71F3H.
765A-765B
DEFW 0000H 00 00
Disk Buffer End
72E8H (empty) or 74E8H (full) or 73E8H after a short read. Set at 6FFDH, 700AH and 70FBH; read at 70D7H, 70DDH and 71B3H.
765C-76FF
DEFB 00H x 164 00 x 164
Unreferenced 00H bytes to the end of the load block.