News:

MASM32 SDK Description, downloads and other helpful links
MASM32.com New Forum Link
masmforum WebSite

How to divide w/o FPU?

Started by w0lfshad3, August 24, 2006, 02:58:59 PM

Previous topic - Next topic

w0lfshad3

First of all i would like to know if its recomandable and why.

For example: 1/4 would be

  1|4    0|4
10|4    2|2
20|4    5|0

I draw the following conclusions:
- all divided numbers(remainders) in consequent divisions to the first are multiplied by ten according to the natural way humans divide.
- 3rd column contains my number in decimal form.
- making a procedure out of this would be advised? (at least it can be general for single digit decimal numbers; 3 params, x, y, number of fraction digits wanted)

I do not really know yet whats the best way to do this(if its beter than using FPU at all).
How to store the fractional number, in this case 0.25 and use it as a fractional number in another division or multiplication?

Tedd

Dividing without fpu: "DIV" or "IDIV" instructions (the latter takes the numbers as 'signed.')
However, the result of these instructions is an integer and remainder. So 1/4 would result in 0, remainder 4. So not what you're hoping for in this case.

Buuut, if you only want to multiply these fractions with other numbers, then there's no need to do it this way.
A little re-arranging gives:
    a * 3/5  =  (a * 3) / 5
which will give the same (integer) result, but without the need to play with the fractions directly. (For 1/4, multipying by 1 is pointless, so it simply becomes divide by 4.)

I presume this would be faster than "long-division" - which is natural for humans, but not for computers. Unless you specifically need the floating-point respresentation, and then it's quite unavoidable.


Quick Trick.. :wink
Divide by 2: "shr eax,1"
Divide by 4: "shr eax,2"
Divide by 8: "shr eax,3"
..and so on, for powers of 2.
No snowflake in an avalanche feels responsible.

dsouza123

1/4 --> 0, remainder 1
5/4 --> 1, remainder 1

Fixed point:   8, 4, 2, 1, 1/2, 1/4, 1/8, 1/16, 1/32, 1/64, 1/128, 1/256

Tedd

Whoops! Thanks, my bad :red
(1 div 4 => 0, remainder 1; not remainder 4)


xor edx,edx   ;top 32-bits of 64-bit number to be divided
mov eax,1     ;lower 32-bits of 64-bit number to be divided
mov ecx,4
div ecx
;eax = result
;edx = remainder

No snowflake in an avalanche feels responsible.

w0lfshad3

Oh yeah thanks i forgot about Pitagora however my calculations were corect except the first :lol but with no impact on the whole picture.

1=4x0+r ---> r=1, however still doesn't feel natural to me somehow, oh wait its because i switched the roles of 4 and 1 in my head  :cheekygreen:

Posted by: dsouza123
QuoteFixed point:   8, 4, 2, 1, 1/2, 1/4, 1/8, 1/16, 1/32, 1/64, 1/128, 1/256
Whats that?

Posted by: Tedd
QuoteQuick Trick..
Divide by 2: "shr eax,1"
Divide by 4: "shr eax,2"
Divide by 8: "shr eax,3"
..and so on, for powers of 2.

Yes i knew that, you shift the other way for multiplication, and i might add shift by 4 for a hex number mul by F?(untested) all you do with hex is add a 0 i think when you multiply by F.

Quotexor edx,edx   ;top 32-bits of 64-bit number to be divided
mov eax,1     ;lower 32-bits of 64-bit number to be divided
mov ecx,4
div ecx
;eax = result
;edx = remainder

Yes thanks of course i was thinking of getting 0.25 that i can store in a variable and use it as a float value the way floats are handled in the FPU(IEEE floating point representation). In a procedure it can be done until it hits 0 remainder or wanted precision. I will do it soon, its a good exercise if i get the time.

From what i read tough its starting to resemble what they call BCD operations.

dsouza123

Hexadecimal is base 16 so 10 is 16 and F is 15
so multiplying by F isn't equivalent to shifting left 4 (adding 0 to the end).
Shifting left 4 is multiplying by 10 ( 16 decimal).

In unsigned binary each bit postition to the left is twice the amount
and each to the right is half so if you use 512 for 2, 256 for 1 then
128 could be 1/2 down to 1 for 1/256 so some fraction could be
represented exactly and some approximated.

raymond

If you don't want/need to use the floating point format of the FPU, have a look at using fixed point math.

http://www.ray.masmcode.com/fixmath.html

Raymond
When you assume something, you risk being wrong half the time
http://www.ray.masmcode.com

w0lfshad3

Yes the last link covers all the logic(and a library :) i would need if i would not have a FPU.

w0lfshad3

#8
In all what i read, i didn't find yet an example of how and when the different types of signed numebrs are used.
Except in the FPU  where only the 1's magnitude is used if i remember corect; in the rest of the cases its up to me to code by one of the three methods? Or are there rules, here i would use 1's complement there 2's complement?

w0lfshad3

bump, i just need a straight answer; the three signed number representation(1's magnitude, 1's complement, 2's complement),
are used(besides the case of the FPU) when and wich of them?

Tedd

x86 uses 2's-complement for signed integer values.
No snowflake in an avalanche feels responsible.

zooba

I honestly have never heard 1's complement mentioned outside of the NOT operation. The FPU/SSE uses a signed-magnitude format while the integer instructions (inc. MMX?) use 2's complement.

For addition and subtraction operations in 2's complement the sign is irrelevant; both operations perform exactly the same.

For multiplication and division there are two sets of operations. MUL and DIV treat the numbers as unsigned. IMUL and IDIV will check the signed-ness of both numbers, make them positive, do an unsigned multiplication and then set the sign of the result according to the signs of the inputs.

In general though, it is as Tedd said. The x86 (IA32) only behaves correctly for unsigned or 2's complement signed integers.

Hope this helps,

Zooba :U

w0lfshad3

Yes, thanks you. 1's complement is the equivalent of negation and is used to make up 2's complement. Anyway they are not saying at first where they used, except that it depends on mnemonics used.