TRS-80 - Level 1 ROM Disassembled

System Variable Storage Chart - All offset from 4000H

+$68-$69
Current cursor location
+$6A-$6B
Physical top of internal ram
+$6C-$6D
Pointer to variable storage space
+$70-$7F
A$ storage space
+$80-$8F
B$ storage space
+$90
Cassette Out Byte
+$91-$92
STEP value
+$9B-$9C
Used to store SP
+$9D-$9E
Current line being executed
+$9F-$A0
Next line to execute for CONT, error
+$A3-$A4
GOSUB, RETURN to line number
+$A5-$A6
Number to return to for FOR-NEXT
+$AC
Keyboard input buffer
+$F4
IX is initialized here
+$200
Where SP is initialized to start, downward

Floating Point Number Storage

IX + F6
L - LSB of NUMBER 2
IX + F7
H - NMSB of NUMBER 2
IX + F8
C - MSB of NUMBER 2
IX + F9
L' - Exponent of NUMBER 2
IX + FA
H' - Sign of NUMBER 2
IX + FB
E - LSB of NUMBER 1
IX + FC
D - NMSB of NUMBER 1
IX + FD
B - MSB of NUMBER 1
IX + FE
E' - Exponent of NUMBER 1
IX + FF
D' - Sign of NUMBER 1

Disassembly

0000H
DI
Disable Interrupts.
0001H
LD HL,00FFH
Let Register Pair HL equal 00FFH, which, when the very next instruction hits, will turn HL into FFFFH.
0004H
JUMP to 018EH to determine How Much RAM is in the System and then continue with startup.
0007H
NOP
No Operation (Do Nothing).

0008H - RST 08H Routine - This routine requires TWO parameters ... a value as the next bit and a byte offset. DE is advanced to the next non-space and tests it against the value. If there is no match, jumps to the return value PLUS the offset. If there is match, jumps to the byte after the offset.

0008H
EX (SP),HL
Since this routine ultimately changes the place to which it returns, we need to get that address so EXchange the value stored in Register Pair HL with the value stored in Register Pair SP.
0009H
RST 28H
Call RST 28H to move DE to point to the next non-space character, with Register A holding that character.
000AH
CP (HL)
Compare the next non-space character (held in Register A) against the value held at the top of the stack (i..e, in the memory location pointed to by the value held in Register Pair HL). Results:
  • If Register A equals the value held in Register (HL), the Z FLAG is set.
  • If A < (HL), the CARRY FLAG will be set.
  • if A >= (HL), the NO CARRY FLAG will be set.
000BH
Continue on with a JUMP to 0098H.

000EH - Display a CARRIAGE RETURN.

000EH
LD A,0DH
Let Register A equal 0DH (ASCII: CARRIAGE RETURN). Routine then falls through to RST 10H which displays the character.

0010H - RST 10H Routine - This routine will send a character to the screen or to the cassette.

0010H
EXX
EXchanges the 16-bit contents of BC, DE, and HL with BC', DE', and HL'. Note: AF is not handled via EXX.
0011H
EX AF,AF'
EXchange the value stored in Register Pair AF' with the value stored in Register Pair AF.
0012H
GOSUB to 0FF0H to check to see if the cassette motor is running.
0015H
JUMP to 0ACBH to send the byte held in Register A either to the screen or the cassette.

0018H - RST 18H Routine - This routine will parse an expression.

0018H
GOSUB to 07ADH to parse an expressions.
001BH
NOP
No Operation (Do Nothing).
001CH
JUMP to 075DH to parse an optional relational expression (">" "<" or "=").
001FH
NOP
No Operation (Do Nothing).

0020H - RST 20H Routine - This routine will compare HL and DE. NZ means no match, Z means match.

0020H - RST 20H Routine - This routine will compare HL and DE. NZ means no match, Z means match.

0020H
LD A,H
Copy the contents of Register H into Register A.
0021H
CP D
Compare Register H (held in Register A) against Register D. Results:
  • If Register A equals the value held in Register D, the Z FLAG is set.
  • If A < D, the CARRY FLAG will be set.
  • If A >= D, the NO CARRY FLAG will be set.
0022H
RET NZ
If the NZ FLAG (Not Zero) has been set, RETurn to the caller.
0023H
LD A,L
If we're here, then H matched D so let's keep going. Copy the contents of Register L into Register A.
0024H
CP E
Compare Register L (held in Register A) against Register E. Results:
  • If Register A equals the value held in Register E, the Z FLAG is set.
  • If A < E, the CARRY FLAG will be set.
  • If A >= E, the NO CARRY FLAG will be set.
0025H
RET
Return to the caller.
0026H
NOP
No Operation (Do Nothing).
0027H
NOP
No Operation (Do Nothing).

0028H - RST 28H Routine

This routine will skip forward from DE until the first non-space character, with Register A holding that character.

0028H
LD A,(DE)
Fetch the next character on the BASIC line being processed (held in the memory location pointed to by Register Pair DE) and store it into Register A.
0029H
CP 20H
Since the purpose of this routine is to skip over SPACE, we compare the value held in Register A against 20H (ASCII: SPACE). Results: If Register A equals SPACE, the Z FLAG is set.
002BH
RET NZ
If the NZ FLAG (Not Zero) has been set, then we have a non-space held in A, so return to the caller.
002CH
INC DE
Otherwise, we still have a space so increment the value stored in Register Pair DE by 1.
002DH
Jump to 0028H to test that character.

