_ASSEMBLY LANGUAGE PROGRAMMING FOR THE 80X87_
by Nicholas Wilt

[LISTING ONE]

; pow.asm: integer power function callable from Borland C++.
; Copyright (C) 1991 by Nicholas Wilt.  All rights reserved.

.MODEL  LARGE,C

.CODE

; double intpow(double x, unsigned int y);
; Returns x^y.

    PUBLIC  intpow

intpow  PROC    X:QWORD,Y:WORD
    fld1            ; Load 1 into the 80x87
    mov cx,Y        ; Get y
    fld X       ; Load x into the 80x87

    jcxz    Return      ; If y already zero, return

TestY:  test    cx,1        ; Is the LSB of y set?
    jz  NextIteration   ; Jump if no
    fmul    st(1),st    ; ret *= x
NextIteration:
    fmul    st,st(0)    ; Square x
    shr cx,1        ; y >>= 1
    jnz TestY       ; Continue if nonzero
Return: fstp    st      ; Pop stack.  Return value is
                ; now in ST(0).
    ret
intpow  ENDP

    END



[LISTING TWO]

; sumarray(), a Borland C++-callable function to sum the values
; in an array of floats.

; Copyright (C) 1991 by Nicholas Wilt.  All rights reserved.

.MODEL  LARGE,C

.CODE

; double sumarray(float *arr, int n);
;   Returns sum of the n elements in arr.

    PUBLIC  sumarray

sumarray    PROC    ARR:DWORD,N:WORD
    les bx,ARR      ; ES:BX <- pointer to arr
    mov cx,N        ; Get number of elements
    fldz            ; Load zero
    jcxz    LeaveSum    ; Leave if count is 0.
DoSum:  fadd    dword ptr es:[bx] ; Add value in array to ST(0).
    add bx,4        ; Point to next value in array.
    loop    DoSum       ; Loop until done.
LeaveSum:           ; Return value in ST(0).
    ret
sumarray    ENDP

    END



[LISTING THREE]

; quad.asm: integer power function callable from Borland C++.
; Copyright (C) 1991 by Nicholas Wilt.  All rights reserved.

.MODEL  LARGE,C

.CODE

; int solve_quadratic(double a, double b, double c, double *x1, double *x2);
; solve_quadratic takes the coefficients of a quadratic polynomial
; and finds the roots of that polynomial.  If there are two real
; roots, it writes them back to x1 and x2 and returns 1.  If the
; discriminant b^2-4*a*c is less than 0, the roots are not real
; and solve_quadratic returns 0.
; The quadratic formula is as follows:
;   (-b +/- sqrt(b*b-4*a*c)) / 2*a

    PUBLIC  solve_quadratic

solve_quadratic PROC    A:QWORD,B:QWORD,C:QWORD,X1:DWORD,X2:DWORD
                ; Comments show stack contents
                ; separated by | signs
                ; Stack top is at left
    fld A       ; a     Here, ST(0) contains a.
    fld B       ; b | a     Now ST(1) has a.  Etc.

    ; Negate b -- squaring it is sign-independent, and we need b
    ; negated in all the other instances in the formula.
    fchs

    fld C       ; c | b | a
    fld st(1)       ; b | c | b | a
    fmul    st,st(0)    ; b*b | c | b | a

    ; Just plain fxch has an implicit operand of ST(1).

    fxch            ; c | b*b | b | a
    fadd    st,st(0)    ; 2*c | b*b | b | a
    fadd    st,st(0)    ; 4*c | b*b | b | a
    fmul    st,st(3)    ; 4*a*c | b*b | b | a
    fsubp   st(1), st   ; b*b-4*a*c | b | a
    ftst            ; Compare against 0

    ; We've computed b*b-4*a*c.  If negative, we return 0.
    ; To do the comparison, we have to store the 80x87 status
    ; word and use sahf to store it into the flags.  Once it's
    ; in the flags, we can jump on above or equal (jae) to jump if the
    ; number tested is greater than 0 after the FTST instruction above.
    sub sp,2        ; Quick, allocate a local
    mov bx,sp       ; Point BX at it
    fstsw   ss:[bx]     ; Store the 80x87's status word there
    mov ax,ss:[bx]  ; AX <- status word
    add sp,2        ; Deallocate the local
    sahf            ; Get SW into flags
    jae ComputeResults  ; Jump if positive
    fstp    st      ; This instruction clears the stack
    fstp    st      ; we've got three values on the stack
    fstp    st      ; to clear
    xor ax,ax       ; Return 0 - no roots found.
    jmp short LeaveQuadratic
ComputeResults:
    fsqrt           ; Find square root of discriminant
    fxch    st(2)       ; a | b | sqrt(b*b-4*a*c)
    fadd    st,st(0)    ; 2*a | b | sqrt(b*b-4*a*c)
    fld st(1)       ; b | 2*a | b | sqrt(b*b-4*a*c)
    fadd    st,st(3)    ; b+sqrt(b*b-4*a*c) | 2*a | b | sq..
    fdiv    st,st(1)    ; x1 | 2*a | b | sqrt(b*b-4*a*c)
    les bx,X1       ;
    fstp    qword ptr es:[bx] ; 2*a | b | sqrt(b*b-4*a*c)
    fxch            ; b | 2*a | sqrt(b*b-4*a*c)
    fsubrp  st(2),st    ; 2*a | -b - sqrt(b*b-4*a*c)
    fdiv            ; x2
    les bx,X2       ; Store x2
    fstp    qword ptr es:[bx]
    mov ax,1        ; Return 1
LeaveQuadratic:
    ret         ; Return
solve_quadratic ENDP

    END

