Machine Language: Jump To It!
The 6502 Jump (JMP) has advantages over the various Branch instructions. For one thing, it may go anywhere in memory, where the Branches can hop only a hundred and twenty locations or so either way. Sometimes it's useful that Jump is unconditional: you want to go somewhere and your condition flags are not definitely known.
Jump has its limitations, too. It takes up one more byte than a Branch. You cannot use it conditionally. And a Jump is not "truly relocatable." If you had a program with no Jumps, only Branches, and you decided to move it to a new location in memory, the Branches would still work. After all, Branches use relative addressing which says to hop ahead or back a number of bytes; so when the program is moved, the Branches are still valid in their new place. Not so with the Jump: when your program moves, all Jumps to within that program must be changed.
Often, Jump and Branches can be used together to give advantages of each: the conditional test of the Branch, and the unlimited reach of the Jump. It's not uncommon to see coding like:
BEQ NEXT JMP NOTEQ NEXT ….
The effect is a little like "inverting" the Branch instruction. The code continues if the equals condition is found (BEQ goes to NEXT and continues); but jumps away if not-equals is the case. It seems backwards: the Equals text causes us to change direction if we find not-Equals; but it works well without fuss or bother.
Jump Tables are a collection of Jump instructions, one behind the other, arranged in some part of memory. They tend to baffle the beginning expert.
"Beginning experts," by the way, are programmers who have learned all the instructions, but haven't yet absorbed the wisdom that comes with programming experience. When confronted with a Jump table, the reasoning goes as follows: "I am asked to go to this location, which will immediately Jump somewhere else. What's the point? I can go directly to the destination and save myself a few microseconds and perhaps a few bytes of memory."
The concepts of microsecond and bytes can be quite valid in certain environments. But most of us should be placing the emphasis elsewhere. Machine language is plenty fast for most applications; you won't have time for an extra cup of coffee in those five hundred microseconds of time you save. Memory is cheap and plentiful; you're unlikely to run out of space in the average machine language program you code. A sound program will probably be economical of space and time, but the main objective is to have a well-constructed program.
What's the purpose of a Jump table? To give the program a standard set of locations through which it can access other programs. This can be very useful in providing easy testing and easy compatibility between different machines.
Suppose, for example, you were writing a program that did quite a bit of screen output. If you wrote for a PET/CBM and then wanted to transfer it to an Apple, AIM or Atari, you might have to change every call to the output routine; there might be dozens of these. On the other hand, if you arranged your code so that every output call went to your own location PRJUMP which in turn jumped to the PET/CBM output routine, you'd need to change only the address of your PRJUMP instruction to switch output for the other machine.
Additionally, building a Jump table encourages you to identify in advance those program connections that might need changing. When it's complete, you'll have an easily identifiable list of those connection points, laid out neatly in your program.
Commodore has carefully laid out a Jump table near the top of ROM memory for the use of Machine Language programmers. Every model of PET, CBM and VIC uses the same entry points, so that the user with experience on one model can easily move to the other. This also makes for a great deal of compatibility between machines; many programs will transport directly without change from one to the other. The "difficult" machines for compatibility are the very first model PET and the VIC: the Jump table is still the same, but differing zero page allocations make it hard to transfer programs without change.
The most important Jump table elements are: $FFD2, for output; $FFE4, for GET; $FFE1, for testing the STOP key. These give you input and output control, and allow you to "guard" loops during debugging.
JSR $FFD2 sends the contents of the A register, a PET-ASCII character, to the output. This is normally the screen, although it can be switched to send to other devices. All registers–A, X, and Y–are preserved.
JSR $FFE4 gets one character and places it into the A register as a PET-ASCII value. It normally gets from the keyboard buffer, but can be switched to receive from other devices. All registers might be changed.
JSR $FFE1 does nothing unless the RUN/STOP key is depressed; in which case it exists to BASIC READY. It's very handy if your program gets stuck in a loop; remember that the JSR $FFE1 must also be in the loop to work. The A register will be changed.
The PET/CBM Switch
We can switch the input or output to devices other than keyboard/screen. Providing the new devices have been OPENed previously (probably in BASIC), we may switch to them by using the logical file number – not the device number.
If we had previously opened a disk file for reading with OPEN 1,8,5,"INFILE,S,R" we may now switch the input to this file with LDX #$01 : JSR $FFC6; later we may restore normal keyboard input with JSR $FFCC. Between these two, we may place as many GET calls (JSR $FFE4) as we wish to receive from the disk file; at a later time, we may switch the file in again and receive more data.
In the same way, we might have opened a printer file for output with OPEN 2,4 and may at any time switch output to the printer with LDX #$02 : JSR $FFC9; later we may switch back to screen output with JSR $FFCC. In between, the JSR $FFD2 call will send to the printer rather than to the screen.
Files may be switched in and out repeatedly as desired. Don't switch input and output at the same time – you would hopelessly confuse the IEEE bus. And remember that when you're finished and return to BASIC, you should CLOSE all open files.
Jump tables, which are seemingly excess code, can greatly enhance program organization and portability. Get into the habit of constructing your own on larger programs. And make a point of knowing the ones provided by your computer manufacturer.