0030H - RST 30H Routine

This routine will continue execution.

0030H
POP AF
Put the return address (which should be held at the top of the STACK) into Register Pair AF.
0031H
GOSUB to 08B3H to check if the next character is a ":" and if yes, jump to 08BAH to check for a CARRIAGE RETURN and if not then jump to the middle of the execute next line routine.
0034H
Jump to 08C9H to display the "WHAT" error (Level 1 equivalent of a SYNTAX ERROR).
0037H
NOP
No Operation (Do Nothing).

0038H - RST 38H Routine.

This routine will check a variable to make sure it exists. If it doesn't, CARRY will be set. If it does, HL will point to the variable and NC will be set. Note that only variables A-Z and A(n) are valid in Level 1.

0038H
RST 28H
First, move to where the variable should be via a call to RST 28H to search DE until a non-space character is found, with Register A holding that character.
0039H
SUB 41H
Subtract the value 41H (ASCII: A) from Register A to test to see if the character is less than a capital "A".
003BH
RET C
If the CARRY FLAG has been set then the variable (i.e., the non-space character) was less than A, meaning an invalid variable. Return to the caller with the CARRY FLAG set.
003CH
CP 1AH
Compare the value held in Register A against 1AH (Decimal: 26) to see if the character is greater than a Control Character. Results:
  • If Register A equals 26, the Z FLAG is set.
  • If A < 26, the CARRY FLAG will be set.
  • If A >= 26, the NO CARRY FLAG will be set.
003EH
CCF
So at this point, a good variable will be less than 26 (with the CARRY FLAG set) and a bad variable will be greater than or equal to 26 (with the NC set). This is backwards from an error, so invert the state of the CARRY FLAG, so that a bad variable has the CARRY set and a good variable has the NC set.
003FH
RET C
If the CARRY FLAG has been set, meaning we have a bad variable, return to the caller.
0040H
INC DE
If we're here then we have a good variable at DE. Increment the value stored in Register Pair DE by 1.
0041H
AND A
Reset the CARRY FLAG and set the Z/NZ FLAGS based on Register A via an AND A (which masks the value of Register A against itself). This tests to see if the variable at DE is an "A" or not, as "A" is the only variable that can be an array in Level 1.
0042H
If the NZ FLAG (Not Zero) has been set (meaning that the variable is not "A"), jump to 0082H to continue processing the single valid non-array variable.
0044H
RST 08H
28H
3AH
Next we need to check for the array, which means a parenthesis. We do this a call to RST 08H with parameters of "(" and an offset of 3AH. RST 08H will move to the next non-space character and check it against 28H (which is a "("). If there is no match, jump to the return (of the next instruction, i.e. 0047H) + 3AH instructions (which would be 0081H).
0047H
If we are here then the next character pointed to by DE is the subscript of an A() variable. GOSUB to 080BH to determine that subscript as a non-negative integer.
004AH
INC HL
Now we need to position HL to point to the variable. Increment the value stored in Register Pair HL by 1.
004BH
ADD HL,HL
Double HL.
004CH
ADD HL,HL
Double HL again!
004DH
If the C FLAG (Carry) has been set because of all that math, then HL doesn't have a valid value anymore so display the "HOW?" error via a jump to 01A2H.
0050H
PUSH HL
If the CARRY FLAG didn't trip, then we have a valid pointer value in HL so save it to the top of the stack.
0051H
RST 08H
29H
35H
Next we need to check for close parenthesis. We do this a call to RST 08H with parameters of ")" and an offset of 35H. RST 08H will move to the next non-space character and check it against 29H (which is a ")"). If there is no match, jump to the return (of the next instruction, i.e. 0054H) + 35H instructions (which would be 0089H).
0054H
POP HL
Restore HL from the top of the stack.
0055H
PUSH DE
Save the current pointer on the line being analyzed (held in Register Pair DE) to the top of the stack.
0056H
PUSH HL
Save the pointer to the variable (held in Register Pair HL) to the top of the stack.
0057H
LD HL,(406AH)
Fetch the value of the top of physical memory (held in memory location 406AH) and store it into Register Pair HL.
005AH
LD DE,(406CH)
Fetch the pointer to the top of user RAM (held in memory location 406CH) and store it into Register Pair DE.
005EH
XOR A
Set Register A to ZERO and clear all Flags.
005FH
SBC HL,DE
Subtract the top of user RAM and the CARRY FLAG from the top of physical memory, with the results into Register Pair HL.
0061H
POP DE
Restore the pointer to the variable (formerly held in Register Pair HL) from the top of the stack into Register Pair DE.
0062H
RST 20H
Compare HL and DE via a call to RST 20H - NZ means no match, Z means match. If H=D but L < E, then the C flag will be set.
0063H
Skip over the NMI handler routine and continue on via a jump to 0076H.

0066H - Non-Maskable Interrupt Routine.

This would be triggered on hitting the RESET BUTTON.

