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
Related
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
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).
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.
I know I can check whether an integer is even if I shift right by 1, then shift left by 1 and the number stays as the original number.
My code isn't working as intended. This is my first time using MIPS and any help would be appreciated. I want to let the user input any number and my code will tell the user whether it is an even number.
.data
msg: .asciiz "even"
.text
.globl main
main:
li $v0, 5
syscall
or $t0, $0, $v0 # Register $t0 gets input
srl $t1 , $t0 , 1 #shift right by 1
syscall
sll $t1 , $t0 , 1 #shift left by 1
syscall
bne $t1, $t0, msg # if t1 equals t2 then it prints out even
syscall
There are a couple of strange things you're doing, and one easy-fix bug. But until you get the strange things fixed, you're going to be hozed.
First, like #markgz said, what are those syscalls supposed to be doing? Get rid of all of them except the one where you're getting a value from the user. Otherwise, you're going to get a number from the user over and over.
Second, branching to msg makes no sense. The memory at msg is an ASCIIZ string containing the characters m, s, g, and \0. These are not the 32 bits you are looking for. You need to branch to an instruction. I'm going to assume that labels isEven and isOdd exist somewhere.
The bug is what #Konrad said. Omitting the strange syscalls, your code is doing this:
srl $t1, $t0, 1 # shift *original val* right by 1 *and put in $t1*
sll $t1, $t0, 1 # shift *original val* left by 1 *and put in $t1*
bne $t1, $t0, isOdd # *will always be true because we just changed $t1 to be <> $t0*
So if you follow #Konrad's suggestion, it would look like this:
srl $t1, $t0, 1 # shift *original val* right by 1
sll $t1, $t1, 1 # shift *modified val* left by 1
bne $t1, $t0, isOdd # *Now we know if the value changed*
Note that I'm branching to isOdd. You claimed that if the values are different, then the number is even. That's incorrect.
As an aside, my favorite way to do this would be a little bit different:
andi $t1, $t0, 0x01
beq $t1, $zero, isEven
I'll leave it to you to figure out what I'm doing. One thing about your method: it fails if the most significant bit is set (which it will be if it's a negative signed integer).
There are so many bugs in your code.
srl $t1 , $t0 , 1 #shift right by 1
syscall # why you are using syscall here ??
sll $t1 , $t0 , 1 #shift left by 1--and should be sll $t1, $t1, 1
syscall #and why also here ??
bne $t1, $t0, msg #wrong ,here you need to pass label as third operand for offset
li $v0,4 # code 4 == print string
la $a0,string # $a0 == address of the string
syscall
Note: in spite of this you can just do & operation on any data with 0x1 and then check for the result is 0 (even) or 1 (odd)
I want also to share this link for programming tutorial on mips
http://chortle.ccsu.edu/AssemblyTutorial/index.html
Fellow SO users,
If I have a value, say 1010 saved in memory, how do I load each of the bits starting from the MSB to the LSB one at a time? By this I mean,
while loop
load $t1 with 1
shift some number by the amount indicated by the value in $t1 (1)
load $t1 with 0
shift some number by the amount indicated by the value in $t1 (0)
do the same until you load the LSB which is 0
start again at MSB (rotate right?)
end loop
I need some tips on how to declare this value in memory in the .data segment first. Do I declare this as:
value: .byte 00001010
And how do I load the individual bits into registers?
Kind regards
You can do this with the SLT instruction described here. Here is some pseudocode:
lbu $s0, value # load the byte
sll $s0, $s0, 24 # shift it into the upper byte of $s0
for (i = 0; i < 8; i++) {
# $t0 is set to 1 if the sign bit (i.e. bit 31) of $s0 is set
slt $t0, $s0, $zero
# $t0 now holds the value of the ith bit of value
. . . . # do something with $t0
sll $s0, $s0, 1 # shift on to the next bit
}
Implementing the for loop in assembler is left as an exercise for the reader.