Parameter passing

In the section on subprograms we saw how to use a stack for storing return values for procedures and functions. In this section, we extend the use of the stack to parameter passing for subprograms.

For this, we need two new instructions PUSH and POP. The PUSH instruction pushes the contents of R1 on top of the stack, and the POP instruction pops the top of the stack and puts it in R0. These two instructions are possible to implement without any further modifications to our architecture. Here is the microprogram for push:

......: 0000000000000000000000010 (PUSH)
......: 0001000100000000000000001 (PUSH)
......: 0011000100000000000000001 (PUSH)
......: 1001000100000000000000001 (PUSH)
And here is the microprogram for POP:
......: 1010000000100000000000101 (POP)
With these two instructions, we can make a more complete call/return protocol that contains rules for parameter passing as well. Here is an example of such a protocol. It pushes the arguments in reverse order (argument n first, argument 1 last). That is common for the C language since it allows the subprogram to find the first argument without knowing how many arguments have been passed:
Caller                                 Callee
------                                 ------

compute argument n in R1
push R1
...
compute argument 1 in R1
push R1
jsr callee
                                       compute return value in R0
				       ret
pop n arguments off the stack

Access to arguments

While this way of passing paramenters works, it is not very practical for the callee to access those parameters. The only possibility currently available is to use the POP instruction. It would be more practical if we had instructions that could use addresses made up of the contents of the stack pointer plus a small constant. If we had such instructions, we could access argument number i by using address SP+(i+1), where SP is the contents of the stack pointer.

What we need is thus to be able to add a constant to the stack pointer. That constant will be stored as an argument to a new instruction. We can do this by storing the constant in the address register, and make it possible to add the contents of the address register and the stack pointer to form an address for main memory. The following modifications will allow that:

Notice the new MOP number 26 to communicate the sum to the address bus.

We can now write a new instruction LDS (for load from stack) that does what we want:

......: 00101010100000000000000000 (LDS)
......: 10100000001000000000000001 (LDS)

Popping the arguments

After the callee returns, the caller has to pop off hte arguments that it pushed before the call. Currently, the only possibility is to use POP as many times as there are arguments. An improvement would be to the possibility to add a constant to the stack pointer. For that, we can use the existing adder, but we need to be able to store the result into the stack pointer. This requires additional lines and an additional signal allowing a value to be loaded into the stack pointer. Here is the modified architecture:

Notice the new MOP number 27 for loading a value into the stack pointer. We can now write an instruction ADDSP that adds a constant value to the stack pointer. Here is its implementation:

......: 001010101000000000000000000 (ADDSP)
......: 100000000000000000000000001 (ADDSP)