0066H
DI
Disable Interrupts.
0067H
LD SP,4200H
Set the Stack Pointer to 4200H.
006AH
XOR A
Set Register A to ZERO and clear all Flags.
006BH
LD (4090H),A
Store the ZERO held in Register A into the cassette port status cache (held in memory location 4090H).
006EH
OUT (FFH),A
Send the ZERO held in Register A into the cassette port.
0070H
LD A,0CH
Let Register A equal 0CH (ASCII: Form Feed), which is essentially a CLS.
0072H
RST 10H
Send the character held in Register A (i.e., 0CH) to the cassette or screen via a RST 10 call.
0073H
Show the READY prompt via a JUMP to 01C9H.

0076H - Continuation point for the RST 38H routine.

At this point, HL has the current pointer to the line being examined is at the top of the stack, DE has the pointer to the variable, Z/NZ is set based on whether the location of the array variable is in or out of bounds, and if Register A is greater than Register E, the CARRY FLAG is set.

0076H
If the C FLAG (Carry) has been set (meaning that DE > HL) then we have a problem, so JUMP to 08F5H to display the "SORRY" error.
0079H
LD HL,(406AH)
Fetch the value of the top of physical memory (held in memory location 406AH) and store it into Register Pair HL.
007CH
SBC HL,DE
Subtracts the value stored in Register Pair DE (the pointer to the variable) and the carry flag from the value stored in Register Pair HL (the top of physical memory).
007EH
POP DE
Put the current pointer to the line being examined (held at the top of the STACK) back into Register Pair DE.
007FH
XOR A
Set Register A to ZERO and clear all Flags.
0080H
RET
Return to the caller.

0081H - Continuation point for the RST 38H routine"

Jumped to if the variable is "A" and no "(" was found after it. This routine will set HL to point to the RAM address which holds the variables "A" - "Z"

0081H
XOR A
Set Register A to ZERO and clear all Flags.

0082H - Continuation point for the RST 38H routine".

Register A will contain 0-25, representing variables "A"-"Z".

0082H
LD H,40H
Let Register H equal 40H to set the MSB to the variable list of 4000H (Variable A) through 4064H (Variable Z)
0084H
0085H
RLA
RLA
Rotate the bits of Register left (i.e., lower bit moves higher) two bit positions so that A will correspond to 00H (Variable A) to 64H (Variable Z)
0086H
LD L,A
Set the LSB of the Register Pair HL variable pointer to the offset calculated and held in Register A.
0087H
XOR A
Set Register A to ZERO and clear all Flags.
0088H
RET
Return to the caller.

0089H - Jump to the routine to Display the "WHAT" error.

0089H
Jump to 08C9H to display the "WHAT" error.

008CH - Subroutine to check to see if the character pointed to by Register Pair DE is, or is not, a digit (i.e., 0-9).

If a digit is found, will return with Register A containing the digit and NC set, or the CARRY FLAG set otherwise.

008CH
LD A,(DE)
Fetch the next character on the BASIC line being processed (held in the memory location pointed to by Register Pair DE) and store it into Register A.
008DH
CP 30H
Compare the value held in Register A against 30H (ASCII: 0). Results:
  • If Register A equals 0, the Z FLAG is set.
  • If A < 0, the CARRY FLAG will be set.
  • If A >= 0, the NO CARRY FLAG will be set.
008FH
RET C
If the C FLAG (Carry) has been set then it's not a digit because it's below 0, so return to the caller with the CARRY FLAG set.
0090H
CP 3AH
Compare the value held in Register A against 3AH (ASCII: :), which is 1 character higher than a 9. Results:
  • If Register A equals :, the Z FLAG is set.
  • If A < :, the CARRY FLAG will be set.
  • If A >= :, the NO CARRY FLAG will be set.
0092H
CCF
If we have a good character, the CARRY FLAG will have been set by the CP instruction. Since the CARRY FLAG being set is supposed to signal a bad character, we need to invert the state of the CARRY FLAG.
0093H
RET C
If the C FLAG (Carry) has been set then it's not a digit because it's above9, so return to the caller with the CARRY FLAG set.
0094H
INC DE
If we are here then we have a good digit stored in Register A. Now a bit of cleanup. First advance the pointer on the line being examined (held in Register Pair DE) by 1 to point to the next character instead of the one we just examined.
0095H
AND 0FH
Cap the number at 15 by masking the value of Register A against 0FH (00001111). This has the effect of turning off bits 7,6,5,4, leaving only bits 3,2,1,0 active.
0097H
RET
Return to the caller.

010AH - Continuation of the FLOATING POINT CONSTANT routine at 00A6H.

Jumped here if we have a non-digit that isn't a ".", "E", or +, or -.

010AH
GOSUB to 0157H to zero out the integer accumulator.
010DH
We need to verify that the character is a digit, so GOSUB to 008CH to check to see if the character pointed to by Register Pair DE is, or is not, a digit. Returns Register A containing the digit, or the CARRY FLAG set otherwise.
0110H
If the CARRY FLAG has been set, and we do not have a digit, JUMP to 0120H.
0112H
SET 5,B
SET (i.e., set as 1) BIT 5 of Register B to indicate that we have found a digit in an exponent position.
0114H
GOSUB to 015EH to accumulate the exponent's digit by multiplying the accumulator by 10 and then adding in A to the newly vacant one's spot. Routine will return a NZ SET if an overflow occurs from the accumulation.
0117H
If the NZ FLAG (Not Zero) has been set, meaning we have an overflow, display the "HOW?" error via a JUMP to 01A2H.
011AH
JUMP to 010DH to parse the next character.

