views:

129

answers:

3

I am having some trouble understanding how to retrieve the result of a calculation done using the Intel's x86 coprocessor.

Please consider the following data segment.

.data

res real4 ?
x real4 5.0
k real4 3.4

and the following code segments, version 1:

.code

main:

fld x      ; 5.0
fadd k1    ; 5.0 + 3.4
fistp res  ; store as integer (it will round, in this case down)

mov eax, res ; eax = 00000008

end main

and version 2:

.code

main:

fld x     ; 5.0
fadd k    ; 5.0 + 3.4
fstp res  ; store as real

mov eax, res ; eax = 41066666

end main

I understand version 1, with no problem.

It's version 2 I don't understand. I can see in the debugger that it does the exact some calculation as version 1, but when it's time to store is does so as "41066666"!?

What is the reason for this?
What "encoding" was used to make 8.4 into "41066666"?
Is there a way to convert it back to 8.4, so that I can print it in the console (for example, using StdOut masm32 library function)?

Thanks.

+4  A: 

Floating Pointt Calculator and Converter

Enter 8.4 and you can see the hex version of the number is represented as: 41066666

CookieOfFortune
Thanks. That explains it. Please take some time to answer the other part of the question: Is there a way convert it back to 8.4 so that I can print it in the console? Thanks.
nunos
Well... the way I would do it in C would be to call printf(%f, x). What library are you using? There is perhaps a function in there to convert it for you.
CookieOfFortune
As mentioned in the post I am using masm32. I don't know, but perhaps there's some masm32 function, like dwtoa, but for floats that can do it.
nunos
+3  A: 

The encoding is IEEE-754 floating point format. It appears you are using 32-bit floats, also known as single-precision. This format contains a sign bit, an eight bit exponent which is biased by 127 (maybe 128—I don't remember offhand), and 24 bits of mantissa where 23 are stored and the missing bit is the most significant and usually has the value one, except for denormal values. There are several patterns with special meaning: zero, NaN, infinity, and denormals.

Besides the external tool suggested by CookieOfFortune, you could write a floating point conversion to ASCII by performing a variety of arithmetic operations to determine the value. There are many algorithms which tradeoff speed for space. See any runtime library source for ftoa, or the %f or %g conversions for printf().

wallyk
+3  A: 

0x41066666 is 8.4 (well, 8.3999996185302734375 to be exact) encoded in the IEEE-754 single precision format. You can easily display its value as a hexadecimal number by extracting the component fields from the encoding, which would give you 0x8.66666, but converting it to decimal is rather harder to do correctly. If you want to have decimal output, the easiest thing is to link against the C library on your system and use the printf function.

Alternatively, as wallyk suggested, grab the source for one of the open source conversion routines (or write your own implementation, though this is a surprisingly challenging task to do well). Probably the best easily accessible sources are in the file gdtoa.tgz on Netlib. The complexity of that implementation should give you some idea of the issues involved, and may point you back toward using a library =)

Stephen Canon