DEBUG script for a 1K command-line calculator follows this
message.  An 80387 (e.g., 486DX or Pentium) is required.
Expression rules are like those for Visual Basic/Foxpro.

Syntax: CALC387 math_expression         Calculates result
        CALC387                         Shows usage

1+4*2^3-5/4%1 --> 32.75                 Usual precedence
((1+4)*2)^3       1000                  Can override
-MEM^(1/3)       -10                    MEM is last result
1 / 7             0.14286               Default 5 decimals
1.0000000/7       0.1428571             Extra implied
1E0/7             1.428571428571429E-1  Max if E-notation
E*COS(PI)        -2.71828               Constants e and pi
1/0               ?                     Error indicator

LOG/LN/LG/SIN/COS/TAN/INT/SIGN/RND/ASIN/ACOS/ATAN/SQR/ABS

If no 80387 is detected, question mark error indicator is
always displayed, no matter what the expression is.

I wrote program to learn about the 80387.  I am passing
it along in case you haven't tried 80387 programming yet.
The examples I ran across were fragments or were 8087-
compatible.  Some hindered more than helped.

Unassemble with DEBUG or else e-mail me for source.  Some
instructions unknown to DEBUG are used:  PUSHA/POPA/
SHL AL,4/FSIN/FCOS/ROR AX,4/SHR AH,4/FNSTSW AX.  Each
appears once except last one.  0.2K of data follows 0.8K
of code.

Program has four sections:  top level calling sequence,
recursive expression parser, 25 short FPU jump table
routines, and two long FPU I/O routines--ASCII number to
ST and vice versa.

Here are a few 80387 tips.  They came from (sometimes
frustrating) real mode experiments/debugging/reading.

o  Start learning from DEBUG, not MASM.  Use FBLD/FBSTP to
   test instructions and view results.  Keep BCD power of
   ten around for FMUL/FDIV scaling.

o  The stack model of operation with implied operands and
   pops is typical way to program.  Explicit instructions
   are sometimes better.  E.g., FLD ST/FMUL squares ST,
   but lone instruction FMUL ST(0),ST does same.

o  If you are not sure of implied operands and pops for
   instruction, DEBUG unassembly fleshes them out.  ST(0)
   and ST are same, but DEBUG is picky about where each
   form is used.

o  FPU state is untouched by DOS.  Program uses this to
   get presumed MEM result from prior run.  Intervening
   use of coprocessor destroys value.

o  You can test for 80387 easily (25 bytes in program).
   This also indirectly assures at least 80386.  Replace
   FNSAVE in test with FNINIT if prior FPU state unneeded.

o  FWAITs are *not* needed anywhere in 80387 programs with
   exceptions masked.  So use .386/.387 directives and FN*
   forms of instructions in MASM.  In contrast, FWAITs
   were essential in 8087 programs.

o  CPU runs concurrently with most 80387 instructions, but
   80387 and CPU are synched for memory load/store.  E.g.,
   try FLDPI/FDIVP ST(0),ST then FLDPI/FBSTP [DI] in 32M
   iteration loop with do-nothing CPU delay after each.
   Vary delay without change to code size to note effect.

o  With exceptions masked, 80387 always provides a result.
   You can usually postpone error checking awhile then use
   FXAM to detect garbage like empty/infinity/NAN.  CALC387
   completes calculation before doing this check.

   For trig functions, C2 is set on range error with no
   other action taken.  Program forces an exception in this
   case so that FXAM later detects error.  Accuracy is shot
   here.  Modulo reduction of larger operand is pointless.

o  With exceptions unmasked, next FPU instruction triggers
   interrupt, *not* instruction producing exception.  The
   offending instruction acted like an FNOP.  Your handler
   must take action, clear exceptions, and chain out (or
   duplicate short default BIOS handler).

   Int 75h is real mode FPU exception interrupt (not used
   in program).  The main protected mode interrupt is 10h.

   Since an FPU store can produce an exception (e.g., if ST
   is large and FIST WORD PTR Small is executed), an FWAIT
   may be needed afterwards.  This trips handler to take
   action before CPU portion of program references stored
   value (possibly adjusted by your handler).  The comment
   "wait for store to complete" in some 80387 examples I've
   seen is highly misleading here.  It should be "trigger
   possible exception handling".

   You'll probably leave exceptions masked, as I did in
   program, and settle for simple default handling.  But I
   found FWAIT confusing.  Finding a legitimate 80387 use
   for it gave me some peace of mind.