011CH - Continuation of the FLOATING POINT CONSTANT routine at 00A6H.

Jumped here if we have a non-digit that isn't a "." or an "E".

011CH
POP DE
Restore the current position on the line being evaluated from the top of the stack into Register Pair DE.
011DH
XOR A
Set Register A to ZERO and clear all Flags.
011EH
JUMP to 0137H.

0120H - Continuation of the FLOATING POINT CONSTANT routine at 00A6H.

Jumped here if we have started processing an exponent and then hit a non-digit.

0120H
BIT 5,B
Test Bit Number 5 of Register B to determine if we already have exponent digits. Z FLAG will be set if that bit is 0, and NZ FLAG will be set if that bit is 1.
0122H
If the Z FLAG (Zero) has been set and we have no exponent digits, JUMP to 011CH.
0124H
POP AF
Put the value held at the top of the STACK into Register Pair AF.
0125H
EXX
EXchanges the 16-bit contents of BC, DE, and HL with BC', DE', and HL'. Note: AF is not handled via EXX.
0126H
LD A,C
Copy the contents of Register C into Register A.
0127H
OR H
OR Register H against Register A. The results are stored in Register A.
0128H
The NZ will be set if either Register C or Register H is not zero. If that's the case, then we have a problem (most likely an overflow) and the NZ FLAG (Not Zero) will have been set, JUMP to 0151H to swap the registers back and give a "HOW" error.
012AH
LD A,L
Copy the exponent (held in Register L) into Register A.
012BH
EXX
EXchanges the 16-bit contents of BC, DE, and HL with BC', DE', and HL'. Note: AF is not handled via EXX.
012CH
BIT 7,A
Test Bit Number 7 of Register A to see if we have a large number of digits (meaning, over 128). Z FLAG will be set if that bit is 0, and NZ FLAG will be set if that bit is 1.
012EH
If the NZ FLAG (Not Zero) has been set, display the "HOW?" error via a JUMP to 01A2H.
0131H
BIT 1,B
Test Bit Number 1 of Register B to see if we have found a exponent minus sign. Z FLAG will be set if that bit is 0, and NZ FLAG will be set if that bit is 1.
0133H
If the Z FLAG (Zero) has been set, JUMP to 0137H.
0135H
NEG
At this point, we have a valid exponent ... but its sign is wrong. Negate the contents of Register A (which is the same as -A).
0137H
ADD A,C
LET Register A = Register A + Register C.
0138H
AND A
Reset the CARRY FLAG and set the Z/NZ FLAGS based on Register A via an AND A (which masks the value of Register A against itself).
0139H
If the Z FLAG (Zero) has been set, then Register A, after all that, is still zero -- so we were given an E00. Since that's not relevant, JUMP away to 014EH to exit the routine.
013BH
BIT 7,A
Test Bit Number 7 of Register A to see if we have a large number of digits (meaning, over 128). Z FLAG will be set if that bit is 0, and NZ FLAG will be set if that bit is 1.
013DH
If the Z FLAG (Zero) has been set then we have a POSITIVE exponent to process ... JUMP to 0146H.
013FH
INC A
INCrement the value stored in Register A by 1.
0140H
PUSH AF
Save the contents of Register Pair AF to the top of the stack.
0141H
GOSUB to 0C95H to divide the floating point stack by 10.
0144H
JUMP to 014BH.

0146H - Continuation of the FLOATING POINT CONSTANT routine at 00A6H; jumped here if to process a POSITIVE exponent.

0146H
DEC A
DECrement the value stored in Register A by 1.
0147H
PUSH AF
Save the contents of Register Pair AF to the top of the stack.
0148H
GOSUB to 0C84H to multiply the floating point stack by 10.
014BH
POP AF
Put the value held at the top of the stack into Register Pair AF.
014CH
JUMP to 0138H.

014EH - Continuation of the FLOATING POINT ROUTINE at 00A6H; exit the floating point routine.

014EH
BIT 6,B
Test Bit Number 6 of Register B to see if we had found any digits. Z FLAG will be set if that bit is 0, and NZ FLAG will be set if that bit is 1.
0150H
RET
RETurn to the caller - If Z is set, then we had a bad value.

0151H - Exit routine with HOW error.

0151H
EXX
EXchanges the 16-bit contents of BC, DE, and HL with BC', DE', and HL'. Note: AF is not handled via EXX.
0152H
Display the "HOW?" error via a JUMP to 01A2H.

0155H - Routine to clear parse flags and prepare for next parsing.

