You can avoid stacking up too many subroutines by using POP to cancel a GOSUB (command that sends control to a subroutine at a given line number and then RETURNs to the statement after GOSUB). A programming tool for all PET/CBM computers.
Atari BASIC and the Microsoft BASIC used on the Apple II provide a rather useful command called POP. The POP command removes the last GOSUB from the stack, so that a RETURN will return the program to the second-to-last GOSUB. For example, in this program:
10 GOSUB100 20 PRINT "CONTROL RETURNS HERE." 30 STOP 100 GOSUB200 110 PRINT "NOT HERE." 120 STOP 200 POP 210 PRINT "GOING" 220 RETURN
the RETURN on line 220 returns the program to line 20 (not 110). This utility can be very useful, but it is not available in Commodore BASIC. Well, it wasn't.
Here is a machine language utility that executes a POP on all PET/CBM models. The code is position independent – in other words, it can be moved to any convenient spot in memory without any changes. I prefer to locate the code at the top of memory. A POKE 53,127:POKE 52,0:CLR (for 32K systems) will prevent BASIC from using this space.
Program 1 provides the machine language routine in the form of a BASIC loader. The program will load and protect the POP routine, and then indicate the proper SYS location to call the routine. Programs 2 and 3 provide changes for older ROMs.
A GOSUB in BASIC pushes five bytes onto the system stack. These bytes tell BASIC where to start running when the RETURN statement is executed. These five bytes are the low and high bytes of the CHRGET pointer (locations 119 and 120 for newer ROMs, 221 and 222 for Original ROMs) and the current line number (locations 54 and 55 for newer ROMs, 136 and 137 for Original ROMs), and the token for GOSUB (141). To perform a POP, all we do is remove these five bytes from the stack. The routine uses the same subroutine that BASIC uses (JSR $B322 for BASIC 4.0, JSR $C2AA for Upgrade BASIC, JSR $C2AC for Original BASIC) to search the stack for the GOSUB token. The subroutine loads the accumulator with the token found at the top of the stack. We compare it to 141 to see if we have located a GOSUB. If a GOSUB is not found, then an error is returned. The error message sent is "?without gosub error in xxxx". Notice that the standard BASIC error routine is used, so program and variable integrity are assured. The five PLAs simulate the action of a RETURN without really doing anything.
This utility is especially useful in highly "modular" programs. An error handling subroutine can easily remove "pending" GOSUBs from the stack to prevent them from building up (and resulting in an "?out of memory error").
To use this POP in the preceding program, change the POP in line 200 to a SYS 32512, or whatever SYS location the loader indicates should be used. The program does not change in any other way.
Program 1: BASIC 4.0 Version
10 POKE53, PEEK (53) - 1 : POKE 52, 0: CLR 20 SADR = PEEK (52) + PEEK (53) * 256 30 FOR ADDR = SADR TO SADR + 22 40 READ DTTA : POKE ADDR, DTTA : NEXT ADDR 50 PRINT "USE SYS "; SADR 60 END 70 DATA 169, 255, 133, 71, 32, 34, 179, 201 80 DATA 141, 240, 5, 162, 29, 76, 207, 179 90 DATA 154, 104, 104, 104, 104, 104, 96
Program 2: Make These Changes For Upgrade BASIC
70 DATA 169, 255, 133, 71, 32, 170, 194, 201 80 DATA 141, 240, 5, 162, 29, 76, 87, 195
Program 3: Make These Changes For Original BASIC
70 DATA 169, 255, 133, 71, 32, 172, 194, 201 80 DATA 141, 240, 5, 162, 29, 76, 89, 195