I am in a computer arch class and we are doing mips using single precision. The homework involves creating newtons method. I have written all the functions required but cannot figure out exactly what is wrong with the code. I am also not exactly sure how to print values out to the screen. All help is much appreciated. I have written comments line by line to explain what i am doing.
Here is my code:
# Newtons Method
# g(x) = (-x^3) + 11
# g'(x) = -3x^2
.data
precision: .float .00001
main:
jal newtons_gee
newtons_top:
li $s2, 11 # stores 11 into the $s2 register
mtc1 $s2, $f5 # moves the value of $s1 (3) to the coproc 1
mul.s $f1,$f0,$f0 # This finds x^2
mul.s $f1,$f0,$f1 # This finds x^3
add.s $f2,$f1,$f5 # adds the value of (x^3) + 11 and stores it into $f2 as asked
newtons_bot:
li $s1, -3 # stores -3 into the $s1 register
mtc1 $s1, $f3 # moves the value of $s1 (-3) to the coproc 1
mul.s $f5, $f3,$f0 # Calculating -3x in derivative of the original function
mul.s $f4,$f5,$f0 # Calculates -3x^2 and stores it in $f4 as asked
newtons_err:
jal newtons_top # Calls newtons_top
jal newtons_bot # Calles newtons_bot
div.s $f6,$f2,$f4 # Calculates g(Xn)/ g'(Xn) and stores it in $f6 as asked
newtons_nth:
addi $a0,$a0,1 # Increases the current iteration by 1
jal newtons_err # Call newtons_err
sub.s $f7,$f0,$f6 # Calculate value of En
mov.s $f7,$f0 # Find the new nth
abs.s $f3, $f3 # Flag Case
l.s $f9, precision # Precision
c.lt.s $f3, $f9 # set the flag if |x'-x| < 0.00001 stores in $v0
j newtons_nth # Repeat
newtons_gee:
li $f0, 1 # Sets the Xn to 1
li $a0, 1 # Sets the current iteration
jal newtons_nth # Calls newtons_nth
Some tips:
When you call a function, you need to return or else your code will just continue to the next section. Newtons_top is going to run into newtons_bot, newtons_bot is going to run into newtons_err, and then they'll just get called again, resulting in an infinite loop. Labels are just labels; they don't magically end your function. The return address is automatically loaded into $ra
when you use the jal
instruction. You can therefore return by using jr $ra
.
When you have nested calls, such as in newtons_err, your $ra
gets squashed. So you need to back up $ra
before using jal
, and then restore it before returning.
When does your loop end? You don't have an exit condition. You're checking the precision, but you don't have a conditional jump afterward. It'll continue forever.
You want to use the values of 11 and -3, but you're not properly loading them into the floating-point registers. When you use mtc1
you're copying the values verbatim. The problem is that 11 as an integer is not the same as 11 in floating-point. You need an additional instruction to convert it to a float:
cvt.s.w $f5, $f5
Here's a reference containing that conversion: http://www.doc.ic.ac.uk/lab/secondyear/spim/node20.html
li $f0, 1
isn't valid. You can't actually load an immediate into a float register. You can use the same method as you used for the 11 and the -3, but you'll still need the conversion instruction above.
Since you're loading constants (11, -3, 1) into float registers, you can save an instruction by declaring them as floats in your data section, and using l.s $fX, someLabel
instead of li $s2, someConstant
-> mtc1 $s2, $fX
.
The MIPS instruction set doesn't know what printing to the screen means. Printing to the screen involves communicating with other hardware, so to answer that question you need to know what hardware is on your board.