0155H
RES 6,B
RESet (i.e., set as 0) BIT 6 of Register B to zero out the flag as to whether we have found a digit yet or not.
0157H
EXX
EXchanges the 16-bit contents of BC, DE, and HL with BC', DE', and HL'. Note: AF is not handled via EXX.
0158H
LD L,00H
Let Register L equal 00H.
015AH
LD H,L
Copy a 0 (i.e., the contents of Register L) into Register H.
015BH
LD C,L
Copy a 0 (i.e., the contents of Register L) into Register C.
015CH
EXX
EXchanges the 16-bit contents of BC, DE, and HL with BC', DE', and HL'. Note: AF is not handled via EXX.
015DH
RET
RETurn to the caller.

0155H - Continuation of the FLOATING POINT CONSTANT routine at 00A6H.

Clear out H', L', C', and Bit 6 of Register B' in anticipation of starting to parse.

0155H
RES 6,B
RESet (i.e., set as 0) BIT 6 of Register B to zero out the flag as to whether we have found a digit yet or not.
0157H
EXX
EXchanges the 16-bit contents of BC, DE, and HL with BC', DE', and HL'. Note: AF is not handled via EXX.
0158H
LD L,00H
Let Register L equal 00H.
015AH
LD H,L
Copy a 0 (i.e., the contents of Register L) into Register H.
015BH
LD C,L
Copy a 0 (i.e., the contents of Register L) into Register C.
015CH
EXX
EXchanges the 16-bit contents of BC, DE, and HL with BC', DE', and HL'. Note: AF is not handled via EXX.
015DH
RET
RETurn to the caller.

015EH - Continuation of the FLOATING POINT CONSTANT routine at 00A6H.

This basically multiplies the 24 bit digit represented by C'H'L' by 10 and then adds in A' with overflow going to B' thus leaving a 32 bit result of B'C'H'L'.. Specifically it accumulates the digit by multiplying the accumulator by 10 and then adding in A to the newly vacant one's spot. Routine will return a NZ SET if an overflow occurs from the accumulation. On entry, the REGULAR REGISTER SET is active.

015EH
EX AF,AF'
EXchange the value stored in Register Pair AF' with the value stored in Register Pair AF.
015FH
EXX
Set the ALTERNATE REGISTER SET as active and EXchange the 16-bit contents of BC, DE, and HL with BC', DE', and HL'. Note: AF is not handled via EXX.
0160H
0161H
LD D,H
LD E,L
Let Register Pair DE' = Register Pair HL'.
0162H
LD A,C
Copy the contents of Register C' into Register A'.
0163H
LD B,00H
Let Register B' equal 00H. Register B' tracks a whole lot of status bits for the floating point routine. Bit 0=Decimal point has been found, Bit 1 = Exponent with a Minus Sign has been Found, Bit 5 = Digits in an exponent have been found, Bit 6 = A digit has been found, and Bit 7 = A large number of digits (more than 127) have been found.
0165H
PUSH AF
Save the contents of Register Pair AF to the top of the stack.
0166H
ADD HL,HL
LET Register Pair HL = Register Pair HL + Register HL.
0167H
RL C
Rotate the bits of Register C left 1 position, with bit 7 going to CARRY and CARRY going to bit 0. This effectively multiplies Register C by 2.
0169H
RL B
Rotate the bits of Register B left 1 position, with bit 7 going to CARRY and CARRY going to bit 0. This effectively multiplies Register B by 2.

So at this point HL, C, and B have all been multiplied by 2.

016BH
ADD HL,HL
LET Register Pair HL = Register Pair HL + Register HL.
016CH
RL C
Rotate the bits of Register C left 1 position similar to above multiplication.
016EH
RL B
Rotate the bits of Register B left 1 position similar to above multiplication.

So at this point HL, C, and B have all been multiplied by 4 total.

0170H
ADD HL,DE
LET Register Pair HL = Register Pair HL + Register DE.
0171H
ADC A,C
LET Register A = Register A + Register C with carry. Now Register A = Register C * 5.
0172H
LD C,A
Save Register C * 5 to Register C.
0173H
LD A,00H
Set Register A to 00H.
0175H
ADC A,B
LET Register A = Register A + Register B with carry. Now Register A = Register B * 5.
0176H
LD B,A
Save Register B * 5 to Register B.

So at this point HL, C, and B have all been multiplied by 5 total.

0177H
POP AF
Restore the original value of C into A from the stack.
0178H
ADD HL,HL
Double Register Pair HL.
0179H
RL C
Rotate bits of Register C left once more.
017BH
RL B
Rotate bits of Register B left once more.

So at this point HL, C, and B have all been multiplied by 10 total.

017DH
EX AF,AF'
Exchange value stored in Register Pair AF' with AF.

The rest of the routine adds Register A to Register Pairs HL and BC.

017EH
ADD A,L
LET Register A = Register A + Register L.
017FH
LD L,A
Copy result to Register L.
0180H
LD A,00H
Set Register A to 00H.
0182H
ADC A,H
LET Register A = Register A + Register H with carry.
0183H
LD H,A
Copy result to Register H.
0184H
LD A,00H
Set Register A to 00H.
0186H
ADC A,C
LET Register A = Register A + Register C with carry.
0187H
LD C,A
Copy result to Register C.
0188H
LD A,00H
Set Register A to 00H.
018AH
ADC A,B
LET Register A = Register A + Register B with carry.
018BH
LD B,A
Copy result to Register B.
018CH
EXX
Exchange BC, DE, HL with BC', DE', HL'. AF is not handled via EXX.
018DH
RET
Return to the caller.

