Assembly Language Help (alang.hlp) (Table of Contents; Topic list)
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
 Map                                       Up Contents Index Back
────────────────────────────────────────────────────────────────────────────
 
;* 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.
;*
;* Shows:   Instructions - sahf     fld1     fld     fadd     fmul
;*                         fxch     fsubr    fchs    fsubp    fstp
;*                         fst      fstsw    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,
        aa:DWORD, bb:DWORD, cc:DWORD, r1:PDWORD, r2:PDWORD
 
        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    aa                      ; 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     notzero                 ; If C3 set, a = 0, in which case
                                        ;   solution is x = -c / b
        fld     cc                      ; Load c parameter
        fchs                            ; Reverse sign
        fld     bb                      ; 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, in which case
                                        ; division by zero
        fdiv                            ; Divide by B
        fstp    DWORD PTR es:[di]       ; Copy result and pop stack
        fstp    st                      ; Clean up stack
        jmp     exit1                   ; Return with code = 1
notzero:
        fmul    st(1), st               ; ST(1) register = 4a
        fxch                            ; Exchange ST and ST(1)
        fmul    cc                      ; 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     bb                      ; 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     tworoot                 ; If C3 set, b*b = 4ac, in which
        inc     bx                      ;   case only 1 root so set flag
tworoot:
        fsqrt                           ; Get square root
        fld     bb                      ; 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    DWORD PTR es:[di]       ; Copy result, pop stack
        fdivr                           ; Divide 2nd dividend by 2*a
        fstp    DWORD PTR ds:[si]       ; Copy result, pop stack
        jmp     exit                    ; Return with code
exit2:
        inc     bx                      ; Error code = 2 for indeterminancy
        fstp    st                      ; Clean stack
exit1:
        inc     bx                      ; Error code = 1 for single root
        fstp    st                      ; Clean stack
exit:
        mov ax, bx
        ret
 
Quadratic ENDP
 
        END
                                    -♦-