fld, fst, fstp, and fxch. The fld instructions always pushes its operand onto the floating point stack. The fstp instruction always pops the top of stack after storing the top of stack (tos) into its operation. The remaining instructions do not affect the number of items on the stack.
fld instruction loads a 32 bit, 64 bit, or 80 bit floating point value onto the stack. This instruction converts 32 and 64 bit operand to an 80 bit extended precision value before pushing the value onto the floating point stack.fld instruction first decrements the tos pointer (bits 11-13 of the status register) and then stores the 80 bit value in the physical register specified by the new tos pointer. If the source operand of the fld instruction is a floating point data register, ST(i), then the actual register the 80x87 uses for the load operation is the register number before decrementing the tos pointer. Therefore, fld st or fld st(0) duplicates the value on the top of the stack.fld instruction sets the stack fault bit if stack overflow occurs. It sets the the denormalized exception bit if you load an 80 bit denormalized value. It sets the invalid operation bit if you attempt to load an empty floating point register onto the stop of stack (or perform some other invalid operation).fld st(1) fld mem_32 fld MyRealVar fld mem_64[bx]
fst and fstp instructions copy the value on the top of the floating point register stack to another floating point register or to a 32, 64, or 80 bit memory variable. When copying data to a 32 or 64 bit memory variable, the 80 bit extended precision value on the top of stack is rounded to the smaller format as specified by the rounding control bits in the FPU control register.fstp instruction pops the value off the top of stack when moving it to the destination location. It does this by incrementing the top of stack pointer in the status register after accessing the data in st(0). If the destination operand is a floating point register, the FPU stores the value at the specified register number before popping the data off the top of the stack.fstp st(0) instruction effectively pops the data off the top of stack with no data transfer. Examples:fst mem_32 fstp mem_64 fstp mem_64[ebx*8] fst mem_80 fst st(2) fstp st(1)
The last example above effectively pops st(1) while leaving st(0) on the top of the stack.
The fst and fstp instructions will set the stack exception bit if a stack underflow occurs (attempting to store a value from an empty register stack). They will set the precision bit if there is a loss of precision during the store operation (this will occur, for example, when storing an 80 bit extended precision value into a 32 or 64 bit memory variable and there are some bits lost during conversion). They will set the underflow exception bit when storing an 80 bit value value into a 32 or 64 bit memory variable, but the value is too small to fit into the destination operand. Likewise, these instructions will set the overflow exception bit if the value on the top of stack is too big to fit into a 32 or 64 bit memory variable. The fst and fstp instructions set the denormalized flag when you try to store a denormalized value into an 80 bit register or variable[7]. They set the invalid operation flag if an invalid operation (such as storing into an empty register) occurs. Finally, these instructions set the C1 condition bit if rounding occurs during the store operation (this only occurs when storing into a 32 or 64 bit memory variable and you have to round the mantissa to fit into the destination).
fxch instruction exchanges the value on the top of stack with one of the other FPU registers. This instruction takes two forms: one with a single FPU register as an operand, the second without any operands. The first form exchanges the top of stack with the specified register. The second form of fxch swaps the top of stack with st(1).fsqrt, operate only on the top of the register stack. If you want to perform such an operation on a value that is not on the top of stack, you can use the fxch instruction to swap that register with tos, perform the desired operation, and then use the fxch to swap the tos with the original register. The following example takes the square root of st(2):fxch st(2) fsqrt fxch st(2)
The fxch instruction sets the stack exception bit if the stack is empty. It sets the invalid operation bit if you specify an empty register as the operand. This instruction always clears the C1 condition code bit.
fld and fst/fstp instructions are conversion instructions as well as data movement instructions because they automatically convert between the internal 80 bit real format and the 32 and 64 bit memory formats. Nonetheless, we'll simply classify them as data movement operations, rather than conversions, because they are moving real values to and from memory. The 80x87 FPU provides five routines which convert to or from integer or binary coded decimal (BCD) format when moving data. These instructions are fild, fist, fistp, fbld, and fbstp.
fild (integer load) instruction converts a 16, 32, or 64 bit two's complement integer to the 80 bit extended precision format and pushes the result onto the stack. This instruction always expects a single operand. This operand must be the address of a word, double word, or quad word integer variable. Although the instruction format for fild uses the familiar mod/rm fields, the operand must be a memory variable, even for 16 and 32 bit integers. You cannot specify one of the 80386's 16 or 32 bit general purpose registers. If you want to push an 80x86 general purpose register onto the FPU stack, you must first store it into a memory variable and then use fild to push that value of that memory variable.fild instruction sets the stack exception bit and C1 (accordingly) if stack overflow occurs while pushing the converted value. Examples:fild mem_16 fild mem_32[ecx*4] fild mem_64[ebx+ecx*8]
fist and fistp instructions convert the 80 bit extended precision variable on the top of stack to a 16, 32, or 64 bit integer and store the result away into the memory variable specified by the single operand. These instructions convert the value on tos to an integer according to the rounding setting in the FPU control register (bits 10 and 11). As for the fild instruction, the fist and fistp instructions will not let you specify one of the 80x86's general purpose 16 or 32 bit registers as the destination operand.fist instruction converts the value on the top of stack to an integer and then stores the result; it does not otherwise affect the floating point register stack. The fistp instruction pops the value off the floating point register stack after storing the converted value.C1 bits if rounding occurs (that is, if there is any fractional component to the value in st(0)). These instructions set the underflow exception bit if the result is too small (i.e., less than one but greater than zero or less than zero but greater than -1). Examples:fist mem_16[bx] fist mem_64 fistp mem_32
Don't forget that these instructions use the rounding control settings to determine how they will convert the floating point data to an integer during the store operation. Be default, the rouding control is usually set to "round" mode; yet most programmers expect fist/fistp to truncate the decimal portion during conversion. If you want fist/fistp to truncate floating point values when converting them to an integer, you will need to set the rounding control bits appropriately in the floating point control register.
fbld and fbstp instructions load and store 80 bit BCD values. The fbld instruction converts a BCD value to its 80 bit extended precision equivalent and pushes the result onto the stack. The fbstp instruction pops the extended precision real value on tos, converts it to an 80 bit BCD value (rounding according to the bits in the floating point control register), and stores the converted result at the address specified by the destination memory operand. Note that there is no fbst instruction which stores the value on tos without popping it.fbld instruction sets the stack exception bit and C1 if stack overflow occurs. It sets the invalid operation bit if you attempt to load an invalid BCD value. The fbstp instruction sets the stack exception bit and clears C1 if stack underflow occurs (the stack is empty). It sets the underflow flag under the same conditions as fist and fistp. Examples:; Assuming fewer than eight items on the stack, the following ; code sequence is equivalent to an fbst instruction: fld st(0) ;Duplicate value on TOS. fbstp mem_80 ; The following example easily converts an 80 bit BCD value to ; a 64 bit integer: fbld bcd_80 ;Get BCD value to convert. fist mem_64 ;Store as an integer.
fadd faddp fadd st(i), st(0) fadd st(0), st(i) faddp st(i), st(0) fadd mem
The first two forms are equivalent. They pop the two values on the top of stack, add them, and push their sum back onto the stack.
The next two forms of the fadd instruction, those with two FPU register operands, behave like the 80x86's add instruction. They add the value in the second register operand to the value in the first register operand. Note that one of the register operands must be st(0)[8].
The faddp instruction with two operands adds st(0) (which must always be the second operand) to the destination (first) operand and then pops st(0). The destination operand must be one of the other FPU registers.
The last form above, fadd with a memory operand, adds a 32 or 64 bit floating point variable to the value in st(0). This instruction will convert the 32 or 64 bit operands to an 80 bit extended precision value before performing the addition. Note that this instruction does not allow an 80 bit memory operand.
These instructions can raise the stack, precision, underflow, overflow, denormalized, and illegal operation exceptions, as appropriate. If a stack fault exception occurs, C1 denotes stack overflow or underflow.
fsub fsubp fsubr fsubrp fsub st(i). st(0) fsub st(0), st(i) fsubp st(i), st(0) fsub mem fsubr st(i). st(0) fsubr st(0), st(i) fsubrp st(i), st(0) fsubr mem
With no operands, the fsub and fsubp instructions operate identically. They pop st(0) and st(1) from the register stack, compute st(0)-st(1), and the push the difference back onto the stack. The fsubr and fsubrp instructions (reverse subtraction) operate in an almost identical fashion except they compute st(1)-st(0) and push that difference.
With two register operands (destination, source ) the fsub instruction computes destination := destination - source. One of the two registers must be st(0). With two registers as operands, the fsubp also computes destination := destination - source and then it pops st(0) off the stack after computing the difference. For the fsubp instruction, the source operand must be st(0).
With two register operands, the fsubr and fsubrp instruction work in a similar fashion to fsub and fsubp, except they compute destination := source - destination.
The fsub mem and fsubr mem instructions accept a 32 or 64 bit memory operand. They convert the memory operand to an 80 bit extended precision value and subtract this from st(0) (fsub) or subtract st(0) from this value (fsubr) and store the result back into st(0).
These instructions can raise the stack, precision, underflow, overflow, denormalized, and illegal operation exceptions, as appropriate. If a stack fault exception occurs, C1 denotes stack overflow or underflow.
fmul and fmulp instructions multiply two floating point values. These instructions allow the following forms:fmul fmulp fmul st(0), st(i) fmul st(i), st(0) fmul mem fmulp st(i), st(0)
With no operands, fmul and fmulp both do the same thing - they pop st(0) and st(1), multiply these values, and push their product back onto the stack. The fmul instructions with two register operands compute destination := destination * source. One of the registers (source or destination) must be st(0).
The fmulp st(i), st(0) instruction computes st(i) := st(i) * st(0) and then pops st(0). This instruction uses the value for i before popping st(0). The fmul mem instruction requires a 32 or 64 bit memory operand. It converts the specified memory variable to an 80 bit extended precision value and the multiplies st(0) by this value.
These instructions can raise the stack, precision, underflow, overflow, denormalized, and illegal operation exceptions, as appropriate. If rounding occurs during the computation, these instructions set the C1 condition code bit. If a stack fault exception occurs, C1 denotes stack overflow or underflow.
fdiv fdivp fdivr fdivrp fdiv st(0), st(i) fdiv st(i), st(0) fdivp st(i), st(0) fdivr st(0), st(i) fdivr st(i), st(0) fdivrp st(i), st(0) fdiv mem fdivr mem
With zero operands, the fdiv and fdivp instructions pop st(0) and st(1), compute st(0)/st(1), and push the result back onto the stack. The fdivr and fdivrp instructions also pop st(0) and st(1) but compute st(1)/st(0) before pushing the quotient onto the stack.
With two register operands, these instructions compute the following quotients:
fdiv st(0), st(i) ;st(0) := st(0)/st(i) fdiv st(i), st(0) ;st(i) := st(i)/st(0) fdivp st(i), st(0) ;st(i) := st(i)/st(0) fdivr st(i), st(i) ;st(0) := st(0)/st(i) fdivrp st(i), st(0) ;st(i) := st(0)/st(i)
The fdivp and fdivrp instructions also pop st(0) after performing the division operation. The value for i in this two instructions is computed before popping st(0).
These instructions can raise the stack, precision, underflow, overflow, denormalized, zero divide, and illegal operation exceptions, as appropriate. If rounding occurs during the computation, these instructions set the C1 condition code bit. If a stack fault exception occurs, C1 denotes stack overflow or underflow.
fsqrt routine does not allow any operands. It computes the square root of the value on tos and replaces st(0) with this result. The value on tos must be zero or positive, otherwise fsqrt will generate an invalid operation exception.fsqrt sets the C1 condition code bit. If a stack fault exception occurs, C1 denotes stack overflow or underflow.; Compute Z := sqrt(x**2 + y**2); fld x ;Load X. fld st(0) ;Duplicate X on TOS. fmul ;Compute X**2. fld y ;Load Y. fld st(0) ;Duplicate Y on TOS. fmul ;Compute Y**2. fadd ;Compute X**2 + Y**2. fsqrt ;Compute sqrt(x**2 + y**2). fst Z ;Store away result in Z.
fscale instruction pops two values off the stack. It multiplies st(0) by 2st(1) and pushes the result back onto the stack. If the value in st(1) is not an integer, fscale truncates it towards zero before performing the operation. C1 since stack underflow occurs). It raises the precision exception if there is a loss of precision due to this operation (this occurs when st(1) contains a large, negative, value). Likewise, this instruction sets the underflow or overflow exception bits if you multiply st(0) by a very large positive or negative power of two. If the result of the multiplication is very small, fscale could set the denormalized bit. Also, this instruction could set the invalid operation bit if you attempt to fscale illegal values. Fscale sets C1 if rounding occurs in an otherwise correct computation. Example:fild Sixteen ;Push sixteen onto the stack. fld x ;Compute x * (2**16). fscale . . . Sixteen word 16
fprem and fprem1 instructions compute a partial remainder. Intel designed the fprem instruction before the IEEE finalized their floating point standard. In the final draft of the IEEE floating point standard, the definition of fprem was a little different than Intel's original design. Unfortunately, Intel needed to maintain compatibility with the existing software that used the fprem instruction, so they designed a new version to handle the IEEE partial remainder operation, fprem1. You should always use fprem1 in new software you write, therefore we will only discuss fprem1 here, although you use fprem in an identical fashion.Fprem1 computes the partial remainder of st(0)/st(1). If the difference between the exponents of st(0) and st(1) is less than 64, fprem1 can compute the exact remainder in one operation. Otherwise you will have to execute the fprem1 two or more times to get the correct remainder value. The C2 condition code bit determines when the computation is complete. Note that fprem1 does not pop the two operands off the stack; it leaves the partial remainder in st(0) and the original divisor in st(1) in case you need to compute another partial product to complete the result.fprem1 instruction sets the stack exception flag if there aren't two values on the top of stack. It sets the underflow and denormal exception bits if the result is too small. It sets the invalid operation bit if the values on tos are inappropriate for this operation. It sets the C2 condition code bit if the partial remainder operation is not complete. Finally, it loads C3, C1, and C0 with bits zero, one, and two of the quotient, respectively.; Compute Z := X mod Y fld y fld x PartialLp: fprem1 fstsw ax ;Get condition bits in AX. test ah, 100b ;See if C2 is set. jnz PartialLp ;Repeat if not done yet. fstp Z ;Store remainder away. fstp st(0) ;Pop old y value.
fxtract instruction is the complement to the fscale instruction. It pops the value off the top of the stack and pushes a value which is the integer equivalent of the exponent (in 80 bit real form), and then pushes the mantissa with an exponent of zero (3fffh in biased form).C1 determines whether stack overflow or underflow occurs). If the original top of stack was zero, fxtract sets the zero division exception flag. The denormalized flag is set if the result warrants it; and the invalid operation flag is set if there are illegal input values when you execute fxtract.; The following example extracts the binary exponent of X and ; stores this into the 16 bit integer variable Xponent. fld x fxtract fstp st(0) fistp Xponent
Fabs computes the absolute value of st(0) by clearing the sign bit of st(0). It sets the stack exception bit and invalid operation bits if the stack is empty.; Compute X := sqrt(abs(x)); fld x fabs fsqrt fstp x
; Compute X := -X if X is positive, X := X if X is negative. fld x fabs fchs fstp x
st(0) quite a bit when programming the 80x87, MASM allows you to use the abbreviation st for st(0). However, this text will explicitly state st(0) so there will be no confusion.