018EH - Determine How Much RAM is in the System by fetching, complementing, storing, and testing each byte from FFFFH downwards. HL = 00FFH on entry.

018EH - Determine How Much RAM is in the System by fetching, complementing, storing, and testing each byte from FFFFH downwards. HL = 00FFH on entry.

018EH
DEC H
DECrement the value stored in Register H by 1. On the first run this turns HL's 00FFH into FFFFH.
018FH
LD A,(HL)
Fetch the value held in the memory location pointed to by Register Pair (HL) and store it into Register A.
0190H
CPL
Reverse each bit in Register A (which is the same as NOT).
0191H
LD (HL),A
Store the value held in Register A into the memory location pointed to by Register Pair HL.
0192H
XOR (HL)
eXclusive OR the value stored at (HL) against Register A. Why XOR the value against itself (since the value at HL was just set as A) when XORing a value against itself produces a Zero? Well, the RAM location might not exist, which is the only way that XOR would produce a NZ result.
0193H
If the NZ FLAG (Not Zero) has been set then the RAM location pointed to by HL didn't accept the value, so LOOP back to 018EH to keep reducing the page of RAM to test (so FFFF to FEFF to FDFF ...).
0195H
LD (406AH),HL
If we are here, then we hit the first tested address that stored a value. Store THAT address (held in Register Pair HL) into memory location 406AH (which is the top of physical memory).
0198H
XOR A
Set Register A to ZERO and clear all Flags.
0199H
LD (4090H),A
Store a 0 (held in Register A) into the cassette port status cache (held at memory location 4090H).
019CH
LD SP,4200H
Set the stack pointer to 4200H / (Decimal: 16896).
019FH
JUMP to 037BH to clear the screen and continue with the startup process.

01A2H - Display the "HOW?" error.

01A2H
PUSH DE
Save the contents of Register Pair DE to the top of the stack.
01A3H
LD DE,01A9H
Let Register Pair DE equal 01A9H to point to the HOW? message.
01A6H
JUMP to 08CDH.

01A9H - MESSAGE STORAGE AREA.

01A9H
"HOW?" + 0DH
01AEH
"READY" + 0DH
01B4H
"WHAT?" + 0DH
01BAH
"SORRY" + 0DH
01C0H
"BREAK AT"
01C8H
DEFB 00H

01C9H - BASIC's READY Entry Point. If JUMPed here, the BASIC RUN STATE is cleared.

01C9H
LD SP,4200H
Set the stack pointer to 4200H.
01CCH
GOSUB to 0FE4H to turn off the cassette motor.

01CFH - BASIC's READY Alternate Entry Point. If JUMPed here, the BASIC RUN STATE is not affected.

01CFH
GOSUB to 000EH to display a CARRIAGE RETURN.
01D2H
LD DE,01AEH
Let Register Pair DE equal 01AEH, which is the message storage area for the READY prompt.
01D5H
GOSUB to 094FH to display the message pointed to by Register Pair DE, returning once a 00H is found.

01D8H - Process a line of code in a READY loop

01D8H
LD SP,4200H
Set the stack pointer to 4200H.
01DBH
GOSUB to 0239H to clear the 10 bytes starting at 409DH and set Register Pair DE to 4200. 409D is the pointer to the line where a STOP statement was activated, 409F is the pointer to the current line being executed, 40A1 is the pointer for the READ statement, 40A3 is the BASIC Stack Pointer location, and 40A5 is the pointer for the current FOR variable.
01DEH
LD IX,40F4H
Let Special Index Register Pair IX, which is used in the floating point math routines, equal 40F4H, which is the bottom of floating point stack. Each entry is 5 bytes consisting of LSB, Middle, MSB (with Bit 7 set), Exponent and Sign (in Bit 7)
01E2H
GOSUB to 08FAH to fetch a line of input.
01E5H
PUSH DE
Save the contents of Register Pair DE to the top of the stack.
01E6H
LD DE,40ACH
Let Register Pair DE equal 40ACH.
NOTE: 40ACH is the storage location for buffer for command input AND the print output to cassette.
01E9H
The first thing we should find is a line number, so GOSUB to 0EC4H to parse an integer into Register Pair HL. Note, this moves DE forward to point to the first non-blank character.
01ECH
LD A,H
OR L
Since the Z-80 cannot test Register Pair HL against zero, the common trick is to set Register A to equal to Register H, and then OR A against Register L. Only if both Register H and Register L were zero can the Z FLAG be set.
01EEH
POP BC
Restore the prior contents of Register Pair DE into Register Pair BC.
01EFH
The flag is currently set by the OR above. If the value is 0, then we are on the command line instead of being inside a program. So ... if the Z FLAG (Zero) has been set, JUMP to 0340H.
01F2H
DEC DE
If we are here, then we are parsing a line in a program. DECrement the value stored in Register Pair DE by 1 to go back to the second number in the 2 byte line number (as DE was moved forward in the call to 0EC4H).
01F3H
LD A,H
Copy the second byte of the line number (held in Register H) into Register A.
01F4H
LD (DE),A
Store the value held in Register A into the memory location pointed to by Register Pair DE.
01F5H
DEC DE
DECrement the value stored in Register Pair DE by 1 to point DE to the first number in the 2 byte line number.
01F6H
LD A,L
Copy the first byte of the line number (held in Register L) into Register A.
01F7H
LD (DE),A
Store the value held in Register A into the memory location pointed to by Register Pair DE.
01F8H
PUSH BC
Save the contents of Register Pair BC to the top of the stack.
01F9H
PUSH DE
Save the contents of Register Pair DE (currently pointing to the line number of the line to be parsed) to the top of the stack.
01FAH
LD A,C
Copy the contents of Register C into Register A.
01FBH
SUB E
LET Register A = Register C - Register E.
01FCH
PUSH AF
Save the contents of Register Pair AF to the top of the stack.
01FDH
GOSUB to 092AH to find the line in RAM which matches the line number pointed to by Register Pair HL. Note: A jump to 092AH resets DE. To do the routine while preserving DE, jump instead to 092DH.

