8-Bit Software

The BBC and Master Computer Public Domain Library

Back to 8BS Or Back to Disassembly


BASIC IV ROM Routines
Page Last Altered:


B4F1 NEXT

Submitted by Steve Fewell

Description:

Call routine &98F5 to set BASIC text pointer B to the BASIC text pointer A value, evaluate the variable name at
pointed to by BASIC text pointer B and obtain the address of the variable's value.

If A is not zero then the variable was valid and has been declared, so jump to &B4FF.

Otherwise, A contains zero (the zero flag is set) on return from &98F5 then the variable name is either not declared
or invalid; so, check the FOR level (&26). Set X to the current FOR level (from location &26).
If the FOR level is zero then issue 'No FOR' error (as this has priority over 'Syntax error'). If the carry flag is
not set then issue 'Syntax error' (as the variable name, after the NEXT keyword, was not declared - so it does not
match any active FOR-variable [This is strange, as I would have expected 'No such variable' to be issued instead!]).

If the carry flag is set then no valid variable name was found after the NEXT keyword, so jump to &B539 to process
the NEXT statement, as we have found a matching FOR statement (we already know that at least one FOR-loop is active;
otherwise, 'No FOR' error would have been issued above). X contains a pointer to the current FOR level (from location
&26), and, more importantly, X points to the details of the last FOR-statement on the FOR stack - therefore, &B539
will process the NEXT for the most recent FOR loop reached. Note: If a variable name is not present after the NEXT
keyword, BASIC assumes that a NEXT-statement without a variable is present, and matches the latest FOR loop. E.g. in the
case of the statement: 140 NEXT %    - the latest FOR loop will be processed, and 'Syntax error'
will be issued after the FOR loop is complete - after the NEXT statement has been processed!

[&B4FF] A variable name was found after the NEXT-keyword - and the variable has been declared. So, check the carry
flag. If the carry flag is set then the variable has a String value - so issue 'Syntax error' as a FOR-variable cannot
be a String.

Set X to the FOR level (from location &26).
If X is zero, then there are no active FOR loops, so issue 'No FOR' error, as the NEXT statement does not have a matching
FOR-statement.

[&B505] Compare the variable's address (stored in locations &2A-&2B) and type (location &2C) with the
3-byte FOR-variable details on the FOR stack (pointed to by X) for the latest FOR-loop (starting at
location: &0519 + X, and ending at location: &051B + X).
If the variable matches the variable for the FOR loop on the stack (pointed to by X) then we have found a matching FOR
loop for the variable, so jump to &B539 to process the NEXT statement.

[&B51A] Otherwise, Subtract #&0F (15) from X, so that X now points to the previous FOR-loop on the FOR
stack.
Store X back to location &26 - to update the FOR stack. This will in effect cancel the most recent FOR loop - as
the NEXT statements are not allowed to be in different orders, so the inner-most loop will be cancelled. I.e.:
10 FOR I = 1 TO 10
20 FOR K = 1 TO 10
30 PRINT I,K
40 NEXT I
50 NEXT K

At line 40, the 'K'-FOR loop will be cancelled, so 'No FOR' error will be issued at line 50. This behaviour makes sense,
as otherwise, BASIC would be forced to jump back into the 'FOR I...'-loop when the 'NEXT K' statement is executed, which
would cause problems.

If X is not zero then jump back to &B505, to compare the FOR-variable of the FOR loop (on the FOR stack) pointed
to by X. Otherwise, the FOR-variable couldn't be matched with any of the FOR loops on the FOR-stack, so issue
'Can't match FOR' error.

[&B539] We have found a corresponding FOR-loop
X points to the details of the matching FOR-loop on the FOR-stack.
Store the start address of the variable's value (from the FOR-stack locations &0519 + X and &051A + X) in
locations &2A (LSB) and &2B (MSB of address).

Check the variable's type (at location &051B + X on the FOR-stack).

If the variable is a Floating-point variable (the variable type is 5 (as a Float is a 5-byte value)), then:
* [&B5C0] Call routine &B1C7 to load the FWA with the FOR-variable's value (pointed to by &2A-&2B)
* Add #&1C to the X value to obtain a pointer to the Floating-Point STEP value for the FOR loop on the
    FOR-stack. Store this LSB pointer in location &4A and set the Most significant byte of the STEP value
    location to #&05 (stored in &4B).
