; Listing2-3.asm
;
; A program that demonstrates caling the math_acsc
; function.

            option  casemap:none
            
; Include the aoalib (ANSI strings) and aoamath
; libraries:

            include    aoalib.inc   
            include    math.inc  
            includelib aoalib.lib   
            includelib aoamath.lib  

            
            .const

; Program title:

            align   word
ttlStr      byte    "Listing 2-3", 0
signBit     qword   8000000000000000h


            .data
            align   16
aVal        real8   -4.0
one         real8   1.0
zero        real8   0.0
aResult     real8   0.0
point5      real8   0.5


            .code

; External definitions for C/C++ atan function

            externdef atan:proc
        
; Here is the main assembly language function.

            
            public  asmMain
asmMain     proc
            push    rbx
            sub     rsp, 64 ;Shadow storage + alignment
            
; Repeat for aVal = -4.0 to +4.0 by 0.5:

            mov     rbx, 21
pgmLoop:

; Compute the assembly language result:

            math(acsc) aVal
            fstp    aResult
            mov     rdx, aVal
            mov     r8, aResult
            call    print
            byte    "ASM.acsc(%4.1f)=%6.3f  ", 0
            
; There is no ACSC function in C/C++, must compute
; it as acsc(x) = Atan(Sign(x) / Sqrt(x * x - 1))
             
            movsd   xmm0, one                 
            movsd   xmm2, aVal      ;x
            movsd   xmm1, xmm2
            mulsd   xmm2, xmm2      ;Compute x*x
            subsd   xmm2, xmm0      ;Compute x*x-1
            
; Compute xmm0=signum(x) by simply copying
; x's sign bit to '1':

            movsd   xmm3, signBit   ;xmm0=signum(x)
            pand    xmm3, xmm1
            por     xmm0, xmm3
            
; See if x*x-1 is less than or equal to zero
; before we try to compute its square root:

            comisd  xmm2, zero      ;Error if <= 0
            jbe     badSqrt
            
; Compute sqrt(x*x-1):

            sqrtsd  xmm1, xmm2
            
; Compute sign(x) / sqrt(x*x-1):

            divsd   xmm0, xmm1
            
; Compute Atan(Sign(x) / Sqrt(x * x - 1)):
 
            call    atan
            
; Print the C result:

            movsd   aResult, xmm0
            mov     rdx, aVal
            mov     r8, aResult
            call    print
            byte    "C.acsc(%4.1f)=%6.3f", nl, 0
            jmp     nextIteration

; Drop down here if we tried to take the square root
; of a negative number or divide by zero:
            
badSqrt:    mov     rdx, aVal
            call    print
            byte    "C.acsc(%4.1f)= -nan", nl, 0
            
nextIteration:
            fld     point5
            fld     aVal
            faddp
            fstp    aVal
            dec     rbx
            jnz     pgmLoop
            
            
 
allDone:    add     rsp, 64
            pop     rbx
            ret     ;Returns to caller
        
asmMain     endp
            end