The line number has been found, so we will overwrite/delete the old line.

0200H
PUSH DE
Save the contents of Register Pair DE to the top of the stack.
0201H
If the NZ FLAG (Not Zero) has been set, JUMP to 0213H.
0203H
PUSH DE
Save the contents of Register Pair DE to the top of the stack.
0204H
GOSUB to 0945H to scan the entire line.
0207H
POP BC
Put the value held at the top of the STACK into Register Pair BC.
0208H
LD HL,(406CH)
Fetch the pointer to the top of used RAM (held in memory location 406CH) and store it into Register Pair HL.
020BH
GOSUB to 0A6FH to copy the bytes held at (DE) to (BC), backwards, until DE = HL.
020EH
LD H,B
LD L,C
Copy the contents of Register Pair BC into Register Pair HL because there is no LD (xxxx),BC command in the Z-80!
0210H
LD (406CH),HL
Now that we used up some RAM, set the NEW top of used RAM to HL by putting HL into 406CH (which points to the top of used RAM).

If we are here we will add a new line to the program UNLESS it was just a line number, in which case we delete the line.

0213H
POP BC
Put the value held at the top of the STACK into Register Pair BC.
0214H
LD HL,(406CH)
Fetch the pointer to the top of used RAM (held in memory location 406CH) and store it into Register Pair HL.
0217H
POP AF
Put the value held at the top of the STACK into Register Pair AF.
0218H
PUSH HL
Save the contents of Register Pair HL (which should be holding the pointer to the end of the line to be moved) to the top of the stack. This will be POPed into DE at 022EH.
0219H
CP 03H
Compare the value held in Register A against the end-of-line terminator 03H. Results: If Register A equals 03H, the Z FLAG is set.
021BH
If the Z FLAG (Zero) has been set then we are at EOL delimiter, so JUMP to the top of the READY LOOP (minus the READY prompt) at 01D8H to infinitely process another line of code.

If we are here then we did not hit the EOL delimiter. The next bunch of calls and math is first designed to make sure there is enough RAM to store the whole line, so HL is set up to be the highest RAM location needed to store the line.

021DH
ADD A,L
LET Register A = Register A + Register L.
021EH
LD L,A
Copy the contents of Register A into Register L. These 2 commands are basically HL = HL + A.
021FH
LD A,00H
Let Register A equal 00H.
0221H
ADC A,H
LET Register A = Register A + Register H.
0222H
LD H,A
Copy the contents of Register A into Register H.
0223H
LD DE,(406AH)
Fetch the value of the top of physical memory (held in memory location 406AH) and store it into Register Pair DE.
0227H
RST 20H
Call the routine at RST 20H to compare HL (the highest RAM address needed to store the line) and DE (the highest possible RAM location). Results: NZ means no match, Z means match. If H=D but L < E, then the C flag will be set.
0228H
Since the RST 20H in the prior instruction was testing to see if the byte we need to store in RAM exceeds the amount of free RAM or not, a NC means we are out of RAM. If the NC FLAG (No Carry) has been set, JUMP to 08F4H to display the "WHAT" error.
022BH
LD (406CH),HL
If we are here, then we still had enough RAM left and BC remains untouched so that it still points to the starting location of the text to move via the call at 0A77H. We still need to set up DE and HL for that call, so store the value held in Register Pair HL into memory location 406CH (which points to the top of used RAM), as HL is where the bytes from (BC) to (DE) will be moved to.
022EH
POP DE
Put the value held at the top of the STACK into Register Pair DE.
022FH
GOSUB to 0A77H to copy the bytes, backwards, from BC through DE to HL.
0232H
POP DE
Put the value held at the top of the STACK into Register Pair DE.
0233H
POP HL
Put the value held at the top of the STACK into Register Pair HL.
0234H
GOSUB to 0A6FH to copy the bytes held at (DE) to (BC), backwards, until DE = HL.
0237H
Jump to the top of the READY LOOP (minus the READY prompt) at 01D8H to infinitely process another line of code.

0239H - Clear the 10 bytes from 409DH to 40A6H and set Register Pair DE to 4200H.

