DeadlyDragonnn
DeadlyDragonnn

Reputation: 7

Division (and negative numbers) in MIPS Assembly, how to work out remainder and print it with result?

I am sceptical about dealing with negative numbers so positive for now, but at the moment when I enter 54 as my first integer and 8 as my second integer, I get a result of 6 rather than 6.75. How can I get both 6 to be outputted and something like Remainder equals 0.75 in my case?

.data
msg1:   .asciiz "\nEnter the first integer"
msg2:   .asciiz "Enter the second integer"
msg3:   .asciiz "Result"

.text
li $v0, 4   # syscall to print string
la $a0, msg1
syscall

li $v0, 5   # syscall to read an integer
syscall
add $t1, $zero, $v0

li $v0, 4   # syscall to print a string
la $a0, msg2
syscall

li $v0, 5   # syscall to read an integer
syscall
add $t2, $zero, $v0

add $t0, $zero, $zero

LOOP:
slt $t3, $t1, $t2
bne $t3, $zero, DONE
sub $t1, $t1, $t2
addi $t0, $t0, 1
j LOOP

DONE:
li $v0, 4   # syscall to print a string
la $a0, msg3
syscall

li $v0, 1   # syscall to print an integer
add $a0, $t0, $zero
syscall

li $v0, 10   # syscall code to exit
syscall
'Template'
main:
    #initialize registers

loop:
    #dividend -= divsor
    #quotient++

    #temp = dividend - divsor
    #if temp < 0 jump to done
    #jump to loop

done:
    #remainder = temp

Upvotes: 0

Views: 2065

Answers (1)

Erik Eidt
Erik Eidt

Reputation: 26656

Division by repetitive subtraction and the div instruction on MIPS are doing integer division.  That means that the quotient is an integer and so is the remainder — there is no rounding of either the quotient or the remainder, these are exact as per integer division.

In your example, both the quotient and the remainder happen to be 6.  In integer division, if you did 55 / 8 you would have a quotient of 6 and remainder of 7.  And 53 / 8 would yield quotient of 6 and remainder of 5.  (The remainder is what's left after the quotient, 6, is multiplied by the divisor, 8, and subtracted from the original dividend, e.g. here, 53-48, 54-48, 55-48.)

However, it sounds like perhaps you don't want integer division.

If you use real division instead of integer division, 6.75 is the quotient and there is no concept of remainder, just quotient — with potential for some of it to be after the decimal point.

(0.75 would be the integer remainder, 6, divided by the divisor, 8, using real division instead of integer division; I don't know a name for this so I've simply called it "the rest" of the quotient.)

Real division is approximated on processors using floating point.  MIPS has a floating point coprocessor that will give you 6.75 for the answer in a floating point register.  In order to use floating point arithmetic, we place values into floating point registers, and then use floating point instructions, which return values to floating point registers — these are named $f0-$f31 to differentiate from the integer registers.   If you're using MARS you can also print the 6.75 after so dividing.


Still, there is a way to get the digits 7 and 5 out of the integer computation (though this is fairly uncommon, since it is a bit like building your own floating point..).

Take the remainder, 6, and multiply by 10 to get 60.  Then do integer division again, 60 / 8 to get 7 quotient and 4 remainder.  Print the 7, and, with the 4 do the above again: multiply by 10 to get 40 and integer divide by 8: 40 / 8 = 5, so print the 5 — you have printed 75 — if you had started with 54 / 8 you would get 675 out as digits, where the decimal point should be placed after the printing the first quotient: 6.75.  Knowing where to stop printing is a trick because 1/3 would always have a remainder of 1, and thus go on forever with 3's: 0.33333333333...

Alternatively, multiply the dividend by 100 to start with: 5400 / 8 = 675, or, multiply the remainder after the first integer division, 6, by 100 then divide by 8 = 75.

Upvotes: 1

Related Questions