A different path of execution through subB
might have called another subroutine,
which would change $ra.
Let us look at an example where
subroutines call other subroutines.
When a subroutine gets control, it
pushes the return address in $ra onto the
stack.
When it returns to its caller,
it pops the stack to get the return address it should use.
QTSPIM gives
main control
(step 1).
main computes for a while
and then calls
subA
(step 2).
subA immediately pushes
the contents of
$ra
onto the stack (step 3).
The return address that subA
will use when it returns control to main
is now on the top of the stack.
subA runs for a while
and then calls
subB (step 4),
which pushes
the current contents of
$ra
onto the stack (step 5).
The return address that subB
will use
is now on the top of the stack.
Now
subB runs for a while
and then calls
subC (step 6).
which pushes
the current contents of
$ra
onto the stack (step 7).
subC computes for a while,
and then returns to its caller
by poping the return address and using
a jr $ra instruction
(step 8).
The call-chain now unwinds as each subroutine pops its return address and jumps back to its caller (steps 9 and 10).
Finally,
main
has control.
After a computing
it exits to QTSPIM. (step 11)
After subA
returns control
to main,
could main
call another subroutine?