Authors
Publication
Pub Details
Date
Pages
In my article “Automatically Set RAMTOP Without Destroying The Program” published in the July-August issue, the GOSUB stack was very briefly discussed. This article will delve more deeply into this subject. I will also cover how to determine the extent of the “Safe Area” in the TS 1000 and 1500. The safe area determines the amount of bytes you can lower RAMTOP without interfering with the execution of the BASIC program. The safe area can be used for the temporary storage of data or machine code, without lowering RAMTOP. The safe area extends from the top of the Calculator stack to the bottom of the Machine stack.
There are three stacks in the upper – RAM memory; the Calculator stack (C stack) the Machine stack (M stack), and the GOSUB stack (GS stack). All of these stacks are used by the routines in the ROM to store temporary data and variables. An item in the GS or M stacks consists of two bytes. The low byte is in the lower address and the high byte is in the next higher address. Items are added to the bottom of either the GS or M stacks. In the TS 1000 and 1500, the GS stack is located immediatly below RAMTOP and above the M stack.
In the RAMTOP article we examined the four addresses below RAMTOP, using the PEEK command. A diagram of the values found in these four addresses is in Figure No. 1. In the same manner we examined the contents of the system variable ERR_SP and found that it pointed to the address RAMTOP-4. The TS 1500 Users Manual defines the system variable ERR SP as the address of the first item on the M stack. The bottom of the GS stack is this address plus two (2). The Stack Pointer (SP) consists of two internal registers. The contents of the SP registers normally point to the address of the low byte of the last effective item on the M stack. The SP registers cannot be addressed from BASIC. Even using machine code, the contents of the SP registers cannot be determined immediately after the computer is turned on. For example, enter the following into your computer:
1 REM 1234567
10 RAND USR 16516
20 PRINT PEEK 16514+256%* PEEK 16515
then:
Z80 assembler
POKE 16516,237 ED : prefix
POKE 16517,115 LD(NN),SP : Let 16514 and
POKE 16518,130 N : 16514=cont-
POKE 16519,64 N : tents of SP
POKE 16520,201 RET : Return to
: Basic
Now RUN the program. The result on _ the screen is the address at which the SP registers are pointing after calling the machine code USR function. You can see that the function itself uses the M stack. Then how do I know that immediately after turning on the computer, the contents of the SP registers is the address of RAMTOP-4? Only by deduction from the disassembly of the ROM, GOSUB and RETURN routines. They would not work unless the SP registers were pointing to RAMTOP-4. The address in the ROM of the GOSUB routine is 3765d and of the RETURN routine is 3800d.
Figure No. 1 shows the’ situation after the computer is intialized and after each BASIC line has been executed. The one exception that I know about is after one or more GOSUB commands and before any RETURN command. For an example of the exception, enter the following lines into the computer (after entering NEW):
10 GOSUB 20
20 STOP
RUN the program. Using immediate commands, PEEK into each of the addresses from RAMTOP-1 to RAMTOP-6. Also PEEK the two bytes of ERR_SP, using the immediate command PRINT PEEK 16386+256*PEEK 16387. Your results should agree with the values’ shown in Figure No. 2. We must assume that the SP registers are also pointing to RAMTOP-6 as the ROM RETURN command routine would not work if this were not true. Looking at Figure No. 2, you can see how the GOSUB command has slipped the GOSUB line number plus one onto the bottom of the GS stack, moving the first item of the M stack down two addresses. A GOSUB line number plus one, once used, is written over by moving the first item on the M stack up two addresses and changing the pointers SP and ERR_SP. For example enter NEW and then enter the following lines into the computer:
10 GOSUB 30
20 STOP
30 PRINT "THE RETURN REMOVES THE GOSUB LINE NUMBER +1 FROM THE GS STACK"
40 RETURN
RUN the program. If you PEEK the four addresses below RAMTOP and ERR_SP you will find that their contents are again the same as Figure No. 1. If the two bytes of the first item on the GS stack (0 and 62) and the two bytes of the first item of the M stack (118 and 6) are in conjunction as in Figure No. 1, and a RETURN command is encountered in the BASIC program, then an error report 7 (RETURN without a corresponding GOSUB) is generated. The ROM routine tests only for the high byte 62. As 62*256=15872, this is beyond the normal maximum line number 9999. It is possible to use higher line numbers by working from the top of the program and POKEing 16509 with the high byte of the line number and POKEing 16510 with the low byte as each line is entered with a normal line number. In this case, line numbers with a high byte of 62 must not be used with a GOSUB command. If the two bytes of the first item on the GS stack and two bytes of the first item on the M stack are seperated by the two bytes of a GOSUB line number+1, then the next line after the GOSUB line is executed when the RETURN command is encountered.
What is that 118 and 6? To find out, we know that an item on the M stack consists of two bytes, the low byte in the lower address and the high byte in the higher address. So 118+256*6=1654. The addresses in the ROM run from 0 to 819d. Let us use the 1654 as an address in a machine code program and see what happens.
1 REM 123
10 RAND USR 16514
20 PRINT "THE ADDRESS 1654 STARTS THE EXECUTION OF THE NEXT BASIC LINE OF THE PROGRAM"
Now in the immediate mode, POKE the following into the REM line:
POKE 16514,195 JP NN : GOTO
POKE 16515,118 N : 118+
POKE 16516,6 N : 256*6=1654
RUN the program and you will see the answer on the screen. Note that using a 118 in the machine code messes up the display, but the program still runs.
Since the M stack expands downward in memory as items are added to it or to the GS stack and then, in effect, contracts as items on the stacks are no longer needed, but not withdrawn, a trail of garbage is left behind. This garbage is written over the next time the stack expands. Turn off your computer and then power up again. Using the immediate command, PEEK into the address that is the value of your RAMTOP minus 50. You should find 129. PEEKing below this address you will find only zeros. (Unless you PEEK all the way down to the top of the Calculator stack. This means that in the intialization ROM routine, the M stack was expanded down to this address. Now enter and run the following program, changing line 10 to the applicable values for your RAM memory:
10 FOR N=(your RAMTOP-50) TO (your RAMTOP-5)
20 POKE N,0
30 PRINT PEEK N;" ":
40 NEXT N
What happens is that between the time 0 is poked into the M stack and the value at address N is peeked, the M stack is being used by the ROM routines which are much faster than BASIC. PEEK again, using the immediate command, into the address of your RAMTOP-50. Once again the value at that address is not O but 129. Peeking below that address there are only zeros. From this we can deduce that coming out of a BASIC program, the ROM routines use the M stack down to RAMTOP-50 and that the little program did not expand the M stack below this point. So the upper limit of the safe area for this program is: RAMTOP-51.
Products
Downloadable Media
Image Gallery
Source Code
Note: Type-in program listings on this website use ZMAKEBAS notation for graphics characters.