1. ホーム
  2. c

[解決済み] MIPSのネストされた関数呼び出し

2022-03-04 22:03:06

質問

C言語コードからMIPSコードに変換しようとしています。

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;
}

このコードには、テスト関数の内部にネストされた関数呼び出しが含まれています。 テスト関数のリターンアドレスをスタックに格納し、減算または乗算された値をmainに返そうとしています。

しかし、私の場合、私のコードは引き算と掛け算の両方の関数を実行します。 私は結果をs0に置こうとしています。実行後、s0は常に値の引き算を表示します。乗算の結果をs1に置くと、s1は真の値を表示します。

subtract 関数は s0 の値を上書きすると思います。しかし、multiplyの場合、なぜsubtractメソッドが呼ばれるのでしょうか?if/elseブロックがありますが、この部分は動作していないようです。

以下は私のMIPSコードですが、何が間違っているのでしょうか?

.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

解決方法は?

問題なのは 掛ける を使用します。 今も 呼ぶ 減算する を次の行に書いてください。関数から戻らなければなりません。 テスト を呼び出した後 掛ける . しかし、関数呼び出しはどちらも関数の最後の命令なので、以下のショートカットを使うことができます。

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

この方法では、$ra をスタックに格納する必要がなく、直接それを使って 呼び出し元 テスト の中に jr $ra 減算する 掛ける . こうすれば、意図したとおりに動作するはずです。

または jal subtract をクリックすると、マルチプルから復帰します。

       jal multiply
       j OUT
ELSE:  jal subtract

 OUT:  ...