go to previous page   go to home page   go to next page hear noise



Pushing the Return Address

Main calling A

To return to the caller a subroutine must have the correct return address in $ra when the jr instruction is performed. But this address does not have to remain in $ra all the time the subroutine is running. It works fine to save the value in $ra somewhere. The value can be restored, later on, when it is time to return to the caller.

In the picture, the operating system calls main. The return address to the operating system is in $ra. As soon as it gets control, main pushes the return address on the stack (step 1). The return address that main should use when it returns to the operating system is now on the top of the stack.

The "push" and "pop" instructions in the picture are conceptual. Actual code does these operations in the usual way.

After pushing the return address, main computes for a bit, and then calls subC using a jal instruction (step 2). This puts the return address to main in $ra. Luckily, it does not matter that $ra has been changed because the return address that main will use to return to the operating system is safely on the stack.

subC receives control and computes for a while. Because it does not call another subroutine, subC does not alter $ra and does not need to save it on the stack. When subC returns to main it uses a jr $ra instruction (step 3).

Control returns to main, which computes for a while longer. It returns to the OS by popping the stack into $ra and executing a jr $ra instruction (step 4).

Exception handler service 10 is another way to return to the OS. For this example let us not do that.


Is there room on the stack for additional addresses?