For the second example of calling procedures on the HC11, we'll create another pretty useless function: this one will do eight-bit addition. If we were writing a function prototype for this function in a high level language, it would look like this:
char add8(char op1, char op2);
So the function takes two parameters, both eight bit integers
(i.e. chars. It returns another eight bit
integer.
We're going to use pretty standard parameter and return value
passing techniques here: we'll pass parameters on the stack, and
return the function value in the A accumulator.
One thing to mention is that this program shows how to pass parameters, but is till incomplete in a couple of ways. First, it doesn't have any local variables, and second, it corrupts the IX index register. We'll be cleaning these problems up in later examples.
We'll start by just writing the main program, and assuming that the function does the right thing. Then we'll write the function to go along with it.
In a high level language, our main program will look like this:
res = add8(12, 34);
so it will add 12 to 34, and put the
result in a global variable named res (we're using a
global because we haven't talked about how to put local variables on
the stack yet).
In assembly, our main program will initialize the stack pointer, push the parameters, and call the function. Then it'll clean the parameters off the stack, and put the result in a variable. Here's how it looks:
org EEPROM
start lds #STACK * initialize stack pointer
ldaa #34 * push parameters right-to-left (so the first
psha * parameter is closest to top of stack)
ldaa #12
psha
jsr add8 * call function
ins * clean up parameters (two bytes pushed, so
ins * need to increment SP twice)
staa res * store return value in global variable.
eloop bra eloop
add8()Now for our function. We need to get the parameters off the stack, add them together, and leave the result in A. The way we get data out of the activation record is by using indexed addressing — unfortunately, we can't use indexed addressing from the stack pointer directly, so we need to use an index register for it. We'll use IX, since the code will be smaller than IY. Here's our code:
add8 tsx * IX = SP+1
ldaa 2,x * A = param1+param2
adda 3,x
rts
Here's a link to the complete example program. Let's watch what happens as it runs.
0009 f800 8e 00 ff start lds #STACK * initialize stack pointer
0010
0011 f803 86 22 ldaa #34 * push parameters right-to-left (so the first
0012 f805 36 psha * parameter is closest to top of stack)
0013
0014 f806 86 0c ldaa #12
0015 f808 36 psha
0016
0017 f809 bd f8 12 jsr add8 * call function
0026 f812 30 add8 tsx * IX = SP+1
0028 f813 a6 02 ldaa 2,x * A = param1+param2
0029 f815 ab 03 adda 3,x
0030 f817 39 rts
ins instruction just adds one to the stack
pointer.
0019 f80c 31 ins * clean up parameters (two bytes pushed, so
0020 f80d 31 ins * need to increment SP twice)
0022 f80e 97 0a staa res * store return value in global variable.
And we're done! The program just goes into its infinite loop now.