by Tom Hudson
Welcome back! As I mentioned last issue, there are only a few more 6502 instructions left for us to cover, and we'll talk about them in the next two installments. There are also a couple of instructions we're going to skip until later. They are for more advanced uses, and won't make much sense until you've got more experience with assembly language.
Several people have written lately, asking if we'll get into full-scale programs and using the Atari's powerful operating system. The answer: You bet! We're going to find out how to access the disk, cassette, graphics, keyboard, and just about anything else you'd like to hear about. We'll study routines for high-speed math, player/missile graphics, and more. If you've got a specific suggestion, drop me a postcard, and I'll add your idea to my topic file. Boot Camp is here not only to teach you what 6502 assembly instructions do, but how to apply them.
Last issue, I asked you to write a program which multiplied the number 5 by 27. There is an almost infinite number of ways to do this, and I'll show you two of them now. Remember, these aren't the only possibilities, and, even though your solution may not be as efficient, getting the correct answer is what counts most.
10 *= $0600
20 CLD ;BINARY MATH!
30 LDA #5 ;GET # TO MULT.
40 STA TIMES1 ;SAVE # TIMES 1
50 ASL A ;*2
60 STA TIMES2 ;SAVE # TIMES 2
70 ASL A ;*4
80 ASL A ;*8
90 STA TIMES8 ;SAVE # TIMES 8
0100 ASL A ;*16
0110 CLC ;CLEAR FOR ADD
0120 ADC TIMES8 ;*24
0130 CLC ;CLEAR AGAIN
0140 ADC TIMES2 ;*26
0150 CLC ;CLEAR AGAIN
0160 ADC TIMES1 ;*27
0170 STA RESULT ;SAVE # TIMES 27
0180 BRK ;WE'RE DONE!
0190 TIMES1 *=*+1
0200 TIMES2 *=*+1
0210 TIMES8 *=*+1
0220 RESULT *=*+1
0230 .END
The first solution I'm going to cover is shown in Figure 1. This program uses the principle of breaking a multiply into "bite-sized" pieces, as shown last issue. In this case, I broke the multiply by 27 down into the following group of adds:
(number * 16) (number * 8) (number * 2) + (number ) ------------- (number * 27)
Let's step through the program in Figure 1 and see how it works.
The second solution I decided to show is a modification of the first technique. In this program, I decided to break the multiply down into smaller pieces again, but structure it so that subtracts are used instead of adds:
(number * 32) (number * 4) - (number ) ------------- (number * 27)
As you can see, we get the same result as with adds, but with only three math operations instead of four. Figure 2 shows the 6502 code necessary to implement this method.
10 *= $0600
20 CLD ;BINARY MATH
30 LDA #5 ;GET # TO MULT.
40 STA TIMES1 ;SAVE # TIMES 1
50 ASL A ;*2
60 ASL A ;*4
70 STA TIMES4 ;SAVE # TIMES 4
80 ASL A ;*8
90 ASL A ;*16
0100 ASL A ;*32
0110 SEC ;SET FOR SUBTRACT
0120 SBC TIMES4 ;*28
0130 SEC ;SET AGAIN
0140 SBC TIMES1 ;*27
0150 STA RESULT ;SAVE # TIMES 27
0160 BRK ;ALL DONE!
0170 TIMES1 *=*+1
0180 TIMES4 *=*+1
0190 RESULT *=*+1
0200 .END
Let's walk through this program and see what's going on.
Obviously, these are just two of the thousands of solutions possible for this problem. If you've got a different approach, I'd like to see it. just send your programs to Boot Camp, in care of ANALOG.
The last topic we're going to cover before going on to bigger and better things is the 6502 stack. This is an important feature of the 6502, as it allows us to write subroutines. Since the stack concept is very important, we're going to cover it in detail starting this issue, and finish it with assembly examples next time. Let's get started finding out what the stack is and how it works.
The 6502 reserves 256 bytes of memory from $0100-01FF (also called page 1) for a temporary storage area. We call this area the stack. This area is automatically maintained for the 6502, but we can use it for short-term storage, too.
We call the stack a "last-in, first-out" structure. The last number placed on the stack is always the first to be pulled off. A good way to remember this is to think of a stack of pancakes. When you pile them up, the last one put on the stack is on top. When you take them off one at a time, the last one you put on comes off first. Using this analogy, the computer could keep track of 256 pancakes, each with a number written on it.
The computer keeps track of the stack's contents by using the Stack Pointer register inside the 6502. This pointer ranges from $00-FF. When the stack pointer contains $00, it is pointing to the memory location $0100. When it contains $FF, the location $01FF is indicated.
Interestingly, the stack works backwards from the way we would expect. When the stack is empty, the stack pointer is set to $FF. Figure 3 shows an empty stack.
Empty stack --------- $01FF | | <-- |---------| | | | | |---------| | SP . | -- . ---|FF| . -- |---------| | | |---------| $0100 | | ---------
As the stack is filled with more and more values, the stack pointer is decremented, pointing to lower areas of page 1. When completely filled, the stack pointer will contain $00, as shown in Figure 4.
Full stack --------- $01FF | 42 | |---------| | 1B | |---------| SP . -- . ---|FF| . | -- |---------| | | 01 | | |---------| | $0100 | 02 |<--- ---------
Since the computer has only reserved 256 bytes for a stack, there are obviously limitations in its use. If the stack is filled with too many values, the stack pointer will "wrap around" back to $FF and begin wiping out earlier stack entries! There is no "error message" for this, so you must be careful when working with the stack.
When entries are removed from the stack, the process is reversed. As each byte is pulled off the stack, the pointer is incremented, pointing to progressively higher locations of the stack.
In BASIC, subroutines are easy to write. You simply set up the necessary BASIC code, put a RETURN instruction at the end of it, and call it with the GOSUB statement whenever you need it. The subroutine code is performed, and BASIC resumes execution at the next statement a er e GOSUB. Neat, huh?
In order for a BASIC subroutine to work, the computer has to know how to get back to the instruction after the GOSUB. It does this by using a stack. Let's look at a simplified example of how a BASIC subroutine is executed.
10 GOSUB 100
20 END
100 GOSUB 200
110 RETURN
200 A=A+1
210 RETURN
Figure 5 is a short BASIC program using the BASIC subroutine statements, GOSUB and RETURN. We're going to step through it and watch what happens to the BASIC stack, a special area similar to the 6502 stack.
Before execution -- The stack is empty, and the stack pointer is pointing to the first available position.
BASIC stack ----------- | | <- POINTER |-----------| | | |-----------| | | |-----------| . .
Line 10 -- The GOSUB to Line 100 is executed. First, the computer finds the next statement after the GOSUB. The next statement is in Line 20, so the computer pushes that line number onto the first location on the stack, and changes the stack pointer to point to the next available location. Execution then proceeds at Line 100. At this point, the stack looks like:
BASIC stack ----------- | 20 | |-----------| | | <- POINTER |-----------| | | |-----------| . .
Line 100 -- This line executes a GOSUB to Line 200. The next statement after this GOSUB is Line 110, so this number is placed on the stack, and the stack pointer is advanced to the next available position. Execution continues at Line 200. The stack now looks like:
BASIC stack ----------- | 20 | |-----------| | 110 | |-----------| | | <- POINTER |-----------| . .
Line 200 -- The computer adds one to the variable A. The stack is not affected.
Line 210 -- The computer encounters a RETURN statement. At this point, the computer increments the stack pointer, like so:
BASIC stack ----------- | 20 | |-----------| | 110 | <- POINTER |-----------| | | |-----------| . .
Now the computer takes the line number 110 from the stack. As you can see, the computer can now go back to the instruction after the last GOSUB. Execution continues at Line 110.
Line 110 -- Another RETURN is encountered, and the stack pointer is incremented again. Now the stack looks like this:
BASIC stack ----------- | 20 | <- POINTER |-----------| | 110 | |-----------| | | |-----------| . .
The computer gets the line number from the stack and completes the RETURN by resuming execution at Line 20.
Line 20 -- This line terminates execution with the END statement. The stack is back to its original condition, with the pointer indicating the first stack location. The line numbers are still in the stack itself, but since the stack pointer no longer points to them, they are no longer active. They will be wiped out by new stack entries.
Now do you see how the stack works? It's a great way to handle subroutines, where the computer must be able to find its way back to the code which called the subroutine.
If you think Boot Camp looks more like Basic Training this issue, hold on! I wanted to explain the subroutine process in a language you're familiar with, like BASIC. Next issue we'll examine the operation of the 6502 subroutine process, and learn how to use the stack for our own programs.
10 GOSUB 10
20 END
Until we meet again, here's a little program to get you thinking. Type in the BASIC program in Figure 6 and RUN it. It may take a while, but something will happen, and I want you to see if you can find the cause. Use the stack illustration method I used in the BASIC example to get the answer.
Also, if you haven't already, try to find more alternate methods for multiplying 5 by 27!