Classic Computer Magazine Archive COMPUTE! ISSUE 17 / OCTOBER 1981 / PAGE 62

Undeletable Lines

Michael P. Antonovich
Wyomissing, PA

Editor's Note: Though described for Applesoft, this crafty technique works on CBM computers as well. For PETs, type SYS1024. Then .M 0400 041F and hit RETURN (where the author mentions CALL-151). — RTM

Did you ever wish that you could put your name into a program in such a way that the average computer user could not delete it and claim the program as his own? Well you can. In APPLESOFT, you normally cannot enter program lines greater than 63999, but I will show you how you can. First we have to see how the APPLE stores your program lines in memory.

The APPLE stores APPLESOFT program lines beginning at memory location $800. (The '$' sign before a number indicates that the number is in hexadecimal). Let's enter the following small program to illustrate the way a program is stored.

2 A = 8

To see how the APPLE stores this program, we have to enter the monitor with a CALL -151. However, before we list the program, there is one other piece of information that we need to determine. To add lines to an existing program, you need to know where the current program ends in memory. You can accomplish this in one of two ways. You can page through the memory to find the program's last byte. (Hint: This is the hard way.) The APPLE also stores the location of the last memory byte in locations $69 and $6A. Let's enter the monitor now to check our program.

CALL -151
* 69.6A
0069-1E 08
* 800.81F
0800-00 07 08 01 00 B2 00 0F
0808-08 02 00 41 D0 38 00 16
0810-08 03 00 BA 41 00 1C 08
0818-04 00 80 00 00 00 FF FF

Although you may not recognize it, the above listing is a memory dump of your program. Let's examine how our BASIC lines were translated to the above hex dump.

The first byte $00 at location $800 has no special meaning to our program. In fact, location $800 will always contain $00. The program lines begin after this point. Each line is prefixed by four bytes. The first pair of bytes stores the starting byte address of the next line. In our example, locations $801 and $802 indicate that the next line will begin at memory location $807. (Remember that the location is split into two bytes which are stored in what seems, to us humans, to be in reversed order.)

The second pair of bytes contains the line number assigned to the program line. In our example we started with the line number "1." Thus memory locations $803 and $804 indicate that the first line number is "1." In addition to the four bytes which prefix each line, each line is ended with single byte ‘00’ to separate it from the next line. Therefore, there is a five byte overhead for each program line used. If multiple statements are combined with a colon (using one byte) on a single line, you can save four bytes for each extra line you eliminate. If you have any doubts, try it yourself with the above program.

The second program line begins at memory address $807. The first four bytes indicate that the next statement will begin at location $80F and will have statement number "2." The next three bytes "41 D0 38" represent the tokens for the equality: A = 8. The information we will need to understand these tokens is found in Appendix F and Appendix K of the APPLESOFT Reference Manual. I'll wait while you go get your copy.

Appendix F lists the decimal tokens for all of the keywords used by the APPLE. However, when we are in the monitor, we need the hexadecimal equivalent of the tokens. For example, the hex equivalent for END is $80, REM is $B2, and PRINT is $BA, etc. You might want to take the time now to write the hexadecimal equivalents next to the decimal values for all of the tokens.

Variable names, numbers and strings are not listed in Appendix F. These must be constructed by using the individual ASCII character representations. Appendix K lists the ASCII character set with the decimal and hexadecimal codes. Again, we are interested in the hexadecimal codes. In our example, we need the "A" or $41 and the "8" or $38.

I have now explained all of the hex codes used in our example except one, the equal sign (=). The problem is that both Appendix F and K contain an equal sign, but each has a different hex code. Which one is correct? We need a rule which will guide us with this and similar problems, so here it is. To construct a variable name, number, or string of characters, use Appendix K. Any symbol used in an arithmetic expression (such as = , (,), etc.) should be taken from Appendix F.

Finally, even though we end our program with an END statement, the APPLE does not know that this is the end of the program (for, indeed, it does not have to be). The end of the program is indicated by the byte pair ‘00 00’ in the locations where it expects to find the next line number.

