【问题标题】:MIPS: Translating C code to MIPS problem in function calls and returnsMIPS:在函数调用和返回中将 C 代码转换为 MIPS 问题
【发布时间】:2020-07-28 18:28:03
【问题描述】:

我需要将 C 代码从下面更改为 MIPS 代码,但我是 MIPS 的新手并坚持使用它。

这是 C 代码:

int main()
{
    int a, b, result;
    if(a == b)
         result = a*b;
    else
         result = assess(a, b);
    return result;
}

int assess(int a, int b)
{
    if(b<a)
        return upgrade(a, b);
    else
        return demote(a, b);
}

int upgrade(int a, int b)
{
    return 4*(a+b);
}

int demote(int a, int b)
{
    return 4*(b-a);
}

这是我编写的 MIPS 代码,它不起作用(我知道存在重大错误和错误)。由于我对语言不熟悉,所以我的主要问题是使用堆栈、返回和调用函数。

.data
    a:.word 8
    b:.word 8
    result:.word 0
main:
    li $s0 a
    li $s1 b
    li $s3 result
    beq $s0,$s1,Resultmul ELSE
    add $s3,$s3,assess

assess:
    blt $s1,$s0,upgrade
    bge $s1,$0,demote
Resultmul :
    mul $s3,$s1,$0

upgrade:
    addi $sp,$sp,-4
    sw $0,0($sp)
    add $t1,$a0,$a1
    mul $t1,$t1,4
    add $v0,$s0,$zero
    lw $s0,0($sp)
    addi $sp,$sp,4
    jr $ra
demote:
    addi $sp,$sp,-4
    sw $0,0($sp)
    sub $t1,$a0,$a1
    mul $t1,$t1,4
    add $v0,$s0,$zero
    lw $s0,0($sp)
    addi $sp,$sp,4
    jr $ra

如果有人可以提供帮助,那将是救命稻草。

【问题讨论】:

  • 这实际上组装没有错误吗?你用的是什么工具?
  • Mars4_5 它组装但没有按预期运行,并且当组装的文本段为空时。
  • 不,它没有。
  • @ErikEidt 它必须是结果:.word 0 不等于我的错误
  • 您缺少.text 指令,因此它忽略了整个程序!我不得不说这对火星来说是很奇怪的行为。将.text 放在数据之后和代码之前。

标签: c mips procedure code-translation


【解决方案1】:

我不会给你完整的解决方案,所以你可以从练习中学习,但我建议你使用模板,例如这个。

我使用了 Visual Studio Code(具有 MIPS 支持和更好的 MIPS 支持突出显示),其中每个空格或选项卡都让我有可能通过这些空格折叠它,而 QtSpim 我能够在其上运行它并得到输出64

另外,我习惯于使用制表符进行编码;这对我来说更清楚,但对你来说可能不是,所以如果你必须删除所有选项卡和 cmets,我很抱歉。

######################## pseudo ####################################
 #
 #  int main()
 #  {
 #      int a, b, result;
 #      if(a == b)
 #           result = a*b;
 #      else
 #           result = assess(a, b);
 #      return result;
 #  }
 #  
 #  int assess(int a, int b)
 #  {
 #      if(b<a)
 #          return upgrade(a, b);
 #      else
 #          return demote(a, b);
 #  }
 #  
 #  int upgrade(int a, int b)
 #  {
 #      return 4*(a+b);
 #  }
 #  
 #  int demote(int a, int b)
 #  {
 #      return 4*(b-a);
 #  }
 #  
###################### DATA Segment ################################

    .data
 A:
    .word 8
 B:
    .word 8
 result:
    .word 0

###################### CODE Segment ################################

    .text
    .globl main
 main:

这里你犯了一个小错误:你已经存储了这些词,所以你也应该加载这些词。否则,您必须输入 li $t0, 8

    # int A = A, B = B, result
    lw      $s0, A      # $s0 = A
    lw      $s1, B      # $s1 = B
    lw      $s2, result # $s2 = result    
    # if (a == b)
        bne     $s0, $s1, noteq # if $s0 != $s1 then noteq
        # result = multiply(a,b);
        move    $a0, $s0        # $a0 = $s0
        move    $a1, $s1        # $a1 = $s1
        jal     multiply        # jump to multiply and save position to $ra
        sw      $v0, result     #         
        b       end             # branch to end
    # else
        noteq:
        # result = assess(a,b);
        move    $a0, $s0        # $a0 = $s0
        move    $a1, $s1        # $a1 = $s1
        # jal       assess      # jump to assess and save position to $ra
        sw      $v0, result     #         
        b       end             # branch to end (this rule can be left out)
    end:
    # printf("%i", result)
    li      $v0, 1      # $v0 = 1
    lw      $a0, result #     
    syscall
    # exit()
    li      $v0, 10     # $v0 = 10
    syscall

