No.
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 of $ra
and then to restore it when needed.
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 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.
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 is safely on the stack.
Because subC
does not
call another subroutine,
the return address in $ra will not be altered.
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).
Trap handler service 10 is another way to return to the OS. For this example let us not do that.