trig387.asm

来自「开放源码的编译器open watcom 1.6.0版的源代码」· 汇编 代码 · 共 532 行 · 第 1/2 页

ASM
532
字号
        shl     BL,1            ; double it for index
        mov     BH,0            ; zero high byte
        lea     BX,octtab[BX]   ; point to table entry
        mov     AX,cs:[BX]      ; get address of routine from table
        pop     BX              ; clean up the stack
        pop     BX              ; restore BX
        pop     BP              ; restore BP
        jmp     AX              ; jump to appropriate routine
endif                           ; __386__

;       at this point the 8087 stack looks like this:
;
;       st(0) = R
;       st(1) = X
;       st(2) = Y
;       st(3) = fac2
;
;       sin(theta) = Y/R
;       cos(theta) = X/R

oct4:                           ; octant 4
oct7:                           ; octant 7
        fchs                    ; change sign of R, to get -sin(theta)
oct0:                           ; octant 0
oct3:                           ; octant 3
        fstp    st(1)           ; copy R up over X
        fdivp   st(1),st(0)     ; sin(theta) = Y/R
        ret                     ; return

oct5:                           ; octant 5
oct6:                           ; octant 6
        fchs                    ; change sign of R, to get -cos(theta)
oct1:                           ; octant 1
oct2:                           ; octant 2
        fdivp   st(1),st(0)     ; cos(theta) = X/R
        fstp    st(1)           ; copy answer up over Y
        ret                     ; return
endif                           ; __FPI87__
        endproc IF@SIN
        endproc IF@DSIN


chk_C2  proc    near
        push    _BP             ; save BP
        mov     _BP,_SP         ; get access to stack
        push    _AX             ; allocate stack space
        fstsw   word ptr -2[_BP]; get status word
        fwait
        mov     AH,-1[_BP]      ; get flags
        or      AH,1            ; force carry bit on (assume arg in range)
        sahf                    ; copy to flags
        _if     p               ; if argument not in range
          fld   tbyte ptr TwoPi ; - load 2*pi
          fxch  st(1)           ; - get them in correct position
          _loop                 ; - loop (reduce argument to range)
            fprem               ; - - reduce the argument
            fstsw  word ptr -2[_BP]; - - get status
            fwait
            mov    AH,-1[_BP]   ; - - ...
            sahf                ; - - ...
          _until  np            ; - until argument in range
          fstp  st(1)           ; - copy up the new argument
          clc                   ; - indicate must retry instruction
        _endif                  ; endif
        pop     _AX             ; clean up stack
        pop     _BP             ; restore BP
        ret                     ; return
        endproc chk_C2


        defp    cos
ifdef __386__
        fld     qword ptr 4[ESP]; load argument
        call    IF@DCOS         ; calculate cos(x)
        loadres                 ; load result
else
        push    BP              ; save BP
        mov     BP,SP           ; get access to parms
        fld     qword ptr argx[BP]; load argument x
        lcall   IF@DCOS         ; calculate cos(x)
        pop     BP              ; restore BP
endif                           ; __386__
        ret_pop 8               ; return
        endproc cos


        defp    sin
ifdef __386__
        fld     qword ptr 4[ESP]; load argument
        call    IF@DSIN         ; calculate sin(x)
        loadres                 ; load result
else
        push    BP              ; save BP
        mov     BP,SP           ; get access to parms
        fld     qword ptr argx[BP]; load argument x
        lcall   IF@DSIN         ; calculate sin(x)
        pop     BP              ; restore BP
endif                           ; __386__
        ret_pop 8               ; return
        endproc sin


;<><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><>
;<>                                                                     <>
;<>     TAN function for 8087                                           <>
;<>                                                                     <>
;<>     tan387 - compute tan of st(0)                                   <>
;<>                                                                     <>
;<><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><>

        public  IF@TAN
        public  IF@DTAN
        defp    IF@DTAN
        defp    IF@TAN
ifdef __FPI87__
        do_fptan                ; calculate tan
        fstp    st(0)           ; get rid of the 1.0 pushed by fptan
        ret                     ; return
else
        chk387                  ; check for 387
        _if     e               ; if 387
          do_fptan              ; - calculate tan
          fstp   st(0)          ; - get rid of the 1.0 pushed by fptan
          ret                   ; - return
        _endif                  ; endif
