MANIPULATING STRINGSMore power and speed from BASIC
by BRIAN WEISS
Learn how to manipulate the Variable Name Table and Variable Value table in your BASIC programs. Professional programmers use these powerful techniques to add speed and variety to their code. The BASIC listings work with all Atari computers of any memory size.
If you program in BASIC, you've almost certainly
used string variables to store and manipulate character strings. In this
article, we'll see how Atari BASIC handles string variables. Then we'll
show you how to use this information to harness the impressive power and
speed of string manipulation in Atari BASIC.
These techniques come in handy whenever you have to move or modify a large area of memory. Some possible applications are: redefining character sets, changing display lists, manipulating machine language programs from BASIC, moving players in Player/Missile graphics, and changing screen memory for animation or page flipping.
Atari BASIC uses two tables to keep track of the variables in your program: the Variable Name Table and the Variable Value Table.
The Variable Name Table holds the names of all the variables used in your program. It also tells the computer if a variable contains a string, a number, or a numeric array.
The Variable Value Table records the size and contents of each variable.
Whenever you use a new variable, whether it's in a program or a direct command, the computer updates both tables. Moreover, when you SAVE a program to disk or cassette, the tables are saved as well. Both tables will remain in memory until you LOAD another program, issue a NEW command, or turn off the computer.
The location of these tables in memory depends upon the length of your program. To find them, we check the contents of four special memory locations which point to the start of the tables. These are:
VNTP= PEEK (130) + PEEK (131) *256
VVTP=PEEK (134) + PEEK (135) *256
VNTP is the starting address of the Variable Name Table and VVTP is the starting address of the Variable Value Table.
The Variable Name Table stores the names of all variables in the order they appear in your program listing. It also stores the type of each variable (string, numeric, or numeric array).
Listing 1 displays the contents of the Variable Name Table in a readable format. The subroutine in lines 1000 through 2005 can be appended to any BASIC program for a listing of the variables used. Type in Listing 1, check it with TYPO II and SAVE a copy.
The Variable Value Table tells the computer where to find the contents of each variable. It also contains the size of each variable. It uses eight bytes per variable to store this information. We'll refer to these bytes as byte one, byte two, etc.
Byte one determines whether the variable represents a string or a number. (A 129 in this location would denote a string variable.)
Byte two is a reference number (0 through 127) assigned to that variable. This is the number which the computer uses to identify each variable.
Byte three and byte four tell the computer where it can find the contents of the variable.
Byte five and byte six contain the length of the variable, and byte seven and byte eight contain the maximum size of the variable. In the case of string variables, this value is equal to its dimensioned length. For example, consider the BASIC line:
10 DIM A$(12):A$="ABC"
In this case, A$ is three characters long, but its maximum
size is 12.
Interpreting bytes three through eight requires an understanding of how the computer stores numbers in memory locations. A single memory location can only store numbers between 0 and 255. The computer breaks up larger numbers into two parts and uses two memory locations to store them.
The first location contains the number of 256's in the number. Programmers refer to this as the "high byte" of a number. The second location, the "low byte," contains the rest of the number.
To calculate the size of a string variable, we multiply byte five by 256 and add byte six. We used the same method to calculate the starting addresses of the Variable Name Table (VNTP) and the Variable Value Table (VVTP) at the beginning of this article.
Finding the location of a variable in memory is slightly more complicated. Strings and arrays are stored in the String and Array Table. Byte three and byte four contain a pointer, or "offset value" used to locate a variable in this table.
First, multiply byte three by 256, and add byte four to determine this offset value. Now, add this to the starting address of the String and Array Table. This address can be found with the equation: STARP = PEEK (140) + PEEK (141) * 256. The final value is the actual address of the string. You could also find this address with BASIC's ADR function.
The location of the String and Array Table varies with the size of your BASIC program. For this reason, references to this table should only be done under program control, not through direct commands.
Listing 2 will display the values of byte one through byte eight for each string variable in the Variable Value Table.
Listing 3 takes the same information and interprets it for you, printing the actual size and location of each string variable in the program. Both of these listings should be checked with TYPO II and SAVEd before you RUN them.
Searching through the variable tables for information about a particular variable is a complicated, error-prone, and often unnecessary procedure. We can easily design and build our own variable tables, if we follow one simple rule: The order of variables in the tables must be the same as the physical order of the variables in your program. Consider the following program:
10 DIM A$(3):A$="ABC"
20 GOSUB 900
30 DIM B$(3):B$="DEF"
900 DIM C$(3):C$="GHI"
In this program, A$ will be the first variable in the variable
tables because it's the first variable in the program. B$ will be the second,
and C$ will be the third. (Note that the computer builds the variable tables
according to the physical order of variables in your program, NOT the logical
If you want to manipulate a variable through the variable tables, it's wise to declare that variable in the first line of your program. This places it at the-top of your variable tables.
Remember to type NEW before typing in your program to assure that no information is left in the tables from earlier programs or direct commands.
If you forgot to do this, you can LIST the programs to disk or cassette, type NEW, and ENTER the program again. Do not use SAVE and LOAD since these commands save the variable tables along with the program.
Both variable tables are in RAM which means that their contents can be changed using BASIC's POKE statement.
For example, suppose we wanted to change the name of the first variable used in Listing 1 from A$ to B$. Since A$ is the first variable used, it will be at the beginning of the table and its name will be in location VNTP. LOAD in Listing 1 and then type:
POKE VNTP, ASC ("B")
Now LIST the program. All references to A$ are now B$.
VALUE TABLE CHANGES
More powerful effects can be achieved by changing the Value Table. By changing a string variable's entry in this table, we can position it anywhere in memory. We can also change its size.
If we place our string variable in a region of memory used for other purposes, we can use it to change those memory locations. For example, if we relocate a string variable to an area reserved for Player/Missile graphics, we can control the players with several well-placed POKEs to the variable tables.
To do this, of course, you'd need a working knowledge of Player/Missile graphics, and that's beyond the scope of this article. Instead, we'll relocate a string variable to screen memory. In this way, we'll change what's on the screen by changing the appropriate entries in the Variable Value Table.
Recall that the Variable Value Table contains information about the location of string variables. This information is kept in bytes three and four in the table. In Listing 3, A$ is the first variable dimensioned. Since its byte one value is in memory location VVTP, its byte three value can be found by PEEKing (VVTP + 2), and its byte four value is in (VVTP + 3).
Let's move A$ to screen memory. The address of the beginning of screen memory is calculated in line 100 of listing 3, and stored in the variable SCRN.
Next, we use SCRN to calculate A$'s new byte three and byte four values for the Variable Value table. Use the following formulas:
Offset = (new location)- (PEEK(140)-PEEK (141) * 256)
Byte four = INT (Offset/256)
Byte three = Offset- Byte four * 256
Lines 150-170 perform these calculations. These new values
are POKEd into the Variable Value table in line 200. These POKEs slide
the contents of the string variable into screen memory.
Lines 250-290 change the variable's size by altering the values for bytes five and six in the Variable Value Table. We can calculate the new values with these formulas:
Byte six = INT (size/256)
Byte five = size-byte six * 256
In this example, we use a size of 400 bytes. This allows us to control the top ten lines of the Graphics 0 display screen.
Once relocated, a string variable can be used to modify the area of memory it occupies. Manipulating the string contents alters the contents of the memory locations. An example is the line:
This will put a 65 in memory location SCRN, 66 in SCRN+1,
67 in SCRN+ 2, and so on. Since we are dealing directly with the screen,
we must use internal character codes rather than ATASCII. In line 400 of
Listing 3, A$ is completely filled with CHR$(0), the ATASCII "heart" character.
This puts a 0 in the first 400 locations of the screen memory area, and
10 blank lines are on the screen.
Line 420 puts the word "HELLO" on the second line of the screen by placing the characters "(% , ,/" into A$, and then sliding A$ to screen memory In this example, when a 40 (ATASCII code for a left parenthesis) is POKEd into screen memory the letter "H" appears on the screen.
The speed you can achieve with this "string sliding" is rivaled only by machine language. Imagine the graphics effects possible!
Four basic steps are needed for positioning string variables in memory:
1. Dimension the variable in the beginning of your program.
2. Calculate VVTP, the starting address of the Variable Value Table, from locations 134 and 135.
3. Select a new memory location for your string variable, break the address into low and high bytes, and POKE these new values into the Variable Value table at byte three and byte four.
4. Calculate the new size of the string variable and place these values into byte five and byte six. Byte seven will contain the new value you need for byte five, and byte eight will contain the value you need for byte six.
Once the string variable is positioned, characters in the
string will correspond to numbers in the memory locations. This method
can be used to place numbers in memory by placing characters in the string.
You can also to read numbers from memory by reading the string.
A string can even be positioned in the area of memory where a program is stored-resulting in a program that can write other programs! As you learn more advanced programming techniques, you'll discover many more uses for relocating string variables.
Brian Weiss is a computer science major at the University of Maryland and has been programming with the Atari for four years.