由于它们是伪代码中的函数,因此它们也应被视为程序集中的函数。这意味着他们被j(用于非返回函数,如退出)或jal(并以jr返回)调用。

我创建了一个完全不必要的函数multiply 来向您展示模板,这对于较大的函数非常方便。

###################### FUNC Segment ################################

###################### FUNCTION ####################################
 # multiply(A, B)
 #
 # Purpose: <General description>
######################## i/0 #######################################
 # Input:
  # $a0 = A
  # $a1 = B
 # Output: 
  # $v0 = value
 # Registers being used:
  # $s0 = A
  # $s1 = B
  # $s2 = value
######################## pseudo ####################################
 #  
 #  int multiply(int A, int B)
 #  {
 #      return A * B;
 #  }
 #
######################## <code> ####################################
 multiply:#(A, B)

始终存储您要覆盖的寄存器的内容,这样您就可以调用其他函数而不会丢失任何内容。还要立即在新寄存器中初始化存储在$a0-$a3 中的参数,因为在使用syscall 打印某些内容时可能会覆盖这些参数。

存储变量有两个主要原因:

  1. 函数调用想在不知不觉中更改您的$s0-$s7-寄存器之一。
  2. 可以在当前函数中调用其他函数,并使用它们自己的堆栈处理,因此无需担心寄存器。在创建 assess-function 之前了解一下可能会很有趣。

这是函数参数初始化的样子:

    # store(&return, parameters that are about overwritten)
    sub     $sp, $sp, 16    # $sp = $sp - 16
    sw      $ra, 0($sp)     #
    sw      $s0, 4($sp)     # 
    sw      $s1, 8($sp)     #
    sw      $s2, 12($sp)    # 
    # int A = A, B = B, value
    move    $s0, $a0        # $s0 = $a0
    move    $s1, $a1        # $s1 = $a1

这是函数的非常短的主体。如您所知,存储所有这些参数是愚蠢的,所以不要创建这些开销函数。

    # value = A * B;
    mul     $s2, $s0, $s1

这是处理函数的返回。在较大的函数中,您大部分时间都需要一个标签来跳转到返回处理。我总是在函数foo 中调用标签,例如foo_thisLabel,但这只是我的建议。

    move    $v0, $s2        # $v0 = $s2
    # restore()
    lw      $ra, 0($sp)     #   
    lw      $s0, 4($sp)     # 
    lw      $s1, 8($sp)     # 
    lw      $s2, 12($sp)    #     
    addi    $sp, $sp, 12    # $sp = $sp + 12
    # return index
    jr      $ra             # jump to $ra
######################## </code> ###################################

请注意,我只等待函数的返回段将value 移动到返回寄存器$v0

这是其他功能的空模板。

###################### FUNCTION ####################################
 # <name of function>
 #
 # Purpose: <General description>
######################## i/0 #######################################
 # Input:
  # $a0 = 
  # $a1 = 
  # $a2 = 
  # $a3 = 
 # Output: 
  # $v0 = 
 # Registers being used:
  # $t0 = 
  # $t1 = 
  # $t2 = 
  # $s0 = 
  # $s1 = 
  # $s2 = 
  # $s3 = 
  # $s4 = 
######################## pseudo ####################################
 #  
 #  int assess(int a, int b)
 #  {
 #      if(b<a)
 #          return upgrade(a, b);
 #      else
 #          return demote(a, b);
 #  }
 #
######################## <code> ####################################
 #
######################## </code> ###################################

附:我已经重命名了你的变量名,因为b 可能会导致错误。

【讨论】:

    猜你喜欢
    • 2019-05-13
    • 2012-06-16
    • 1970-01-01
    • 2014-09-01
    • 1970-01-01
    • 2016-08-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多