MIPS:在函数调用和返回中将C代码转换为MIPS问题 [英] MIPS: Translating C code to MIPS problem in function calls and returns
问题描述
我需要将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:
- 该函数调用会在不知不觉中更改您的
$s0-$s7
-寄存器之一. - 可以在当前函数中调用其他函数,并对其进行自身的堆栈处理,因此无需担心寄存器.制作
assess
函数之前,可能会很有趣.
- The function call want unknowingly change one of your
$s0-$s7
-registers. - 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屋!