* Add the Floating-Point STEP value (pointed to by &4A-&4B) to the FWA (FOR-Variable value).
* Set &37-&38 to &2A-&2B (i.e. the address of the FOR-Variable's value.
* Call routine &B369 to store the FWA value to the 5-byte location starting at the address pointed to
    by &37-&38.
* Load X with the value at location &26 (the current FOR level)
* Add #&21 to X and store the result in location &4A. This is the LSB of the FOR-loop's TO value
    Note: &4B still contains #&05 (the MSB value). This will update the FOR-Variable value.
* Call routine &9C8F to unpack the Floating-Point value pointed to by &4A-&4B to the FWB and compare
    the FWB value with the FWA value.
* If the values are equal then we have not exceeded the TO-value yet (but should do when the STEP value is
    next added to the FOR-Variable's value), so jump to &B59E to repeat the FOR-loop
    again.
* Check the second byte of the STEP value (at location &051D + X), which contains the STEP value's sign.
* If the STEP value is negative, and the carry flag is set (FOR-Variable (FWA) > TO value (FWB)), then jump
    to &B5AE to exit the FOR-loop; otherwise, jump to &B59E to continue the FOR-loop.
* If the STEP value is positive, and the carry flag is clear (FOR-Variable (FWA) < TO value (FWB)), then jump
    to &B5AE to exit the FOR-loop; otherwise, jump to &B59E to continue the FOR-loop.
Otherwise, the variable is an Integer variable (the variable type is 4 (as an Integer is a 4-byte value)), so:
* [&B54A] Add the STEP value to the current value of the FOR-variable (pointed to by &2A-&2B).
    The 4-byte STEP value starts at location &051C + X on the FOR-Stack [LSB value] and finishes at &051F + X.
    The result of the addition is stored as the FOR-variable's value, and also in locations &37-&39 and Y.
* [B571] Subtract the 4-byte TO-value (stored on the FOR-stack starting at location &0521 + X and ending
    at location &0524 + X), from the FOR-variable's current value (stored in locations &37-&39 and Y).
         To do the subtraction, firstly, the TO-value's LSB is subtracted and the result is stored in &37.
         next, the TO-value's next significant byte is subtracted and the result Tests and Sets (TSB) bits in &37.
         next, the TO-value's next significant byte is subtracted and the result Tests and Sets (TSB) bits in &37.
         next, lastly, the TO-value's Most significant byte (MSB) is subtracted and the result is OR-ed (ORA) with &37.
         Note: the Test and Set bits (TSB) operation is effectively the same as ORA - except that the result is stored to
                  memory.
* If location &37 contains zero, then the TO-value is the same as the FOR-variable's current value,
    so jump to &B59E to repeat the FOR-loop again (as we have not exceeded the TO-value yet!).
* Check the sign (top bit of the MSB value) of the STEP value and the TO value and the FOR-Variable value (Y).
      This is done as follows:
              Result = (FOR-Variable's MSB) EOR (MSB of the STEP value) EOR (MSB of the TO value)
      
       The result will be determined from the sign of the STEP, TO and (new) FOR-Variable values as follows:
         FOR-Variable-sign    STEP-sign    TO-sign    Result
         -----------------    ---------        -------    ------
         Pos................          Pos......        Pos....      Pos
         Pos................          Pos......        Neg....      Neg
         Pos................          Neg......        Pos....      Neg
         Pos................          Neg......        Neg....      Pos
         Neg................          Pos......        Pos....      Neg
         Neg................          Pos......        Neg....      Pos
         Neg................          Neg......        Pos....      Pos
         Neg................          Neg......        Neg....      Neg
      
      This result determines how we should handle the subtraction result. If the result is positive, then
      if the result of (FOR-Variable - TO-value) is less than 0 then we have exceeded the TO value;
      otherwise, if the result of (FOR-Variable - TO-value) is more than 0 then we have exceeded the TO value.
      
* If the EORed-sign result is positive (Most significant bit not set), then check the carry flag. If the carry flag
    (after the subtraction) is not set then repeat the FOR-loop again, as we haven't exceeded the TO-value
    yet, so jump to &B59E to repeat the FOR loop again. Otherwise, if the Carry-flag is set then we have
    exceeded the TO-value, so jump to &B5AE to exit the FOR-loop.
* If the EORed-sign result is negative (Most significant bit is set), then check the carry flag. If the carry flag
    (after the subtraction) is set then we haven't exceeded the TO-value yet, so jump to &B59E
    to repeat the FOR loop again. Otherwise, if the Carry-flag is clear then we have exceeded the TO-value,
    so jump to &B5AE to exit the FOR-loop.

[&B59E] Repeat the FOR-loop again
We have not exceeded the TO-value yet, so jump back to the first statement within the FOR-loop and begin executing
that statement. To do this, first set BASIC Text pointer A (&0B-&0C) to the Program address following the
FOR-statement (from the FOR-stack locations &0526 + X and &0527 + X, call routine &9BC6 to set the BASIC
Text Pointer A offset (&0A) to 1 and check for [Escape-Key]-pressed condition (if Escape is pressed, then issue
'Escape' error.), and jump to &900B to execute the first statement of the FOR-loop again.

[&B5AE] Exit the FOR-loop
Subtract #&0F (15) from the FOR level (in X) and store the new value back to &26, so that &26 now points
to the FOR-loop before the one we have just exited from (if one exists).
Set BASIC Text pointer A offset to the BASIC Text pointer B offset (to update the BASIC text pointer A so that it
points to the Program Code following the NEXT-statement.
If the next character (pointed to by BASIC text pointer A) is a comma ',', then jump back to the start of the NEXT
routine - &&B4F1, (as the NEXT statement includes multiple FOR-variables) to process the NEXT for the next
FOR-Loop.
Otherwise (comma not found), jump to &9000 to issue for 'Syntax error' if end of statement wasn't found and execute
the next program statement.


Disassembly for the NEXT routine

B4F1   032 245 152 20 F5 98 JSR &98F5 PtrB=PtrA & evaluate variable name & obtain address of value
B4F4   208 009 D0 09 BNE 9 --> &B4FF
B4F6 & 166 038 A6 26 LDX &26
B4F8 8 240 056 F0 38 BEQ 56 --> &B532 'No FOR' error
B4FA = 176 061 B0 3D BCS 61 --> &B539 We have found a matching FOR-statement, so process the NEXT-statement
B4FC Li 076 105 155 4C 69 9B JMP &9B69 Syntax error
B4FF   176 251 B0 FB BCS -5 --> &B4FC    issue 'Syntax error'
B501 & 166 038 A6 26 LDX &26
B503 - 240 045 F0 2D BEQ 45 --> &B532 'No FOR' error
B505 * 165 042 A5 2A LDA &2A
B507   221 025 005 DD 19 05 CMP &0519,X
B50A   208 014 D0 0E BNE 14 --> &B51A
B50C + 165 043 A5 2B LDA &2B
B50E   221 026 005 DD 1A 05 CMP &051A,X
B511   208 007 D0 07 BNE 7 --> &B51A
B513 , 165 044 A5 2C LDA &2C
B515   221 027 005 DD 1B 05 CMP &051B,X
B518   240 031 F0 1F BEQ 31 --> &B539 We have found a matching FOR-statement, so process the NEXT-statement
B51A   138 8A TXA
B51B 8 056 38 SEC
B51C   233 015 E9 0F SBC#&0F
B51E   170 AA TAX
B51F & 134 038 86 26 STX &26
B521   208 226 D0 E2 BNE -30 --> &B505 Compare the next FOR loop's variable
B523   'Can't match FOR' error
B532   'No FOR' error
B539   189 025 005 BD 19 05 LDA &0519,X
B53C * 133 042 85 2A STA &2A
B53E   189 026 005 BD 1A 05 LDA &051A,X
B541 + 133 043 85 2B STA &2B
B543   188 027 005 BC 1B 05 LDY &051B,X
B546   192 005 C0 05 CPY#&05
B548 v 240 118 F0 76 BEQ 118 --> &B5C0 Increment FOR-variable & Check for end of FOR-loop (FOR-variable is Float)
B54A * 178 042 B2 2A LDA (&2A)
B54C } 125 028 005 7D 1C 05 ADC &051C,X
B54F * 146 042 92 2A STA (&2A)
B551 7 133 055 85 37 STA &37
B553   160 001 A0 01 LDY#&01
B555 * 177 042 B1 2A LDA (&2A),Y
B557 } 125 029 005 7D 1D 05 ADC &051D,X
B55A * 145 042 91 2A STA (&2A),Y
B55C 8 133 056 85 38 STA &38
B55E   200 C8 INY
B55F * 177 042 B1 2A LDA (&2A),Y
B561 } 125 030 005 7D 1E 05 ADC &051E,X
B564 * 145 042 91 2A STA (&2A),Y
B566 9 133 057 85 39 STA &39
B568   200 C8 INY
B569 * 177 042 B1 2A LDA (&2A),Y
B56B } 125 031 005 7D 1F 05 ADC &051F,X
B56E * 145 042 91 2A STA (&2A),Y
B570   168 A8 TAY
B571 7 165 055 A5 37 LDA &37
B573 8 056 38 SEC
B574 ! 253 033 005 FD 21 05 SBC &0521,X
B577 7 133 055 85 37 STA &37
B579 8 165 056 A5 38 LDA &38
B57B " 253 034 005 FD 22 05 SBC &0522,X
B57E 7 004 055 04 37 TSB &37
B580 9 165 057 A5 39 LDA &39
B582 # 253 035 005 FD 23 05 SBC &0523,X
B585 7 004 055 04 37 TSB &37
B587   152 98 TYA
B588 $ 253 036 005 FD 24 05 SBC &0524,X
B58B 7 005 055 05 37 ORA &37
B58D   240 015 F0 0F BEQ 15 --> &B59E Repeat the FOR-loop again
B58F   152 98 TYA
B590 ] 093 031 005 5D 1F 05 EOR &051F,X
B593 ]$ 093 036 005 5D 24 05 EOR &0524,X
B596   016 004 10 04 BPL 4 --> &B59C If carry set then Exit FOR loop otherwise repeat FOR-loop
B598   176 004 B0 04 BCS 4 --> &B59E Repeat the FOR-loop again
B59A   128 018 80 12 BRA 18 --> &B5AE Exit the FOR-loop
B59C   176 016 B0 10 BCS 16 --> &B5AE Exit the FOR-loop
B59E & 188 038 005 BC 26 05 LDY &0526,X
B5A1 ' 189 039 005 BD 27 05 LDA &0527,X
B5A4   132 011 84 0B STY &0B
B5A6   133 012 85 0C STA &0C
B5A8   032 198 155 20 C6 9B JSR &9BC6 Set PTR A Offset to 1 & Check for Escape error condition
B5AB L 076 011 144 4C 0B 90 JMP &900B Process next BASIC program statement
B5AE   138 8A TXA
B5AF 8 056 38 SEC
B5B0   233 015 E9 0F SBC#&0F
B5B2 & 133 038 85 26 STA &26
B5B4   164 027 A4 1B LDY &1B
B5B6   132 010 84 0A STY &0A
B5B8   032 229 140 20 E5 8C JSR &8CE5 Compare next non-space [PTR A] character with ','
B5BB 8 208 056 D0 38 BNE 56 --> &B5F5 Start processing the next Program statement
B5BD L 076 241 180 4C F1 B4 JMP &B4F1 Check whether there are any additional NEXT statements to process
B5C0   032 199 177 20 C7 B1 JSR &B1C7 Load FWA with Floating-Point Value (ain)
B5C3   138 8A TXA
B5C4   024 18 CLC
B5C5 i 105 028 69 1C ADC#&1C
B5C7 J 133 074 85 4A STA &4A
B5C9   169 005 A9 05 LDA#&05
B5CB K 133 075 85 4B STA &4B
B5CD   032 141 166 20 8D A6 JSR &A68D Floating-Point Addition [FWA=argp+FWA]
B5D0 * 165 042 A5 2A LDA &2A
B5D2 7 133 055 85 37 STA &37
B5D4 + 165 043 A5 2B LDA &2B
B5D6 8 133 056 85 38 STA &38
B5D8 i 032 105 179 20 69 B3 JSR &B369 Store the FWA value to the variable's memory address
B5DB & 166 038 A6 26 LDX &26
B5DD   138 8A TXA
B5DE   024 18 CLC
B5DF i! 105 033 69 21 ADC#&21
B5E1 J 133 074 85 4A STA &4A
B5E3   032 143 156 20 8F 9C JSR &9C8F Unpack argp to the FWB and compare it's value with the FWA value
B5E6   240 182 F0 B6 BEQ -74 --> &B59E Repeat the FOR-loop again
B5E8   189 029 005 BD 1D 05 LDA &051D,X
B5EB 0 048 004 30 04 BMI 4 --> &B5F1 If carry set then Exit FOR loop otherwise repeat FOR-loop
B5ED   176 175 B0 AF BCS -81 --> &B59E Repeat the FOR-loop again
B5EF   128 189 80 BD BRA -67 --> &B5AE Exit the FOR-loop
B5F1   144 171 90 AB BCC -85 --> &B59E Repeat the FOR-loop again
B5F3   128 185 80 B9 BRA -71 --> &B5AE Exit the FOR-loop
B5F5 L 076 000 144 4C 00 90 JMP &9000   Check end of statement & execute the next statement on the Command/Program line

 


 Back to 8BS
Or