The Floating Point Unit (FPU)
From ASM Book
The x87 coprocessor, or the floating-point unit (FPU), executes approximately 70 instructions. This chapter will describe the instruction set of the FPU up to the Pentium processor. It includes the data transfer, arithmetic, comparison, transcendental, and constant instructions. The FPU can be very useful for performing calculation and mathematics heavy applications such as 3D graphics and audio processing.
The FPU uses a different system for moving data around in the processor. Instead of using named registers, like the CPU, it uses a stack. The stack is refered to as ST(x) where x is a position on the stack. This causes a lot of confusion to newcomers because unlike programming on the main CPU, where eax is always eax, when you move data into a register on the FPU, everything below it moves down, and you need to keep track of your register stack at all times.
Throughout this article, ST(0) will be used to represent the top of the FPU stack, though many people refer to it as ST without a number.
The FPU also contains a status register, who's purpose is to hold status flags for operations like comparison, bit test operations, etc. The FSTSW instruction moves the status word register into the CPU, so you can use it for flow controll, exception detection, and response, and the like.
Contents |
FPU Data Formats
The FPU uses 3 different types of data: signed integer, BCD, and floating point. The following table shows the various data types used by the FPU along with their sizes and approximate ranges.
| Type | Length | Range |
|---|---|---|
| Type | Length | Range |
| Word Integer | 16-bit | -32,768 to 32,767 |
| Short Integer | 32-bit | -2.14e9 to 2.14e9 |
| Long Integer | 64-bit | -9.22e18 to 9.22e18 |
| Single Real | 32 bit | 1.18e-38 to 3.40e38 |
| Double Real | 64 bit | 2.23e-308 to 1.79e308 |
| Extended Real | 80 bit | 3.37e-4932 to 1.18e4932 |
| Packed BCD | 80 bit | -1e18 to 1e18 |
Signed Integers
- Positive signed integers are stored in normal format, with the left-most sign bit set to 0. Negative numbers are stored in 2's-complement form, with the left-most sign bit equal to 1. Following shows how to define the various integer types, and what their binary representations are
;--------------------------+----------------------+ ; Definition | Hexadecimal | ;-------------------------------------------------+ var1 dw 24 ; 0024 | var2 dw -2 ; FFFE | var3 dd 1234 ; 000004D2 | var4 dd -123 ; FFFFFF85 | var5 dq 9876 ; 0000000000002694 | var6 dq -321 ; FFFFFFFFFFFFFEBF | ;+------------------------------------------------+
Binary-Coded Decimal (BCD)
BCD numbers are 10-bytes in size. Each number is stored as 18 digits, with 2 digits per byte. The highest order byte stores the sign of the number, with the highest order bit of this byte being the sign bit. Note that both positive and negative numbers are stored in true form, and not in complemented form.
+----------+-----+-----+-----+-----+-----+-----+-----+-----+----+----+----+----+----+----+----+----+----+----+ | Sign bit | D17 | D16 | D15 | D14 | D13 | D12 | D11 | D10 | D9 | D8 | D7 | D6 | D5 | D4 | D3 | D2 | D1 | D0 | +----------+-----+-----+-----+-----+-----+-----+-----+-----+----+----+----+----+----+----+----+----+----+----+ 79 0
List of FPU Instructions
This list of instructions was compiled from Ray Filiatreault's online floating point tutorial.
F2XM1 2 to the X power minus 1 FABS Absolute value of ST(0) FADD Add two floating point values FADDP Add two floating point values and pop ST(0) FBLD Load BCD data from memory FBSTP Store BCD data to memory FCHS Change the sign of ST(0) FCLEX Clear exceptions FCMOVcc* Conditional move based on CPU flags FCOM Compare ST(0) to a floating point value FCOMI Compare ST(0) to ST(i) and set CPU flags FCOMIP Compare ST(0) to ST(i) and set CPU flags and pop ST(0) FCOMP Compare ST(0) to a floating point value and pop ST(0) FCOMPP Compare ST(0) to ST(1) and pop both registers FCOS Cosine of the angle value in ST(0) FDECSTP Decrease stack pointer FDIV Divide two floating point values FDIVP Divide two floating point values and pop ST(0) FDIVR Divide in reverse two floating point values FDIVRP Divide in reverse two floating point values and pop ST(0) FFREE Free a data register FIADD Add an Integer located in memory to ST(0) FICOM Compare ST(0) to an integer value FICOMP Compare ST(0) to an integer value and pop ST(0) FIDIV Divide ST(0) by an Integer located in memory FIDIVR Divide an Integer located in memory by ST(0) FILD Load integer from memory FIMUL Multiply ST(0) by an Integer located in memory FINCSTP Increase stack pointer FINIT Initialize the FPU FIST Store integer to memory FISTP Store integer to memory and pop ST(0) FISUB Subtract an Integer located in memory from ST(0) FISUBR Subtract ST(0) from an Integer located in memory FLD Load real number FLD1 Load the value of 1 FLDCW Load control word FLDENV LoaD environment FLDL2E Load the log base 2 of e (Napierian constant) FLDL2T Load the log base 2 of Ten FLDLG2 Load the log base 10 of 2 (common log of 2) FLDLN2 Load the log base e of 2 (natural log of 2) FLDPI Load the value of PI FLDZ Load the value of Zero FMUL Multiply two floating point values FMULP Multiply two floating point values and pop ST(0) FNCLEX Clear exceptions (no wait) FNINIT Initialize the FPU (no wait) FNOP No operation FNSAVE Save state of FPU (no wait) FNSTCW Store control word (no wait) FNSTENV Store environment (no wait) FNSTSW Store status word (no wait) FPATAN Partial arctangent of the ratio ST(1)/ST(0) FPREM Partial remainder FPREM1 Partial remainder 1 FPTAN Partial tangent of the angle value in ST(0) FRNDINT Round ST(0) to an integer FRSTOR Restore all registers FSAVE Save state of FPU FSCALE Scale ST(0) by ST(1) FSIN Sine of the angle value in ST(0) FSINCOS Sine and cosine of the angle value in ST(0) FSQRT Square root of ST(0) FST Store real number FSTCW Store control word FSTENV Store environment FSTP Store real number and pop ST(0) FSTSW Store status word FSUB Subtract two floating point values FSUBP Subtract two floating point values and pop ST(0) FSUBR Subtract in reverse two floating point values FSUBRP Subtract in reverse two floating point values and Pop ST(0) FTST Test ST(0) by comparing it to +0.0 FUCOM Unordered Compare ST(0) to a floating point value FUCOMI Unordered Compare ST(0) to ST(i) and set CPU flags FUCOMIP Unordered Compare ST(0) to ST(i) and set CPU flags and pop ST(0) FUCOMP Unordered Compare ST(0) to a floating point value and pop ST(0) FUCOMPP Unordered Compare ST(0) to ST(1) and pop both registers FWAIT Wait while FPU is busy FXAM Examine the content of ST(0) FXCH Exchange the top data register with another data register FXTRACT Extract exponent and significand FYL2X Y*Log2X FYL2XP1 Y*Log2(X+1) * cc refers to any of these variations FCMOVB Move if below (CF=1) FCMOVE Move if equal (ZF=1) FCMOVBE Move if below or equal (CF=1 or ZF=1) FCMOVU Move if unordered (PF=1) FCMOVNB Move if not below (CF=0) FCMOVNE Move if not equal (ZF=0) FCMOVNBE Move if not below or equal (CF=0 and ZF=0) FCMOVNU Move if not unordered (PF=0)
