Floating point numbers

single-precision

double-precision

double-extended precision

The data formats for these data types correspond directly to formats specified in the IEEE Standard 754 for Binary Floating-Point Arithmetic.

sign - 1 bit

exponent - 8 bits

mantissa - 23 bits

value = mantissa * 2^-112

sign - 1 bit

exponent - 11 bit

mantissa - 52 bit

value = (-1)^sign * (1 + mantissa / 2 ^ 52) * 2 ^ exponent - 1023)

sign - 1 bit

exponent - 15 bit

mantissa - 112 bit

x87 FPU

Data transfer instructions

Basic arithmetic instructions

Comparison instructions

Transcendental instructions

Load constant instructions

x87 FPU control instructions

FDL - load floating point

FST - store floating point (in ST(0) register)

FSTP - store floating point and pop (in ST(0) register)

FADD - add floating point

FIADD - add integer to floating point

FSUB - subtract floating point

FISUB - subtract integer from floating point

FABS - get absolute value

FIMUL - multiply integer and floating point

FIDIV - device integer and floating point

Conclusion

It is eight and final part ofand here we will take a look on how to work with non-integer numbers in assembler. There are a couple of ways how to work with floating point data:First of all let's look how floating point number stored in memory. There are three floating point data types:As Intel'sdescribed:Single-precision floating-point float point data presented in memory:So for example if we have following number:Exponent is either an 8 bit signed integer from −128 to 127 or an 8 bit unsigned integer from 0 to 255. Sign bit is zero, so we have positive number. Exponent is 00001111b or 15 in decimal. For single-precision displacement is 127, it means that we need to calculateor. Since the normalized binary integer part of the mantissa is always equal to one, then in the mantissa is recorded only its fractional part, so mantissa or our number is. Result value will be:Double precision number is 64 bit of memory where:Result number we can get by:Extended precision is 80 bit numbers where:Read more about it - here . Let's look at simple example.The x87 Floating-Point Unit (FPU) provides high-performance floating-point processing. It supports the floating-point, integer, and packed BCD integer data types and the floating-point processing algorithms. x87 provides following instructions set:Of course we will not see all instructions here provided by x87, for additional information see. There are a couple of data transfer instructions:Arithmetic instructions:and etc... FPU has eight 10 byte registers organized in a ring stack. Top of the stack - register, other registers are ST(1), ST(2) ... ST(7). We usually uses it when we are working with floating point data. For example:pushes value ofto this stack. Operator can be 32bit, 64bit or 80bit. It works as usual stack, if we push another value with, x value will be in ST(1) and new value will be in ST(0). FPU instructions can use these registers, for example:Let's look on simple example. We will have circle radius and calculate circle square and print it:Let's try to understand how it works: First of all there is data section with predefined radius data and result which we will use for storing result. After this 2 constants for calling exit system call. Next we see entry point of program -. There we stores radius value inandwithinstruction and multiply this two values withinstruction. After this operations we will have result of radius on radius multiplication inregister. Next we load The numberwithinstruction to the st0 register, and after it radius * radius value will be in st1 register. After this execute multiplication withon st0 (pi) and st1 (value of radius * radius), result will be in st0 register. Ok, now we have circle square in st0 register and can extract it withinstruction to the. Next point is to pass result to the C function and call it. Remember we call C function from assembly code in previous blog post . We need to know x86_64 calling convention. In usual way we pass function parameters through registers rdi (arg1), rsi (arg2) and etc..., but here is floating point data. There is special registers:provided by sse . First of all we need to put number ofregister to rax register (0 for our case), and put result toregister. Now we can call C function for printing result:We can build it with:And run:It was a eight part of series 'say hello to x64 assembly'. Here we saw how to work with floating point number in assembly. if you will have a questions/suggestions write me a comment or ping me at twitter for discussing. If you're interesting in some additional themes about assembly and x86_64 programming write me a comment and I will try to write blog post about it in near time. It was a last part of this series, at least in regular way. I'm starting to write new series of blog post about linux kernel internals. If there will be something new in the kernel or somewhere else about x86_64 or assembler generally, i will write post about it.All another parts you can find - here All source code you can find as every time - here English is not my first language, so you'll find mistakes in my blog post. Please tell me in the comments or drop me an email