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
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)
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)