1

Normally I would terminate my programm with

li        $v0, 10
syscall

Now I've seen many code examples where they terminate the programm by jumping back to the $ra register.

jr        $ra        

Why is this possible to terminate the program like this? Does it depend on the compiling program?

Recent main I've looked in:

main:

    addi    $sp, $sp, -4        # save return adress
    sw  $ra, 0($sp)

    lw  $a0, x              #get some arguments for a function called exp
    lw  $a1, n              #get more args

    jal exp                 #call the function

    move    $s1, $v0

    move    $a0, $s1

    li  $v0, 1               #print return value
    syscall
    lw  $ra, 0($sp)          #here we load the ra for the jr
    addi    $sp, $sp, 4
    jr  $ra
Richie
  • 73
  • 1
  • 6
  • 2
    Depends on your environment. Typically if you have `main` that means you can return from it. – Jester Mar 26 '18 at 11:14
  • 1
    This works if the process doesn't start with `main()` but instead with some `_start()` which loads libraries, sets up the environment, calls `main()` and, crucially, terminates the process gracefully when `main()` returns. – EOF Mar 26 '18 at 11:29
  • Okay lets say I'm in my main function and I use a jal to another function. In that function at the end I use jr $ra to return back to MY main. How does QtSPIM for example knows that I want to go to MY main and not the main of QtSPIM? The return adress is the same and I didnt stored and loaded it on the stack pointer. For declaration after .text I set .globl main as I'm doing it in university and then start coding my main in main: [CODE] – Richie Mar 26 '18 at 11:45
  • 1
    @Richie If you are in function `a()` and you have not saved `$ra` before calling `b()`, then returning from `a()` after `b()` has returned will lead to an infinite loop (unless stack adjustments/register restoration in `a()` leads to a fault). – EOF Mar 26 '18 at 11:57
  • 1
    There is no magic in QtSPIM, or in real CPUs in general. `jr $ra` means jump to the address in that register, nothing more, nothing less. A function that wants to use `jal` itself has to save/restore `$ra`, or else it will lose its return address. (If you don't do this, then the pointer in `$ra` will be to the instruction after the last `jal` like EOF said, often creating an infinite loop of the few instructions at the end of your function.) – Peter Cordes Mar 26 '18 at 16:09
  • @Peter Cordes Is there aswell a mips tags like in your profile for x86 with all documentation and so one? – Richie Mar 26 '18 at 17:20
  • 1
    Yeah, mouseover the MIPS tag in your question and click info. Unfortunately the MIPS tag wiki is nowhere near as big as x86; I only have the time/energy/interest to really maintain the x86 tag wiki. I do edit others sometimes. – Peter Cordes Mar 26 '18 at 17:21
  • In `main`, doing `li $v0,10`, `syscall` is like (in C) doing `exit(0)`. Doing `jr $ra` is like: `int main(void) { return 0; }`. Or, more correctly, since most `mips` simulators don't honor the return codes: `exit()` and `void main(void) { return; }` respectively. – Craig Estey Mar 26 '18 at 22:26

1 Answers1

0

jr $ra is the equivalent of ret on x86 or bx lr on ARM, it's often the case where we're not writing an entire program but just a single function or routine, that returns to a main program. This is how you tell the CPU that you wish to return to the instruction after the jal or jalr that got you here. (Well, since it's MIPS, it would be the instruction 2 down from the call point but I digress.)

puppydrum64
  • 1,598
  • 2
  • 15