Search code examples
cassemblymipsmips32nested-function

MIPS nested function calls


I'm trying to convert a C Code to MIPS code.

int main() {
  int a;
  int b;
  int result = 0;
  if (a != b)
    result = test(a, b);
  else
    result = a + b;
  return result;
}
int test(int a, int b) {
  if (a > b)
    return multiply(a, b)
  else
    return subtract(a, b)
}
int multiply(int a, int b) {
  return a * b;
}
int subtract(int a, int b) {
  return a - b;
}

This code contains nested function calls inside test function. I have put the return address of test function into stack and trying to return the subtracted or multiplied value to the main.

But in my case, my code executes both subtract and multiply functions. I'm trying to put my result to s0. After running s0 always shows subtraction of values. If I put multiply result to s1, s1 shows true value.

I think subtract function overrides value at s0. But when case is multiply, why subtract method is called? I have an if/else block, but this part seems to be not working.

Here is my MIPS Code, what am I doing wrong?

.data
    numberA: .word 4
    numberB: .word 2
.text
.globl main

    main:
    addi   $s0, $0, 0 # result = 0
    lw   $a0, numberA
    lw   $a1, numberB

    bne $a0, $a1, L1
    add $s0, $a0, $a1
L1: jal test

    add $s0, $v0, $0

    li $v0,10
    syscall 


test:
        addi $sp, $sp, -4
        sw $ra, 0($sp)

        slt $s1,$a1,$a0
        bne $s1, 1, ELSE
        jal multiply
ELSE:   jal subtract

lw $ra, 0($sp)

addi $sp, $sp, 8

jr $ra


subtract:
    sub $s0, $a0, $a1
    jr  $ra


multiply:
    mult $a0, $a1
    mflo $s0
    jr $ra

Solution

  • The problem is, that after you return from multiply, you still call subtract in the next line. You have to return from the function test after calling multiply. However, since the function calls are both the last instruction of your function, you can use the following shortcut:

    test:
            slt $s1,$a1,$a0
            bne $s1, 1, ELSE
            j multiply
    ELSE:   j subtract
    

    This way, you do not have to store the $ra in your stack, but you can directly use it to jump back to the caller of test in the jr $ra of subtract and multiply. This way it should work as intended.

    Alternatively, skip over jal subtract after returning from multiply:

           jal multiply
           j OUT
    ELSE:  jal subtract
    
     OUT:  ...