Thursday, March 28, 2024 | Toby Opferman
 

FPU Programming

Toby Opferman
http://www.opferman.net
programming@opferman.net



                            387 FPU Tutorial

        Anyone who programs in assembly knows that the CPU is an
integer machine.  It can only deal with Non-Floating point numbers.
Many of the older machines emulate floating point which is slow.
Why emulate Floating Point numbers now or why use fixed point math
and such when the FPU is SOOOO much faster.  The FPU can even do
integer operatoins much faster than the CPU now.  The FPU is so easy to
use as well as you will see.


        The FPU is a stack based processor.  It does operatoins on
stack elements.  These Elements are labeled ST(0)-ST(7).  Each location
is 80 bits. In Turbo Debugger, to view the stack go to:

VIEW -> NUMERIC PROCESSOR

It show the IEEE Hex Format of the Number in 80 bits (10 Bytes) and will also
show the decimal number to the side (I.E. 45.393 or whatever). To declare
a float number in your program do the following (I use TASM 5.0):
FloatNumber2 dd 393.33          ; 4 Byte Float
FloatNumber3 dt 393.393993      ; 10 Byte Float

The Assembler will automatically put them in IEEE Float Format.
If the number is a whole number and you want it a float, just make sure
you do 135.0

Before you begin using the FPU, in your program you must put

.387

at top or somewhere when you are going to use FPU.  That is
the directive to make the assembler assemble for the FPU (If
your assembler supports it).

To use the FPU in it's simpliest form, quick calculations
All the FPU instructoins require that 1 of the operands must be the stack.
If no operands are suppilied, the default is

ST = ST(1) op ST

FADD = FADD ST(1), ST
You can pair ST with any of the registers

FADD ST,ST(n)
FADD ST(n),ST

You can also do registers or Variables.
FADD FloatVar
FADD TBYTE PTR [SI] ; Ten Bytes
FADD DWORD PTR [DI] ; Four Bytes

The Integer instructions have an I after the F.
Example:
FILD Integer
FIADD Integer2
FISTP Integer
That is Integer = Integer + Integer2

This is the easiest way to use the FPU.
PUSH The Value
OPERATION With A Value
POP The Value

It's also easy to change a Float to an Integer:
 Float dt 343.33                ; 10 Byte Float
 Integer dd 0                   ; 4 Byte Integer

 FLD Float        ; Load Float
 FISTP Integer    ; Pop Float

 It's That Easy!


Here is a list of the instructoins for the FPU:
Experament with them as u need.


 FBLD                   Loads BCD Number
 FBSTP                  Stores And Pops a BCD Number
 FILD                   Loads An Integer
 FIST                   Stores an Integer
 FISTP                  Stores an Integer and Pops The Stack
 FLD                    Loads A Float
 FSTP                   Stores a Float and Pops the Stack
 FST                    Stores A Float
 FXCH                   Exchanges two stack elements

 FABS                   Computes Absoulte Value
 FADD                   Adds 2 Floats
 FIADD                  Adds 2 Integers
 FADDP                  Adds real Numbers and Pops the stack
 FCHS                   Change Sign of Number
 FDIV                   Divides 2 Floats
 FIDIV                  Divides 2 Integers
 FDIVP                  Divides 2 Floats and Pops the stack
 FDIVR                  Divides 2 Floats but Reverses the dividend and divisor
 FIDIVR                 Same as above with Integers
 FDIVRP                 Divide real numbers, reverse order and pop stack

 FMUL                   Multiply 2 Floats
 FIMUL                  Multiply 2 Integers
 FMULP                  Multiply 2 Floats and Pop Stack
 FPREM                  Computes Partial Remainder
 FPREM1                 Computes Partial Remainder using IEEE Format
 FRNDINT                Rounds the Operand to an Integer

 FSCALE                 Scales by a power of 2
 FSUB                   Subtracts real numbers
 FISUB                  subtracts integers
 FSUBP                  Subtracts real numbers & pops stack
 FSUBR                  Subtracts real number in reverse order
 FISUBR                 Subtracts integers in revers order
 FSUBRP                 Subtracts real numbers in revese order and pops the stack
 FSQRT                  Computes the square root
 FXTRACT                Extracts the exponents and significand from real number

 All Angles in Radians!!

 F2XM1                  Computes the value 2x-1
 FCOS                   Computes the Cosine
 FPATAN                 Computes partial arctangent
 FPTAN                  Computes partial tangent
 FSIN                   Computes Sine
 FSINCOS                Computes Sine and Cosine
 FYL2X                  Compues the expression y*log2(x)
 FYL2XP1                Computes the expressoin y*log2(x+1)

 Constants Loading onto stack

 FLD1                   Loads a 1.0
 FLDL2E                 Loads Log2(e) 
 FLDL2T                 loads Log2(10)
 FLDLG2                 Loads Log10(2)
 FLDPI                  Loads PI
 FLDZ                   Loads 0

 FCOM                   Compares real numbers
 FCOMP                  Compares real numbers & pops the stack
 FCOMPP                 Compares real numbers & pops the stack twice
 FICOM                  Compares integers
 FICOMP                 Compares integers and pops the stack
 FTST                   Compares top of stack to 0
 FUCOM                  Performs an Unordered compare
 FUCOMP                 Performs an Unordered compare and pops the stack
 FUCOMPP                Performs an unordered compare and pops the stack 2x
 FXAM                   Set condition bits for value at top of stack

 FCLEX                  Clears all unmasked floating point exceptoins
 FNCLEX                 Clears all exceptions
 FDECSTP                Decrements the stack pointer
 FFREE                  Clears a stack element, making it seem as if it was poped
 FINCSTP                Incremtns the stack pointer
 FINIT                  Initalizes 387 and checks for exceptions
 FNINIT                 Initalizes 387 w/o checking for exceptions
 FLDCW                  Loads the Control word
 FLDENV                 Loads the 387 Enviroment
 FNOP                   Equivlent to NOP
 FRSTOR                 Restores the state of the 387 with a given memory area
 FSAVE                  Saves the state of the 387 to memory and checks for
                        excpetions
 FNSAVE                 Saves the state of the 387 to memory w/o checking
                        for exceptions

 FSTCW                  Stores the control word and checks for exceptions
 FNSTCW                 Stores the Control word w/o checking for excpetoins
 FSTENV                 Stores the enviroment and checks for exceptoins
 FNSTENV                Stores the enviroment w/o checking for exceptions
 FSTSW                  Stores the status word and checks for exceptions
 FNSTSW                 Stores the status word w/o checking for excpetoins
 FSTSW AX               Stores the status word into AX and checks for excpetoins
 FNSTSW AX              Stores the status word int AX w/o checking for excpetoins
 WAIT                   Suspends the CPU until the 387 is finished with operatoin.

(Thanx to "Black Art of 3D Programming" for suppling the list)

That's all there is to it.  I'm not going to go into the complexities of the
FPU, this was just a general overview so you can easily use the FPU in
your asm programs with ease as if you were using C.
 
About Toby Opferman

Professional software engineer with over 15 years...

Learn more »
Codeproject Articles

Programming related articles...

Articles »
Resume

Resume »
Contact

Email: codeproject(at)opferman(dot)com