MIPS:在函数调用和返回中将C代码转换为MIPS问题 [英] MIPS: Translating C code to MIPS problem in function calls and returns

查看:159
本文介绍了MIPS:在函数调用和返回中将C代码转换为MIPS问题的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I need to change C code from below to a MIPS code but I am new to MIPS and stuck with it.

这是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代码,该代码无法正常工作(我知道这里有主要的错误和错误).因为我不熟悉该语言,所以我的主要问题是使用堆栈,返回和调用函数.

Here is MIPS code that I wrote, which isn't working (I am aware there are major errors and wrongs). Because I am not familiar with the language, my main problems are using stack, return and calling the functions.

.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

如果有人可以帮助,那将是救生员.

If someone can help that would be a lifesaver.

推荐答案

我不会为您提供完整的解决方案,因此您可以从练习中学习,但是我建议您使用模板来工作,例如此处例如.

I'm not going to give you the full solution, so you can learn from the exercise, but I recommend you work from a template, like at this one for example.

我使用了Visual Studio Code(具有MIPS支持和更好的MIPS支持以突出显示),其中每个空格或选项卡都使我可以将这些空格折叠起来,并使用QtSpim来运行它并得到输出64.

I used Visual Studio Code (with MIPS Support and Better MIPS support for highlighting), in which every whitespace or tab, gives me the possibility of collapsing it by these whitespaces, and QtSpim on which I was able to run this and got the output 64.

此外,我习惯于使用制表符进行编码;对我来说更清楚了,但可能对您而言不是,所以很抱歉,如果您必须删除所有标签和注释.

Also, I'm used to coding with tabs; it's more clear to me, but it might not be to you, so I'm sorry if you have to remove all the tabs and comments.

######################## 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:

您在这里犯了一个小错误:您已经存储了这些单词,因此您也应该 load 这些单词.否则,您必须输入li $t0, 8.

Here you made a little mistake: You already stored the words, so you should also load the words. Else, you'll have to type 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返回)调用的.

Since they are functions in your pseudo-code, they should be treated as functions in your assembly as well. Meaning they are being called with j (for non-returning function like exit) or jal (and return with jr).

我制作了一个完全不必要的功能multiply来向您展示模板,这对于较大的功能非常方便.

I made a completely unnecessary function multiply to show you the template, which is pretty handy for larger functions.

###################### 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打印某些内容时,您可能会覆盖这些参数.

Always store the content of the registers you are going to overwrite, so you can call other functions without losing any content. Also immediately initialize your parameters stored in $a0-$a3 in new registers, because you might overwrite the parameters when printing something using syscall.

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

There are two main reasons to store the variables:

  1. 该函数调用会在不知不觉中更改您的$s0-$s7-寄存器之一.
  2. 可以在当前函数中调用其他函数,并对其进行自身的堆栈处理,因此无需担心寄存器.制作assess函数之前,可能会很有趣.
  1. The function call want unknowingly change one of your $s0-$s7-registers.
  2. Other functions can be called within the current function, with their own stack handling, so again no need to worry about registers. Might be interesting to know before making an assess-function.

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

This is how the initialization of a function's parameters would look like:

    # 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

这是该函数的非常短的正文.如您所知,存储所有这些参数是愚蠢的,所以不要使用这些开销函数.

This is the very short body of the function. As you can tell, storing all these parameters is idiotic, so don't make these overhead functions.

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

这是为了处理函数的返回.在较大的函数中,大多数时候您将需要标签来跳转到返回处理.我总是在像foo_thisLabel这样的函数foo中调用标签,但这只是我的建议.

This is to handle a function's return. In larger functions, you'll need a label most of the time to jump to the return-handling. I always call labels inside a function foo like foo_thisLabel, but that's just my recommendations.

    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.

Note that I only wait for the function's return segment to move value into the return register, $v0.

这里是其他功能的空模板.

Here is an empty template for the other functions.

###################### 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> ###################################

P.S.我已重命名了您的变量名,因为b可能会导致错误.

P.S. I've renamed your variable names, because b might cause an error.

这篇关于MIPS:在函数调用和返回中将C代码转换为MIPS问题的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