o  Internal real sign/exponent/mantissa is 1/15/64 bits.
   You normally only need to know this for implied limits
   on exponent and precision.  The load/store instructions
   automatically convert from/to other formats.

o  80387 maintains internal 84-bit pi, which is slighly
   more accurate than rounded 80-bit pi from FLDPI.

o  FNSTSW AX unassembles in DEBUG as ESC 3C,AX.  The ESC
   instruction (in MASM 5.0 Reference but omitted from
   6.1 version) was once the only way to program FPU.

o  6.1 version also omits following 80387 info.  Low 6 bits
   are mask/exception bits.  C0-C3 are condition flags.
   RC/PC are rounding/precision controls.  SP is stack
   pointer.  B/ES/SF are busy/error summary/stack error
   flags.  Default CW rounds to nearest or even, flags
   64-bit precision, and masks exceptions.  Program
   explicitly references only C3/C2/C0 (FNSTSW AX/SAHF).

   CW:  x x x x RC(2) PC(2)  x  x  PM UM OM ZM SM IM
   SW:  B C3 SP(3) C2 C1 C0  ES SF PE UE OE ZE SE IE

o  Believe nothing--test everything--including all above.

Comments/corrections/requests for source are welcome.

craig.hessel@mailgw.er.doe.gov

:BEGIN DEBUG SCRIPT
A
DB  59 0E 51 99 BE 81 00 8B FE 57 4F 42 41 AA AC 3C
DB  0D 74 15 24 DF 74 F7 3C 41 73 F1 34 10 3C 18 74
DB  EA 3C 19 75 E7 4A 75 E4 5E 4A 75 48 BA 93 04 49
DB  74 45 B0 19 AA 8B FA 54 58 2B C4 75 37 DD 35 48
DB  DF E0 40 74 2F D9 EE D9 E4 DB E3 DF E0 9E 74 24
DB  BD 05 00 E8 3C 00 D9 E5 DF E0 9E 72 14 7B 02 74
DB  10 57 D9 C0 E8 F8 01 5A B8 24 09 AA E9 E1 FE 0E
DB  51 E8 49 01 BA 34 04 EB EF E8 00 00 86 C4 BF 8D
DB  04 B1 07 F2 AE 8B D9 8A 87 41 04 38 C4 C3 3C 18
DB  75 DD E8 40 00 AC 3C 19 74 F3 E8 E1 FF E3 D0 4E
DB  E8 02 00 EB F0 83 EC 0A 8B DC DB 3F AC 50 E8 24
DB  00 58 8A 24 50 E8 C1 FF 76 05 E8 E8 FF EB F2 58
DB  93 8B DC DB 2F D9 C9 BB 3A 04 9C E8 30 00 9D 73
DB  D7 83 C4 0A C3 B1 13 BF 47 04 33 C0 51 03 F8 8A
DB  0D 47 60 F3 A6 61 91 59 E0 F2 BF B5 04 75 15 03
DB  F0 51 80 F9 10 73 03 E8 DB FF 58 BB 28 04 D7 05
DB  9E 02 FF E0 AC 3C 0A 72 04 3C 1E 75 81 57 99 E8
DB  48 01 33 DB 86 D6 3C 1E 75 17 8A E6 E8 3A 01 8A
DB  C2 02 C3 3C 13 72 02 B0 13 98 3B C5 72 01 95 2A
DB  D7 4E B1 09 33 C0 F3 AB 5F 93 98 52 50 56 8B F7
DB  B1 0A EB 06 AD C0 E0 04 0A E0 4F 88 25 E2 F5 5E
DB  AC 3C 45 75 1C 49 AC 8B E9 3C 1D 74 0F 41 3C 1B
DB  74 0A EB 09 98 93 F7 26 2E 04 03 D8 AC 3C 0A 72
DB  F3 4E E3 02 F7 DB 59 2B D9 58 8A C8 3B D9 9C 8A
DB  CC 83 EB 12 03 D9 DF 25 E8 67 00 74 0E E8 32 00
DB  89 1D D9 E9 DE 0D DE C1 E8 9B 00 9D 7C 02 D9 FC
DB  C3 E8 0E 00 D9 C9 EB 07 E8 07 00 EB 02 D9 E8 D9
DB  F3 C3 D9 E8 D9 C1 D8 C8 DE E9 D9 FA C3 DB 2E A1
DB  04 C3 D9 E8 D9 C9 D9 F1 C3 E8 F6 FF D9 EA EB 20
DB  E8 EF FF D9 E9 EB 19 D9 E1 C3 D9 EB C3 D9 FE EB
DB  02 D9 FF D9 E8 EB 02 D9 F2 DF E0 9E 7B 02 D9 EE
DB  DE F9 D9 E4 DF E0 9E C3 D9 EA EB 3A E8 1C 00 DE
DB  E9 C3 DE C1 C3 DE C9 C3 D9 EE D9 C9 E8 E3 FF 74
DB  F4 73 21 D9 E1 E8 1C 00 D9 E0 C3 D9 C0 D9 E8 D9
DB  C9 D9 F8 DF E0 9E 7A F9 EB 17 7D 02 89 0C DF 04
DB  DF 06 2E 04 D9 F1 E8 E2 FF D9 F0 D9 E8 DE C1 D9
DB  FD D9 C9 DD D8 C3 84 C0 75 07 84 E4 75 07 43 EB
DB  08 B4 FF B7 FF FE C7 42 AA AC 3C 0A 72 E8 C3 BA
DB  20 20 E8 09 00 79 F7 89 1C DF 04 BA 45 2B 33 DB
DB  E8 7F FF 73 02 B6 2D 92 AB 74 49 D9 E1 E8 50 FF
DB  D9 C0 73 04 D9 E8 DE E9 E8 71 FF DF 14 B3 11 87
DB  1C D9 E0 DE 04 DE C1 E8 96 FF B1 02 3B E9 7C 06
DB  29 2C 29 1C 39 0C E8 81 FF D9 FC DC F9 D9 C9 D9
DB  FC DE C9 B1 12 E8 74 FF D8 D9 DF E0 9E 77 05 DE
DB  36 2E 04 43 DF 34 33 C9 85 ED 78 1A B8 13 00 85
DB  DB 78 08 D1 E5 3B C3 D1 DD EB 0B F7 DB 3B DD 76
DB  01 93 8B CB F7 DB B0 30 F3 AA B1 09 03 F1 4E 98
DB  8A 04 C1 C8 04 C0 EC 04 0D 30 30 AB E2 F0 B1 16
DB  F3 AA 83 EF 28 B1 11 85 ED 51 9C 78 04 8B CD 03
DB  FB B0 2E 41 47 86 05 E2 FB B1 80 FD F3 AE 47 B0
DB  2E F3 AE FC AF 9D 5D C3 7C 7A 39 1C 0F 03 0A 00
DB  6A 5E 49 43 3F 24 2B 32 1F 3C 5A 6C 81 52 67 61
DB  64 00 03 02 02 02 01 01 45 02 50 49 03 4D 45 4D
DB  03 4C 4F 47 02 4C 4E 02 4C 47 03 53 49 4E 03 43
DB  4F 53 03 54 41 4E 03 49 4E 54 04 53 49 47 4E 03
DB  52 4E 44 04 41 53 49 4E 04 41 43 4F 53 04 41 54
DB  41 4E 03 53 51 52 03 41 42 53 01 1D 01 1B 1D 1A
DB  1F 15 5E 4E 65 65 64 20 38 30 33 38 37 3A 20 43
DB  41 4C 43 33 38 37 20 5B 6D 61 74 68 5F 65 78 70
DB  72 65 73 73 69 6F 6E 5D 20 04 20 43 52 48 2F 32
DB  38 20 4A 61 6E 20 39 36 0D 0A 45 2E 67 2E 2C 20
DB  31 2B 34 2A 32 5E 33 2D 35 2F 34 25 31 2C 20 31
DB  45 30 2F 37 2C 20 28 4D 45 4D 2B 31 29 5E 31 2E
DB  35 2C 20 6F 72 20 45 2A 43 4F 53 28 50 49 29 24

RCX
400
N CALC387.COM
W
Q
:END DEBUG SCRIPT
