.png)
Optional. Nothing in the main course depends on it.
When you write RST 8 followed by DEFB 158, something else does the work.
This is about what that something is, what it gives you, and what it takes in
return - because both matter later.
The Einstein has software built into it, in read-only memory, running before you arrive. Part of it is the prompt you return to when a program ends. Part of it is a collection of routines that do the jobs every program needs: putting a character on screen, reading a key, moving the disc head, making a noise, drawing a line, converting a number to text.
Those routines are the machine's own library, and RST 8 is the door.
The number after it chooses which routine you want. 158 is the one that
prints the character in A. There are around sixty of them, covering the
screen, the keyboard, the disc, the sound chip, the serial port and a set of
graphics operations that will plot points, draw lines, fill areas and draw
polygons.
They are usually called MCALs - machine calls.
It looks like unnecessary ceremony. Why not just CALL the routine's real
address, the way S7 calls your own subroutines?
Because the ROM is not always there to call into. One I/O port toggles the
bottom 32K of memory between the ROM and ordinary RAM - a program can ask for
either, and other software (the ROM's own routines among them) may have
switched it since you last checked. A CALL to a fixed ROM address is a bet
that the ROM is currently switched in; get the timing wrong and that address
holds whatever RAM was doing instead, which is not code you meant to run.
RST 8 sidesteps the bet. It always lands in the same small, fixed handler,
which does the bank switching itself before running the routine you asked
for and switches back before returning to you. The number after it is not
decoration - it is the only address that stays meaningful regardless of which
bank happens to be switched in at the moment you call it.
Three things, and they are not small.
They work. Somebody else wrote and tested them. A single RST 8 and a
byte gets you a character on screen, correctly, first time.
They are short. Two bytes for the call and one for the number. Writing the same job yourself takes considerably more.
They handle the detail. The print routine does not simply deposit a byte somewhere. It tracks where the cursor is, moves it along, wraps at the end of a line, and scrolls the display when the text reaches the bottom. You get all of that for free, and you would have to write every bit of it otherwise.
That is why the course starts here. You got a word on screen in S3 rather than in S13.
Time. All that helpfulness has to happen on every single call. Run a loop that prints without pausing and you can watch the screen fill - not instantly, but visibly, character by character. For printing a message that is fine. For a game redrawing the screen thirty or sixty times a second, work you did not ask for and cannot skip is exactly what you cannot afford.
Control. The routine decides, not you. It will move the cursor. It will scroll when it reaches the bottom, whether or not you wanted the screen to move. There is a separate routine in the ROM whose entire purpose is to print a character without advancing the cursor, specifically so that scrolling can be avoided - which tells you the problem is real enough that the people who wrote the ROM worked around it themselves.
Registers. When you call somebody else's code, you do not know what it
does with the processor while it runs. A and C come back intact - which is
why the counted loops in S6 and S7 work. What happens to the others is not
something you can assume. Every register you care about across a call is
either one you have tested, or a gamble.
Version. The routines are in ROM, and the ROM has revisions. Two of the graphics characters swapped position between MOS 1.1 and MOS 1.2. A program that depends on a routine behaving exactly as it does on one machine may not behave the same on another.
Almost no commercial game used the ROM's printing routines for anything that had to be fast.
The reason is the whole of the previous section. A game has a strict budget: everything on screen has to be redrawn in the gap between one frame and the next, and the gap is fixed. A routine that maintains a cursor, checks for wrapping and might decide to scroll the display is doing work the game does not want, at a moment when there is no time for it.
So games talk to the video hardware directly. They put bytes into video memory themselves, at addresses they chose, in an order they control, doing exactly as much work as the frame requires and no more. It is more code and it is less forgiving, and it is faster by a margin that decides whether a game is playable.
Because they are the shortest route to a working program, and because you cannot judge what direct hardware access buys you until you have felt the alternative.
There is also plenty they remain the right tool for. Loading a level off disc is not on the critical path. Neither is printing a title screen, or a high-score table, or reading a name the player types in. The rule is not "never use them" - it is do not use them for the things that have to be fast.
The sections after this one keep using MCALs, because they are how you get results while learning the processor. Later, when the subject is drawing a screen rather than printing a word, the course goes underneath them: to the video hardware, its memory, and what it costs to write to it directly.
At that point the trade in this appendix stops being background and becomes the thing you are deciding about, several times a frame.