MIPS multiplying an int by a float, getting wrong answer - mips

when I run my program and input 20 degrees, the output is 8.8E-44 in MARS and 0.000000 in QtSpim. it should be 62.8
am I using the wrong instructions here?
.data
pi: .float 3.14
c: .word 180
initMSG: .asciiz "\nEnter an angle in degrees: "
.text
.globl main
main:
mul $t5, $t2, $t6
add $t5, $t5, $sp
addi $t5, $t5, 4
lw $t9, 0($t5)
mul $t4, $t1, $t6
add $t4, $t4, $a0
sw $t9, 0($t4)
addi $t2, $t2, 1
addi $t1, $t1, 1
j forLoop3
Exit:
li $v0, 10 #load the system exit command
syscall #stop the program

The problem is that pi is a float, but the value you grab from the user is a plain integer. You'd need to convert the user's value into a float before you multiply it with pi.
Fortunately you don't have to convert it manually because there's a syscall for reading floats instead of integers. Change the reading syscall from 5 to 6 (6 means read float), and delete the subsequent two lines (syscall 6 will read the float into $f0 directly). After doing that and running it again using 20 degrees, I get 62.800003 as the output (there will be a small amount of error because 3.14 can't be represented exactly using binary floats).

Related

How do I work with integers that result in bigger than 10 with MIPS?

I am trying to make a Fibonacci sequence with MIPS and this is the code I have so far.
main:
li $t1, 0
li $t2, 1
add $t3, $t1, $t2
loop:
add $t3, $t1, $t2
la $t1, ($t3)
add $t3, $t1, $t2
la $t2, ($t3)
j loop
It works fine until it gets to 8, it should then be adding 5 to make 13 but instead the register shows 0x0000000d, then it completely messes up the sequence, somehow a 15 comes up then 22 then 37.
I'm guessing it has something to do with the carry but how would I actually deal with this so that it carries on with the sequence properly?
Thank you

Converting floating point numbers to integers without conversion instructions

I'm working on a program that should convert a user inputted floating point number to an integer, I got it to work but only for floating point numbers that don't have a fractional part that exceeds 2^-1, which is obviously 1/2. It'll work for numbers like 75.5 or 2.5, but not a number like 75.625. I need to keep the code in this format, but I am not sure what I should make the program shift left and right (around the hashtags) by to cancel out the fractional part regardless of what the fractional part is.
.data
Prompt: .asciiz "\n Please Input a value for the float N = "
result1: .asciiz " The converted N is "
.text
li $v0, 4 # system call code for Print String
la $a0, Prompt # loads address of prompt into $a0
syscall # print the message in Prompt
li $v0, 6 # System call code for Read Float
syscall # read whatever you input float as
mfc1 $t1, $f0 # Stores the float value into the $t1
srl $t2, $t1, 23 # srl by 23 to leave out the biased exponent and store it
in $t2
add $s3, $t2, -127 # Subtract 127 to get the exponent
sll $t4, $t1, 9 # Shift left and right by 9 to remove the exponent
srl $t5, $t4, 9
addi $t6, $t5, 8388608 # Add the implied bit (2^24)
add $t7, $s3, 9 # Add 9 to the exponent value
sllv $s4, $t6, $t7 # Shifts the implied bit to 2^32 (32nd bit)
###########################
rol $s5, $t6, $t7 #rotate to the left by whatever the exponent + 9 is to
get
the integer part of the number to the first few bits
sll $s5, $s5, 1
srl $s5, $s5, 1 # sll and srl cancels out the fractional part #should be
1001011 #s5 is the newly converted integer
######################
li $v0, 4 # Tells computer to get ready to print a .asciiz number
la $a0, result1
syscall
li $v0, 1 # Tells computer to get ready to print the converted integer
number
move $a0, $s5 # Moves the contents of $s5 to %a0 so it can be called
syscall # Returns the integer

MIPS, how to invert a series of numbers in a while loop (a rapid method)

I coding an exercise but I have find a little problem... My exercise ask me that convert a character (keyboard input) in:
ASCII code
Binary code
Hex code
without the MIPS syscall. 2 points on 3 are solved for now but in the point 2 I have find my problem... When I insert a letter for example, the binary code is invertited (see below)
Give me a character: a
ASCII: 97
Binary 10000110 (The real is 01100001)
Exist an easy method to invert this number? I leave the code below.
print_binary:
#move the function parameter in t0
move $t0, $a0
#Show a message
li $v0, 4
la $a0, m3
syscall
while:
#check if my counter is 8(conversion on 8 bit)
beq $t2, 8, end_loop
#Divide the number
div $t1, $t0, 2
#move hi in t4 to show in video
mfhi $t4
#Counter
add $t2, $t2, 1
#move for another division
move $t0, $t1
#Show hi for every division
li $v0, 1
move $a0, $t4
syscall
j while
end_loop:
jr $ra
I don't use the array very well, so I would avoid this method if possible...
Thank you

MIPS Runtime Error "Cannot read diectly from text segment"

The block of code starting from jal next is given in the question, so it can't be changed (have to give intermediate memory and register states after each instruction). The program terminates at the error line with the mesage Runtime exception at 0x00400054: Cannot read directly from text segment!0x00400074' I think the line is supposed to load the value of memory location x200040054 to $t0. I tried manually entering the memory and register values and removing the first block of code to get a different program count when the line with the error executes, but get the same error.
.text
li $t2, 0x0012b628
li $t3, 0x01234567
li $t4, 0xfedcba98
li $t5, 0xf0f0f0f0
sw $t2, 0x10000000
sw $t3, 0x10000004
sw $t5, 0x1000000C
li $a0, 0x000007de
li $t0, 0x52f123d6
li $t1, 0xffffffff
li $s0, 0x10000000
jal next
next : lw $t0 , 0x20($31) #line with error
andi $t1 , $t0 , 0x07C0
xor $t0 , $t0 , $t1
lw $t1 , 0($s0)
andi $t1 , $t1 , 0x07C0
or $t0 , $t0 , $t1
srl $t1 , $t1 , 6
sw $t0 , 0x20($ra)
sll $a0 , $a0 , 31
li $v0, 10
syscall
You are getting a runtime exception because the code you are running is trying to read and the write the text segment (the memory which holds the program code) and usually you cannot read/write those portions of memory at runtime.
The line of code that is giving you the exception is trying to put into register $t0 the contents of the instruction located 8 instructions ahead of $ra which at that moment should point to the location of instruction lw $t0 , 0x20($31) #line with error, that is the binary representation of instruction sll $a0 , $a0 , 31
Then, after some bit manipulation it tries to change the instruction sll $a0 , $a0 , 31 with some other instruction, apparently with sll $a0 , $a0 , 24

MIPS, using a while loop to calculatethe sum of odd integers 1-9

The following is my code in MIPS to calculate the sum of odd integers using a while loop.
.data
num: .space 4
.text
.globl main
main:
li $t1, 1
li $t2, 9 # make $t2 9 to break the loop
li $t3, 1
loop:
beq $t3, 11, Exit # check to see if $t3 = 11 if so exit
addi $t3, $t3, 2 # change $t3 to next odd number by adding 2
add $t1, $t1, $t3 # add $t3 to $t1 (1+3,...3+5...etc...)
j loop #jump back to the start of the loop
Exit:
li $v0, 1 # system call code to print an int
lw $a0, num # address of int to print
syscall # print the int
jr $ra #exit
This is my first real experience with MIPS and I'm not sure what is going wrong in this code. I put the print inside the while loop to see if it was ever calculating, but the result is always 1.
So, my result at the end is just 111111.
Edit: Removed the prints inside of the loop with the same result.
And OS is Windows 7 64x
Update: Having num as a variable was over complicating things. Code has been revised as follow and works. Thank you for the help!
enter code here
.data
.text
.globl main
main:
addi $t1, $0, 1
addi $t2, $0, 3
loop: bge $t2, 11, Exit # check to see if $t3 >= 11 if so exit
add $t1, $t1, $t2 # add $t2 to $t1 (1+3,...3+5...etc...)
addi $t2, $t2, 2 # change $t2 to next odd number by adding 2
j loop #jump back to the start of the loop
Exit:
li $v0, 1 # system call code to print an int
move $a0,$t1 # address of int to print
syscall # print the int
jr $ra #exit
la $t1, num
You're clearly getting into trouble here, since you're overwriting your accumulator with the address of num every time you're making the syscall. You're losing the current state of your calculation each time.
You'll need to either save your registers, or simply use different ones. Since I don't know what OS it is that you're using, I don't know if you more generally need to save registers over a syscall, but that could also be a source of errors.
I did similar problems for an architecture class and this seemed to be a recurrent problem among all students. When facing problems similar to this our professor's recommendation was to use a different register to temporarily store the register's address to avoid overwriting other desired values from our most commonly used regs.