问题
I need to change C code from below to a MIPS code but I am new to MIPS and stuck with it.
Here is the C code:
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);
}
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.
回答1:
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.
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:
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
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
).
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)
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:
- 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
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> ###################################
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. I've renamed your variable names, because b
might cause an error.
来源:https://stackoverflow.com/questions/61234603/mips-translating-c-code-to-mips-problem-in-function-calls-and-returns