Commodore EXEC
Edwin King
There are times when you'd benefit from being able to access subroutines directly from a disk file. They're not in your program (taking up space), but they can be accessed from a main program, executed, and then the main program continues. Called the EXEC command on those few versions of BASIC which have it, this technique is worth adding to your programmer's bag of tricks. For all Commodore machines. We'll go through the process step by step so you can try the technique and watch it in operation.
Here's a way to store all of your favorite subroutines on disk and have programs call them when they're needed, without having to retype or append or use up memory space.
The Technique
The idea behind the EXEC command (as found in Applesoft BASIC; Commodore Microsoft has no such thing) is to execute a subroutine from disk as if it were typed directly into the computer. Just call a command from the disk, in the form of a character string, and start POKEing to the dynamic keyboard.
For those not familiar with the dynamic keyboard concept, let me review. Every time a key is pressed, the computer stores the ASCII code representation of it in a place called the "keyboard buffer." It keeps doing this until you press RETURN (which also goes into the buffer), then it goes back to evaluate and execute what you just typed in. Lest the computer forget some of the things you typed, it also keeps track of how many characters you typed before (and including) RETURN.
Now, if we are in immediate mode, we can make the computer think we typed something in by PRINTing it, then RETURNing over what was printed on screen. The dynamic keyboard routine involves PRINTing a command on the screen and then POKEing a few carriage returns (13) into the buffer to make the computer think we typed in the command and the carriage returns. This way we only need to POKE one carriage return for every line we want entered.
There are a few drawbacks to this system. First of all, it only works in immediate mode, not as an executing, RUNning program. So, we have to PRINT the command and PRINT a GOTO to get us back into the program. This requires the cursor to be very carefully positioned each time we execute a command – which means no PRINT statements can be anywhere in our EXEC file. Second, INPUT, INPUT #, GET, and GET # are illegal in immediate mode and therefore cannot be used in our EXEC file. And last, since typing in a line with a line number causes that line to be added to the program, our EXEC file will have no line numbers. This means that any use of GOTOs or GOSUBs will call lines in the program, not in the EXEC file. Be very careful if you use these commands.
The Program
"EXEC-file" was written on a VIC-20 and will also run, as is, on a Commodore 64 (you may want to change the "22" in line 85 to "40"). It can easily be modified to run on other Commodore machines (more on this later).
Lines | Function |
40–60 | get input and store file to disk |
70–100 | call and execute the file |
1000–1002 | check for disk error |
When creating an EXEC file, be sure to type in the EXEC file commands without line numbers. Numbers will almost guarantee a crash when you later EXEC the file. The file-call routine (lines 70–100) can easily be lifted and relocated to be used in another program.
Modifications
Users of other Commodore machines should find this program very easy to modify for their system. There are only two changes to be made.
First, change the exit code (the key you press to stop creating the file and get on to other things). The exit code is in quotes on line 55; change the prompt in line 40 accordingly.
Next, the keyboard buffer and the "howmany" (number of characters currently contained in keyboard buffer) location are in different places on different machines. The chart below should assist you in changing this (in line 90).
VIC/64 | Original ROMPETs | BASIC 4.0PETs |
buffer | 631–640 | 527–536 | 623–632 |
how-many | 198 | 525 | 158 |
Thus, on a PET 4032, line 90 would become:
90 POKE 623, 13 : POKE624, 13 : POKE625, 13 : POKE626, 13 : POKE158, 4 : STOP
VIC and 64 owners may also wish to make the print color the same as the screen color before calling this routine, so the user is unaware of the EXEC taking place on screen.
Testing The EXEC
The program here contains both the filemaking and EXEC routines. To test the EXEC function, you must first answer YES when asked if you want to "Create A File?" and then type something like A = 51 : B = 17 : F$ = "Mirabelle" or whatever you want to pass to the program from the disk. It could be a POKE to change screen color or to change the character set, anything you like.
Then, the special file will be on your disk under whatever name you gave it during the filemaking phase. To try out the file, RUN the program again, but answer NO when asked if you want to create a file. This time, the program will move down to line 70 and EXEC the file. When you use the EXEC function in a program, you'll probably want to replace F$ in line 70 with the actual name of the file you want to EXEC: OPEN2, 8, 2, "NAME, U, R". The technique of adding a string to a quoted name (F$ + ", U, R") is the way to specify variable file names, but in a real program you'll know in advance the file name that you intend to EXEC.
Pay special attention to the key in quotes in line 55. If you are using a PET/CBM, for example, you'll want to change this to the back-arrow key or something. PET/CBM has no function keys so you could never signal the end of your INPUT when creating an EXEC file.
EXEC-file
10 REM *COMMODORE* 15 REM *EXEC-FILE* 20 K$ = " " : A$ = " " : F$ = " " 25 INPUT "{CLR}{2 DOWN} CREATE A FILE" ; A$ 30 INPUT "{2 DOWN}FILE NAME" ; F$ 35 IFLEFT$(A$, l) < > "Y" THEN70 38 REM** CREATE EXEC FILE ** 40 PRINT "{CLR}{3 DOWN}{RVS}{6 SPACES}F1 TO END {7 SPACES}" 45 OPEN2, 8, 2, " @0 : " + F$ + ", U, W" : OPEN15, 8, 15 : GOSUB1000 50 GETA$ : IFA$ < > " " THENPRINTA$; : PRINT # 2, A$; 55 IFA$ < > "{F1}" THEN50 60 CLOSE2 : CLOSE15 66 REM** {3 SPACES} EXECUTE FILE {2 SPACES} ** 70 OPEN2, 8, 2, F$ + ", U, R" : 0PEN15, 8, 15 : GOSUB 1000 75 PRINT "{CLR}{4 DOWN}" : GET # 2, A$ : IFA$ < > C HR$ (13) AND (ST < > 64) THENK$ = K$ + A$ : GOTO 75 80 IF (ST) AND 64 THEN 100 85 PRINTK$ "{3 DOWN}" : PRINT "GOTO75" : PRINT "{10 UP}" + LEFT$ ("{7 UP}", INT (LEN(K$)/22)) : K$ = "" 90 POKE 631, 13 : POKE 632, 13 : POKE 633, 13 : POKE 634, 13 : POKE 198, 4 : STOP 100 CLOSE2 : CLOSE15 : END 911 REM.. {3 SPACES} CHECK DISK ERROR {2 SPACES}.. 1000 INPUT # 15, EN, EMS, ET, ES 1001 IFDS > 20 THENPRINTEN, EM$ : STOP 1002 RETURN 63003 A = PEEK (B) + 256 * PEEK (B+1) : IFA = 0THENCLR : END