Now that we know how the APPLE interprets our APPLESOFT program and stores it in memory, we are ready to begin adding lines to our program which will be undeletable to the average APPLE user.

Normally, only program line numbers from 0 to 63999 can be used and referenced in an APPLESOFT program. Converting 63999 to hexadecimal we get $F9FF, but we can write larger hexadecimal numbers than in two bytes. In fact, we should be able to use the numbers from $FA00 through $FFFF or 64000 through 65536. Even though the APPLE will prevent us from entering these line numbers through the keyboard, we know enough about how the APPLE stores program lines to sneak them in.

Let's keep this example simple and assume that I just want to store my name and the date as remark statements. We could just as easily make them PRINT statements if we wanted to. The statements we want are:

64001 REM JUNE 28, 1981

Now enter the monitor (CALL -151) and type the following:

81C : 37 08 00 FA
820 : B2 4D 49 43 48 41 45 4C
828 : 20 50 2E 20 41 4E 54 4F
830 : 4E 4F 56 49 43 48 00 4A
838 : 08 01 FA B2 4A 55 4E 45
840 : 20 33 30 2C 20 31 39 38
848 : 31 00 00 00

Before you return to APPLESOFT, we must reset the end of program pointer. If we do not do this, the first time you run your program, any variables you store will write over the new lines you just added. Our program now ends at memory location $84C. This information must be put into locations $69 and $6A.

69 : 4C 08

We can now reenter APPLESOFT using CNTL-C RETURN, and list the program. There are lines 64000 and 64001 at the end. Try to delete them. HA! You cannot touch them. You can SAVE this program, reload it, RUN it, and copy it, and still those two lines will be there. In fact the only way to get rid of them is to enter the monitor, find where you want the program to end, change the last two bytes to "00 00," and change the program ending location in addresses $69 and $6A. It's easy, but only if you know how.

Remarks are not the only things that you can put into undeletable lines. You can store anything you want from program lines using tokens and character strings to machine language programs using this method.

I would like to clear one thing up before anyone gets the wrong idea. The tokens we have been using above are NOT machine language. All microcomputers use tokens to store keywords. All BASIC program lines are stored in the above manner, not in machine language. The program lines must be interpreted each and every time that they are run. However, there is a lot that you can do with undeletable lines.

[Manipulating BASIC using your monitor can also hide lines from LISTing, but they will RUN normally. To make this program print the 8, but without line 3 appearing in the program LISTing — simply change the one hexadecimal number to 16 like this:

.: 0800 00 07 08 01 00 B2 00 16
    Apple Version
.: 0400 00 07 04 01 00 8F 00 16
    PET Version

Also notice that PET and Apple versions are similar (both are Microsoft BASICs), but the hex number for REM is $B2 for Apple, $8F for PET. The location of the last BASIC memory byte (the top of a BASIC program) is different in the PET, too. For Original PETs, this address is found in $007C, $007D. For Upgrade and 4.0 PETs: $002A, 002B. Another difference is that Apple starts its BASIC programs at $0800, where PET starts at $0400. You will notice this reflected in the line links which contain the starting byte address of the next line. (In PET, the first links are at $0401 and $0402, and they point to $0407 where the next link points up the chain once again. It is this $0407 (or Apple's $0807) which we changed to skip over line three in our "hidden line" technique above.) Here is the complete program as it would appear in the PET:]

.: 0400 00 07 04 01 00 8F 00 0F
.: 0408 04 02 00 41 B2 38 00 16
.: 0410 04 03 00 99 41 00 1C 04
.: 0418 04 00 80 00 37 04 00 FA
.: 0420 B2 4D 49 43 48 41 45 4C
.: 0428 20 50 2E 20 41 4E 54 4F
.: 0430 4E 4F 56 49 43 48 00 4A
.: 0438 04 01 FA B2 4A 55 4E 45
.: 0440 20 33 30 2C 20 31 39 38
.: 0448 31 00 00 00 AA AA AA AA