0239H
LD B,0AH
Let Register B equal 0AH (Decimal: 10) for a DJNZ loop of 10 iterations.
023BH
PUSH HL
Save the contents of Register Pair HL to the top of the stack.
023CH
LD HL,409DH
Let Register Pair HL equal 409DH, which is the parse pointer saved when a STOP command is executed (current line being executed).
023FH
LD (HL),00H
Store 00H at the memory location pointed to by HL, setting current line number to 0000.
0241H
INC HL
Increment Register Pair HL by 1.
0242H
Loop back to 023FH, decrementing B each time, until B reaches zero.
0244H
LD DE,4200H
Set Register Pair DE to 4200H.
0247H
POP HL
Restore previous value of Register Pair HL from the stack.
0248H
RET
Return to the caller.

0249H - RESERVED WORD LOOKUP/VECTOR TABLE.

0249H
DEFM "LIST"
024DH
DEFW 8401H
The entry point for the LIST command is 0401H.
024FH
DEFM "RUN"
0251H
DEFW 838CH
The entry point for the RUN command is 038CH.
0249H
DEFM "NEW"
0257H
DEFW 8378H
The entry point for the NEW command is 0378H.
0259H
DEFM "CONT"
025DH
DEFW 83EBH
The entry point for the CONT command is 03EBH.
025FH
DEFM "CLOAD"
0264H
DEFW 8EE9H
The entry point for the CLOAD command is 0EE9H.
0266H
DEFM "CSAVE"
026BH
DEFW 8F3BH
The entry point for the CSAVE command is 0F3BH.
026DH
DEFM "NEXT"
0271H
DEFW 85A3H
The entry point for the NEXT command is 05A3H.
0273H
DEFM "LET"
0276H
DEFW 86B8H
The entry point for the LET command is 06B8H.
0278H
DEFM "INPUT"
027DH
DEFW 8623H
The entry point for the INPUT command is 0623H.
027FH
DEFM "IF"
0281H
DEFW 85FBH
The entry point for the IF command is 05FBH.
0283H
DEFM "ON"
0285H
DEFW 84FEH
The entry point for the ON command is 04FEH.
0287H
DEFM "GOTO"
028BH
DEFW 83B5H
The entry point for the GOTO command is 03B5H.
028DH
DEFM "GOSUB"
0292H
DEFB 84C4H
The entry point for the GOSUB command is 04C4H.
0294H
DEFM "RESET"
0299H
DEFB 8838H
The entry point for the RESET command is 0838H.
029BH
DEFM "RETURN"
02A1H
DEFB 84E6H
The entry point for the RETURN command is 04E6H.
02A3H
DEFM "READ"
02A7H
DEFB 86F9H
The entry point for the READ command is 06F9H.
02A9H
DEFM "RESTORE"
02B0H
DEFB 86CDH
The entry point for the RESTORE command is 06CDH.
02B2H
DEFM "REM"
02B5H
DEFB 85F6H
The entry point for the REM command is 05F6H.
0287H
DEFM "DATA"
02BBH
DEFB 85F6H
The entry point for the DATA command is 05F6H.
02BDH
DEFM "FOR"
02C0H
DEFB 8546H
The entry point for the FOR command is 0546H.
02C2H
DEFM "PRINT"
02C7H
DEFB 842FH
The entry point for the PRINT command is 042FH.
02C9H
DEFM "SET"
02CCH
DEFB 883CH
The entry point for the SET command is 083CH.
02CEH
DEFM "STOP"
02D2H
DEFB 83C5H
The entry point for the STOP command is 03C5H.
02D4H
DEFM "END"
02D7H
DEFB 8387H
The entry point for the END command is 0387H.
02D9H
DEFM "CLS"
02DCH
DEFB 84B5H
The entry point for the CLS command is 04B5H.
02DEH
DEFB 86B3H
That's the end of the single command reserved words. If none of the above reserved words were found, JUMP to 06B3H, which will process a variable assignment.
02E0H
"GOTO"
02E4H
DEFW 850FH
The entry point for the ON x GOTO command is 050FH.
02E6H
"GOSUB"
02EBH
DEFW 8517H
The entry point for the ON x GOSUB command is 0517H.
02EDH
DEFW 88C9H
If we were looking for a GOTO or GOSUB, and they weren't found, the JUMP here to 08C9H will display the "WHAT" error.
02EFH
"RND"
02F2H
DEFW 8E47H
The entry point for the RND command is 0E47H.
02F4H
"ABS"
02F7H
DEFW 8819H
The entry point for the ABS command is 0819H.
02F9H
"MEM"
02FCH
DEFW 8821H
The entry point for the MEM command is 0821H.
02FEH
"INT"
0301H
DEFW 882FH
The entry point for the INT command is 082FH.
0303H
"POINT"
0308H
DEFW 8840H
The entry point for the POINT command is 0840H.
030AH
DEFW 87F2H
030CH
DEFM "TO"
030EH
DEFB 8555H
The entry point for the TO command is 0555H.
0310H
DEFB 88C9H
0312H
DEFM "STEP"
0316H
DEFB 8560H
The entry point for the STEP command is 0560H.
0318H
DEFB 8565H
031AH
DEFM "TAB"
031DH
DEFB 849FH
The entry po