4

I was always under the impression that MS BASIC implemented NEXT by pushing the address of the FOR on the stack. So convinced that when I read the source code I assumed CURLIN had to be referring to the address. Quelle surprise!

So does anyone know why they didn't point to the line's address, or at least the statement after it? MS didn't allow self-modification, and one could have made this an instance where CONT wouldn't be allowed. It seems this would also offer a significant performance boost and (very slightly) reduce code size as well.

Am I missing something obvious?

9
  • Insert a line before the for loop and that adress need to be recalculated, after first finding it somewhere in the code. There might be hundreds of for-next loops that need to be corrected
    – UncleBod
    Aug 9, 2019 at 16:07
  • 1
    Any edits in "stop mode" to the structure of the program negate CONT. So this is already not possible. Aug 9, 2019 at 16:12
  • MS was probably imitating Dartmouth Basic. Aug 9, 2019 at 17:38
  • 1
    I think you should recheck your analysis. The TRS-80 (Z-80) version of Microsoft Basic keeps a stack for FOR/NEXT loops which includes a pointer to the exact point to continue execution. I doubt the 6502 version diverges that much. It might still track the line number, too, so it can report errors. If only the line number is stored then it is hard to see how "10 FORI=1TO4:FORJ=1TO5 20 NEXT:NEXT" works. Aug 9, 2019 at 19:08
  • 2
    A line with a FOR/NEXT loop can have other code on the line both before and after the FOR/NEXT. Pointing to the line's address is insufficient.
    – Tim Locke
    Aug 9, 2019 at 19:08

1 Answer 1

10

Your initial interpretation was correct -- Microsoft Basic is storing the address of the first statement of the FOR/NEXT loop. But it is also storing the line number of the first statement. See the comment at the top of flow1.s:

; ----------------------------------------------------------------------------
; "FOR" STATEMENT
;
; FOR PUSHES 18 BYTES ON THE STACK:
; 2 -- TXTPTR
; 2 -- LINE NUMBER
; 5 -- INITIAL (CURRENT)  FOR VARIABLE VALUE
; 1 -- STEP SIGN
; 5 -- STEP VALUE
; 2 -- ADDRESS OF FOR VARIABLE IN VARTAB
; 1 -- FOR TOKEN ($81)
; ----------------------------------------------------------------------------

In eval.s we see the code that happens when a NEXT continues the loop. The current line and the pointer to the next statement are copied off the stack into their zero page variables. Then it jumps to NEWSTT to continue execution at TXTPTR.

        sbc     STACK+BYTES_FP+4,x
        beq     L2C22
        lda     STACK+2*BYTES_FP+5,x
        sta     CURLIN
        lda     STACK+2*BYTES_FP+6,x
        sta     CURLIN+1
        lda     STACK+2*BYTES_FP+8,x
        sta     TXTPTR
        lda     STACK+2*BYTES_FP+7,x
        sta     TXTPTR+1
L2C1F:
        jmp     NEWSTT

The current line isn't really needed unless an error occurs at which point BASIC will want to report the line where the error was triggered.

5
  • I would think that it would be more helpful to keep a pointer to the start of the current line rather than the line number, since (1) the line number can easily be fetched given a start-of-line pointer, and (2) line-link pointers could allow the skip-to-next-line required for "REM" or "IF THEN" to be processed without having to scan for the next zero byte. I wonder if line-link pointers were designed in after the logic for skip-to-next-line?
    – supercat
    Aug 12, 2019 at 15:53
  • AHHHHHH! That definitely explains it! Aug 12, 2019 at 16:04
  • BTW, is the last byte the token of the command? If so, any idea why? Aug 12, 2019 at 16:15
  • It uses a single stack to track FOR loops and GOSUB. A NEXT will skip over GOSUB entries in the stack to find a FOR record as will a RETURN skip over FOR entries. This program will generate a "next without for" message. 10 GOSUB 30 | 20 NEXT N:END | 30 FOR N=1 TO 2:PRINT N:RETURN Aug 13, 2019 at 19:05
  • @supercat You may be right. BASIC is ROM is generally optimized for code size over speed so perhaps the choice was made to keep the code as small as possible. I'd think the link pointers were an early feature because without them BASIC would be slowed down considerably. Aug 13, 2019 at 19:12

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .