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?

  • 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 at 16:07
  • 1
    Any edits in "stop mode" to the structure of the program negate CONT. So this is already not possible. – Maury Markowitz Aug 9 at 16:12
  • MS was probably imitating Dartmouth Basic. – Walter Mitty Aug 9 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. – George Phillips Aug 9 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 at 19:08
9

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.

  • 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 at 15:53
  • AHHHHHH! That definitely explains it! – Maury Markowitz Aug 12 at 16:04
  • BTW, is the last byte the token of the command? If so, any idea why? – Maury Markowitz Aug 12 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 – George Phillips Aug 13 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. – George Phillips Aug 13 at 19:12

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.