/*personal notes of renzo diomedi*/

~ 00000111 ~




Floating-Point Numbers

In the decimal world, you are used to seeing values such as 0.159. What this value represents is 0 + 1⁄10 + 5⁄100 + 9⁄1000.
The same principle applies to the binary world.
The coefficient value 1.0101 multiplied by the exponent 2^2 would yield the binary value 101.01, which represents the decimal whole number 5, plus the fraction 0⁄2 + 1/4. This yields the decimal value 5.25.





IEEE Standard 754 floating-point formats are used universally to represent real numbers in computer systems.
Intel and AMD have adopted this standard in the IA-32 platform for representing floating-point values.

❑ A sign
❑ A significand
❑ An exponent

The sign bit denotes if the value is negative or positive. A one in the sign bit denotes a negative value, and a zero denotes a positive value.

The exponent is modified to accommodate how many bit positions have been shifted to accomplish this (similar to the scientific notation method). This means that in a normalized value, the significand is always comprised of a one and a binary fraction. The exponent represents the exponent part of the floating-point number. Because the exponent value can be positive or negative, it is offset by a bias value. This ensures that the exponent field can only be a positive unsigned integer. It also limits the minimum and maximum exponent values available for use in the format.

The significand part represents the coefficient (or mantissa) of the floating-point number. The coefficient can be either normalized or denormalized. When a binary value is normalized, it is written with a one before the decimal point.



The IEEE Standard 754 defines two sizes of floating-point numbers:

❑ 32-bits (single-precision)

❑ 64-bits (double-precision)



then







# fpux
.section .data
value1:
.float 12.34 # directive to create 32-bit singleprecision values
value2:
.double 2353.631 # directive is used to create 64-bit double-precision values
.section .bss
.lcomm data, 8 # label that points to an empty buffer in memory that will be used to transfer a double-precision floating-point value
.section .text
.globl _start
_start:
nop
flds value1 # instruction for loading single-precision floating-point numbers
fldl value2 # instruction for loading double-precision floating-point numbers
fstl data # instruction for retrieving the top value on the FPU register stack and placing the value in a memory location
# FSTS for single-precision numbers and FSTL for double-precision numbers
movl $1, %eax
movl $0, %ebx
int $0x80



fpux.s
fpux.o
fpux.exe



C:\>gdb -q users\rnz\desktop\fpux.exe
Reading symbols from users\rnz\desktop\fpux.exe...done.
(gdb) break 1
Breakpoint 1 at 0x401000: file users\rnz\desktop\fpux.s, line 1.
(gdb) run
Starting program: C:\users\rnz\desktop\fpux.exe
[New Thread 10236.0x4624]
Breakpoint 1, start () at users\rnz\desktop\fpux.s:12
12 nop
(gdb) s
13 flds value1
(gdb) x/4b &value1
0x402000 : -92 112 69 65
(gdb) x/4 &value1
0x402000 : 0xa4 0x70 0x45 0x41
(gdb) x/4t &value1
0x402000 : 10100100 01110000 01000101 01000001
(gdb) x/gf &value2
0x402004 : 2353.6309999999999
(gdb) s
14 fldl value2
(gdb) print $st0
$1 = 12.340000152587890625 # FIRST ELEMENT IS LOADED IN LOWEST ADDRESS REGISTER
(gdb) print $st1
$2 = 0
(gdb) s
15 fstl data
(gdb) print $st0
$3 = 2353.63099999999985812 # LAST ELEMENT IS LOADED IN LOWEST ADDRESS REGISTER
(gdb) print $st1
$4 = 12.340000152587890625 # PREVIOUS ELEMENT SHIFTS IN NEXT HIGHER ADDRESS REGISTER
(gdb) x/gf &data
0x403000 : 0 # after indtruction FSTL data still set to zero
(gdb) s
16 movl $1, %eax
(gdb) x/gf &data
0x403000 : 2353.6309999999999 # now after movl $1 %eax , fpu stack pointer retrieve last element pushed in st0

The FSTL instruction loaded the value in the ST0 register to the memory location pointed to by the data label.




HOME PAGE