【问题标题】:MIPS nested function callsMIPS 嵌套函数调用
【发布时间】:2023-12-08 17:53:01
【问题描述】:

我正在尝试将 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显示真值。

我认为减法函数会覆盖 s0 处的值。但是当 case 是乘法时,为什么要调用减法呢?我有一个 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

【问题讨论】:

  • 这不是嵌套函数。那将是int foo(){ int nested(){ return 1;} blah blah foo(); blah foo(); },其中nested() 可以访问foo 中的局部变量。 GCC 支持:gcc.gnu.org/onlinedocs/gcc/Nested-Functions.html。你正在做的只是从一个函数进行函数调用。这很正常。不进行任何调用的函数称为叶函数(它们是调用树的叶)。所以你真的在问如何在 MIPS 中编写非叶函数。

标签: c assembly mips mips32 nested-function


【解决方案1】:

问题是,当你从multiply返回后,你仍然在下一行调用subtract。在调用 multiply 之后,您必须从函数 test 返回。 但是,由于函数调用都是函数的最后一条指令,您可以使用以下快捷方式:

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

这样,你不必将$ra存储在你的堆栈中,而是可以直接使用它在@中跳回testcaller 减法乘法的987654322@。这样它应该可以按预期工作。

或者,从乘法返回后跳过jal subtract

       jal multiply
       j OUT
ELSE:  jal subtract

 OUT:  ...

【讨论】:

  • 感谢您的快速回复,但我必须使用堆栈,因为这是我的作业:)
  • @mekafe 好吧,那就换一种方式吧,重点是:乘法返回后不要跳进减法