Important Notice
The pages on this site contain documentation for very old MS-DOS software,
purely for historical purposes.
If you're looking for up-to-date documentation, particularly for programming,
you should not rely on the information found here, as it will be woefully
out of date.
Quadratic
◄Example► ◄Back► ◄Contents► ◄Index►
──────────────────────────────────────────────────────────────────────────────
;* Quadratic - Solves for the roots of a quadratic equation of form
;* A*x*x + B*x + C = 0
;* using floating-point instructions. This procedure requires either a math
;* coprocessor or emulation code. If executing within the QuickAssembler
;* environment, emulation is automatically provided if a coprocessor is not
;* installed. If executing from the QCL command line, the /FPi switch must
;* be specified if a coprocessor is not installed. For example, to create
;* the MATHDEMO.EXE example program with floating-point emulation, enter the
;* following line:
;* QCL /Cx mathdemo.c /FPi math.asm common.asm
;*
;* Shows: Instructions - sahf fld1 fld fadd fmul
;* fxch fsubr fchs fsubp fstp
;* fst fdivr fwait ftst
;*
;* Params: a - Constant for 2nd-order term
;* b - Constant for 1st-order term
;* c - Equation constant
;* r1 - Pointer to 1st root
;* r2 - Pointer to 2nd root
;*
;* Return: Short integer with return code
;* 0 if both roots found
;* 1 if single root (placed in r1)
;* 2 if indeterminate
Quadratic PROC \
USES ds di si, \
a:DWORD, b:DWORD, c:DWORD, r1:PTR DWORD, r2:PTR DWORD
LOCAL status:WORD ; Intermediate status
LoadPtr es, di, r1 ; ES:DI points to 1st root
LoadPtr ds, si, r2 ; DS:SI points to 2nd root
sub bx, bx ; Clear error code
fld1 ; Load top of stack with 1
fadd st, st ; Double it to make 2
fld st ; Copy to next register
fmul a ; ST register = 2a
ftst ; Test current ST value
fstsw status ; Copy status to local word
fwait ; Ensure coprocessor is done
mov ax, status ; Copy status into AX
sahf ; Load flag register
jnz @F ; If C3 set, a = 0, in which case
; solution is x = -c / b
fld b ; Load b parameter
ftst ; Test current ST value
fstsw status ; Copy status to local word
fwait ; Ensure coprocessor is done
mov ax, status ; Copy status into AX
sahf ; Load flag register
jz exit2 ; If C3 set, b = 0, so don't divide
fld st ; Copy b to next register
fld c ; Load C parameter
fchs ; Reverse sign
fxch ; Exchange ST and ST(1)
fdiv ; Divide c by b
fst DWORD PTR es:[di] ; Copy result
jmp SHORT exit1 ; Return with code = 1
@@: fmul st(1), st ; ST(1) register = 4a
fxch ; Exchange ST and ST(1)
fmul c ; ST register = 4ac
ftst ; Test current ST value
fstsw status ; Copy status to local word
fwait ; Ensure coprocessor is done
mov ax, status ; Copy status into AX
sahf ; Load flag register
jp exit2 ; If C2 set, 4*a*c is infinite
fld b ; Else load b parameter
fmul st, st ; Square it; ST register = b*b
fsubr ; ST register = b*b - 4*a*c
ftst ; Test current ST value
fstsw status ; Copy status to local word
fwait ; Ensure coprocessor is done
mov ax, status ; Copy status into AX
sahf ; Load flag register
jc exit2 ; If C0 set, b*b < 4ac
jnz @F ; If C3 set, b*b = 4ac, in which
inc bx ; case only 1 root so set flag
@@: fsqrt ; Get square root
fld b ; Load b parameter
fchs ; Reverse sign
fxch ; Exchange ST and ST1
fld st ; Copy square root to next reg
fadd st, st(2) ; ST = -b + sqrt(b*b - 4*a*c)
fxch ; Exchange ST and ST1
fsubp st(2), st ; ST = -b - sqrt(b*b - 4*a*c)
fdiv st, st(2) ; Divide 1st dividend by 2*a
fstp WORD PTR es:[di] ; Copy result, pop stack
fdivr ; Divide 2nd dividend by 2*a
fstp WORD PTR ds:[si] ; Copy result, pop stack
jmp SHORT exit ; Return with code
exit2: inc bx ; Error code = 2 for indeterminancy
exit1: inc bx ; Error code = 1 for single root
exit: mov ax, bx
ret
Quadratic ENDP
-♦-