qa.hlp (Table of Contents; Topic list)
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
                                    -♦-