flat assembler
Message board for the users of flat assembler. Index > Main > 80 bit floats
Author
 Thread  edemko

Joined: 18 Jul 2009
Posts: 549
edemko
Hi.
It's a small revision.
Hope it helps.
Let me know when smth. comes wrong.
I wish you knew.
Once to be translated into Russian, sorry guys i'm tired now and bugs in raw version must be detected.
Can you propose DIVISION samples?
Smth else, smth needed in practice?
edit 2010_08_28: checked
Code:
```_____________
80 bit floats

This document intended describing 80 bit floats all the computation by FPU
(Floating Point Unit) performed in. This document no way is a candidate into float
numbers format. There are many internet sources and documentation concerning FPU
internals, instructions. It's aim - bringing you basical review of the destinative
TBYTE =ten bytes= 80bits any loaded number gets transformed in as such form is the
most informative/valuable.

Suppose we have 625d of something.
This equals: 6*10^2 + 2*10^1 + 5*10^0 =
= 600    + 20     + 5      =
= 625                      =
= 6.25e2

Suppose we have 0.625d of something.
This equals: 0*10^0 + 6*10^-1 + 2*10^-2 + 5*10^-3 =
= 0      + 0.6     + 0.02    + 0.005   =
= 0.625                                =
= 6.25e-1

Let us see 625d in binary:
625 / 2, 1 ->            Check it: 1*2^0 = 001 +
312 / 2, 0 ->                    + 0*2^1 = 000 +
156 / 2, 0 ->                    + 0*2^2 = 000 +
078 / 2, 0 ->                    + 0*2^3 = 000 +
039 / 2, 1 -> remainders         + 1*2^4 = 016 +
019 / 2, 1 ->                    + 1*2^5 = 032 +
009 / 2, 1 ->                    + 1*2^6 = 064 +
004 / 2, 0 ->                    + 0*2^7 = 000 +
002 / 2, 0 ->                    + 0*2^8 = 000 +
001 / 2, 1 ->                    + 1*2^9 = 512 = 625

If you feel difficult, divide 625 by 10 and try see analogy over:
625., to get 5, we divide by 10
to get 2, we divide by 10 by 10
to get 6, we divide by 10 by 10 by 10

= 1001110001.b * 2^0
= 100111000.1b * 2^1
= 10011100.01b * 2^2
= 1001110.001b * 2^3
= 100111.0001b * 2^4
= 10011.10001b * 2^5
= 1001.110001b * 2^6
= 100.1110001b * 2^7
= 10.01110001b * 2^8
= 1.001110001b * 2^9, fpu will always normalize number like this

Well, now you know a method to get whole part ;)
Come to spread 625.625d in binary:
625 as we know equals 1001110001b and, as though in decimal, to form binary output
we must merge fractional part 0.625.

Returning to our native count system:
0.625, to get 6, we multiply by 10
to get 2, we multiply by 10 by 10
to get 5, we multiply by 10 by 10 by 10

0.625 * 2, 1 ->            Check it: 1*2^-1 = 0.500 +
0.250 * 2, 0 -> remainders         + 0*2^-2 = 0.000 +
0.500 * 2, 1 ->                    + 1*2^-3 = 0.125 = 0.625

= 0.101b * 2^0
= 1.010b * 2^-1, fpu will always normalize number like this

Gluing 625.0 and 0.625.
1st points must be arranged as  625.0
+ 0.625 is wrong.
625.0
+   0.625
= 625.625 is ok.

FPU does same thing, losing a lot of useful information sometimes if shifts are too big.
It's the reason 80 bits were chosen still those are also doomed.

1001110001.000b
+          0.101b
= 1001110001.101b * 2^0
= 1.001110001101b * 2^9
pos. powers---neg. powers

Cool, you've got it and are able using.
As you know number/10=number*0.1.
Are you eager :?
0.1 * 2
-------
0.2 * 2
0.4 * 2
0.8 * 2
.......
1.6 * 2
1.2 * 2
0.4 * 2
0.8 * 2
.......
1.6 * 2

.000(1100)b
Approximatelly = .0001101b ie rounded.
Sharing into DWORD: .1100'1100'1100'1100'1100'1100'1100'1101 binary      shr 3
= .c       c    c    c    c    c    c    d hexadecimal shr 3

Mind this principle 10*0.1 = 10*1.0/10.
Hence eax*edx shr 32+3 must be executed to get whole part.
32 as .cccc'cccd is a fraction but CPU treats it as an integer.
Mind the principle mentioned over!
03 as .cccc'cccd = 0.1 * shl 3.

[code]
mov     edx,\$cccccccd      ;0.1 * 2^+3
mov     eax,1'234'567'890  ;any number(dividend)
mul     edx                ;number*0.1, result will take 64 bits as DWORD*DWORD=QWORD
shr     edx,3              ;whole got
[/code]

Cool, we've avoided FPU.
In future you'll see how FPU useful is so let's, at last, see the structure of TBYTE floats
0'000000000000000'0.000000000000000000000000000000000000000000000000000000000000000b
| |               |
| |               |mantissa 64 bits size
| |
| |2's power or an exponent, mantissa multiplied by, 15 bit size
|
|sign 1 bit size, 1="-", 0="+"

+0d      = 0'000000000000000'0.000000000000000000000000000000000000000000000000000000000000000b
-0d      = 1'000000000000000'0.000000000000000000000000000000000000000000000000000000000000000b

Unlike decimal, the power of two(exponent) is biased to \$3fff.
So that -1=\$3fff-1, 1=\$3fff+1, and so on.
Pitfall: FPU's FXTRACT decomposes float into ST0 and ST1 as mantissa and exponent respectivelly.
\$0000'8xxxxxxx'xxxxxxxx -> -16'382
\$0000'4xxxxxxx'xxxxxxxx -> -16'383

Finally
+625.625 = 0'100000000001000'1.001110001101000000000000000000000000000000000000000000000000000b
-625.625 = 1'100000000001000'1.001110001101000000000000000000000000000000000000000000000000000b
_______________ -----____----____
\$3fff+9=4008    9    c   6   8

Some practice.
Addition: 625.625 + 001.000 = 626.625
un-normalize 625.625 shifting it 9 places left
1001110001.101000000000000000000000000000000000000000000000000000b
un-normalize 001.000 shifting it 0 places neither left nor right
1.000000000000000000000000000000000000000000000000000000000000000b
1001110010.101000000000000000000000000000000000000000000000000000b
normalize
1.001110010101000000000000000000000000000000000000000000000000000b
hex
\$4008'9ca80000'00000000

Addition: 625.625 + 625.625 = 1251.25
1001110001.101000000000000000000000000000000000000000000000000000b
1001110001.101000000000000000000000000000000000000000000000000000b
10011100011.01000000000000000000000000000000000000000000000000000b
normalize, shifting 10 digits right
remember to reflect changes in exponent
1.001110001101000000000000000000000000000000000000000000000000000b
hex
\$4009'9c680000'00000000

Addition: 625.000 - 625.625 = -(625.625-625.000) = -0.625
mantissas arranged and there is nothing to shift, substracting
1.001110001101000000000000000000000000000000000000000000000000000b
1.001110001000000000000000000000000000000000000000000000000000000b
0.000000000101000000000000000000000000000000000000000000000000000b
normalize multiplying by 2^10(shifting left 10 times)
1.010000000000000000000000000000000000000000000000000000000000000b
hex
\$3fff+9-10'a0000000'00000000 with MINUS
\$3ffe     'a0000000'00000000 with MINUS
\$bffe     'aaaaaaaa'00000000

Multiplication: a^x * a^y = a^(x+y) e.g. 1.5*0.75 = 15*10^-1 * 75*10^-2 = 15*75*10^(-1+-2)
let us play with CPU again you to understand deeper
1.50 = 3FFF'C0000000'00000000 = 2^0  * 1.1b
0.75 = 3FFE'C0000000'00000000 = 2^-1 * 1.1b
now view how we divided by ten ...
now view how we multiplied by 0.1 ...
jerk, catcha, have you remembered the principle :?
here it is again: 0.1*0.1 = 1*1/10/10
[code]
mov     eax,\$C0000000
mov     edx,\$C0000000
mul     edx
shrd    eax,edx,31*2+1-32
shr     edx,31*2+1-32    ;edx.eax = whole.fraction = 1.125
;take care as fraction might got zero or denormalized
;eg. after such multiplication EAX=\$20000000
[/code]

Multiplication:
00.9 = 3FFE'E6666666'66666666, exp=-1
10.0 = 4002'A0000000'00000000, exp=+3
[code]
mov     eax,\$E6666667
mov     edx,\$a0000000
mul     edx
shr     edx,31*2+1-3-32  ;edx=9
[/code]

http://ray.masmcode.com/
http://www.intel.com/products/processor/manuals/

Compose date:
2010_08_28, 10:52 Kiev Time

Contact:
edemko@rambler.ru
``` 27 Aug 2010, 16:42  Display posts from previous: All Posts1 Day7 Days2 Weeks1 Month3 Months6 Months1 Year Oldest FirstNewest First  Jump to: Select a forum Official----------------AssemblyPeripheria General----------------MainTutorials and ExamplesDOSWindowsLinuxUnixMenuetOS Specific----------------MacroinstructionsOS ConstructionIDE DevelopmentProjects and IdeasNon-x86 architecturesHigh Level LanguagesProgramming Language DesignCompiler Internals Other----------------FeedbackHeapTest Area

Forum Rules:
 You cannot post new topics in this forumYou cannot reply to topics in this forumYou cannot edit your posts in this forumYou cannot delete your posts in this forumYou cannot vote in polls in this forumYou cannot attach files in this forumYou can download files in this forum