ifdef __386__
        push    EBX             ; save EBX
        fldpi                   ; load pi
        sub     EBX,EBX         ; init 'invert'(BH) flag and 'negate'(BL) flag
        fxch    st(1)           ; get argument
        ftst                    ; get sign of argument
        fstsw   AX              ; . . .
        sahf                    ; get flags ZF = C3, CF = C0
        _if     b               ; if argument is negative
          fchs                  ; - make argument positive
          not   BL              ; - indicate result to be negated
        _endif                  ; endif
        _loop                   ; loop (reduce argument to mod pi)
          fprem                 ; - calculate partial remainder
          fstsw AX              ; - store status word
          sahf                  ; - ... PF = C2
        _until  np              ; until C2 is clear
        fld     tbyte ptr piby2 ; load pi/2
        fstp    st(2)           ; stack is r, pi/2
        fcom                    ; compare r to pi/2
        fstsw   AX              ; . . .
        sahf                    ; get flags ZF = C3, CF = C0
        _if     a               ; if r > pi/2
          fsub  st,st(1)        ; - tan(r) = -1/tan(r - pi/2)
          not   EBX             ; - set the 'invert' flag, complement 'negate'
        _endif                  ; endif
        fld     tbyte ptr piby4 ; load pi/4
        fcomp                   ; compare pi/4 to r and pop
        fstsw   AX              ; . . .
        sahf                    ; get flags ZF = C3, CF = C0
        _if     b               ; if r > pi/4
          fsubr st,st(1)        ; - tan(r) = 1/tan(pi/2 - r)
          not   BH              ; - complement the 'invert' flag
        _endif                  ; endif
        fstp    st(1)           ; copy r up over pi/2
        fptan                   ; st(1)/st(0) = tangent, st(0) = X, st(1) = Y
        cmp     BH,0            ; if result is inverted
        _if     ne              ; then
          fdivr                 ; - 1/tangent = st(0)/st(1)
        _else                   ; else
          fdiv                  ; - tangent = st(1)/st(0)
        _endif                  ; endif
        cmp     BL,0            ; if result to be negated
        _if     ne              ; then
          fchs                  ; - negate result
        _endif                  ; endif
        pop     EBX             ; restore registers
else
        push    BP              ; save BP
        mov     BP,SP           ; get access to stack
        push    AX              ; allocate auto
        push    AX              ; save registers
        push    BX              ; . . .
        push    CX              ; . . .
        push    DX              ; . . .
        fldpi                   ; load pi
        sub     BX,BX           ; init 'invert' flag
        sub     CX,CX           ; init 'negate' flag
        fxch    st(1)           ; get argument
        ftst                    ; get sign of argument
        fstsw   word ptr -2[BP] ; . . .
        fwait                   ; . . .
        mov     AX,-2[BP]       ; . . .
        sahf                    ; get flags ZF = C3, CF = C0
        _if     b               ; if argument is negative
          fchs                  ; - make argument positive
          not   CX              ; - indicate result to be negated
        _endif                  ; endif
        _loop                   ; loop (reduce argument to mod pi)
          fprem                 ; - calculate partial remainder
          fstsw word ptr -2[BP] ; - store status word
          fwait                 ; - wait for store to complete
          mov   AX,-2[BP]       ; - get status
          sahf                  ; - ... PF = C2
        _until  np              ; until C2 is clear
        fld     tbyte ptr piby2 ; load pi/2
        fstp    st(2)           ; stack is r, pi/2
        fcom                    ; compare r to pi/2
        fstsw   word ptr -2[BP] ; . . .
        fwait                   ; . . .
        mov     AX,-2[BP]       ; . . .
        sahf                    ; get flags ZF = C3, CF = C0
        _if     a               ; if r > pi/2
          fsub  st,st(1)        ; - tan(r) = -1/tan(r - pi/2)
          not   BX              ; - set the 'invert' flag
          not   CX              ; - complement the 'negate' flag
        _endif                  ; endif
        fld     tbyte ptr piby4 ; load pi/4
        fcomp                   ; compare pi/4 to r and pop
        fstsw   word ptr -2[BP] ; . . .
        fwait                   ; . . .
        mov     AX,-2[BP]       ; . . .
        sahf                    ; get flags ZF = C3, CF = C0
        _if     b               ; if r > pi/4
          fsubr st,st(1)        ; - tan(r) = 1/tan(pi/2 - r)
          not   BX              ; - complement the 'invert' flag
        _endif                  ; endif
        fstp    st(1)           ; copy r up over pi/2
        fptan                   ; st(1)/st(0) = tangent, st(0) = X, st(1) = Y
        or      BX,BX           ; if result is inverted
        _if     ne              ; then
          fdivr                 ; - 1/tangent = st(0)/st(1)
        _else                   ; else
          fdiv                  ; - tangent = st(1)/st(0)
        _endif                  ; endif
        or      CX,CX           ; if result to be negated
        _if     ne              ; then
          fchs                  ; - negate result
        _endif                  ; endif
        pop     DX              ; restore registers
        pop     CX              ; . . .
        pop     BX              ; . . .
        pop     AX              ; . . .
        pop     BP              ; clean off auto
        pop     BP              ; restore BP
endif                           ; __386__
        ret                     ; return
endif                           ; __FPI87__
        endproc IF@TAN
        endproc IF@DTAN


        defp    tan
ifdef __386__
        fld     qword ptr 4[ESP]; load argument
        call    IF@DTAN         ; calc the tan
        loadres                 ; load result
else
        push    BP              ; save BP
        mov     BP,SP           ; get access to parms
        fld     qword ptr argx[BP]; load argument x
        lcall   IF@DTAN         ; calculate tan(x)
        pop     BP              ; restore BP
endif                           ; __386__
        ret_pop 8               ; return
        endproc tan


        endmod
        end

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?