; Program used to calculate SIN/COS of a number
; 1995 Robert Piontek
 
FACT  DD  -2,-6,24,120,-720,-5040
 
; Before calling SIN function, set AX to (degrees/90) * 65536 where
; 0 <= degrees < 90.
 
SIN:
 PUSH ECX,EDX,ESI,EDI,BP  ; Save registers
 
 AND EAX,0FFFF        ; Zero out high word of EAX
 MOV EBX,EAX          ; Store in EBX
 SHR EBX,1            ; Divide EBX by 2
 ADD EAX,EBX          ; Add to EAX
 SHR EBX,3            ; Divide EBX by 8
 ADD EAX,EBX          ; Add to EAX
 SHR EBX,3            ; Divide EBX by 8
 ADD EAX,EBX          ; Add to EAX
 SHR EBX,4            ; Divide EBX by 16
 ADD EAX,EBX          ; Add to EAX
 MOV EBX,EAX          ; Store result in EBX
 MOV ESI,EAX          ; Load SIN value with result
 MOV EDI,010000       ; Load COS value with 1.0000 * 65536
 MOV BP,0
SINL:
 MUL EBX              ; Multiply EAX by EBX
 MOV AX,DX            ; Load AX with whole part
 ROL EAX,16           ; Rotate whole part to high word of EAX
 MOV ECX,EAX          ; Store in ECX
 XOR DX,DX            ; Zero out DX for divide operation
 IDIV FACT[BP]        ; Divide by N!
 ADD EDI,EAX          ; Add cos value with result
 MOV EAX,ECX          ; Restore EAX
 MUL EBX              ; Multiply EAX by EBX
 MOV AX,DX            ; Load AX with whole part
 ROL EAX,16           ; Rotate whole part to high word of EAX
 MOV ECX,EAX          ; Store in ECX
 XOR DX,DX            ; Zero out DX for divide operation
 IDIV FACT[BP+4]      ; Divide by N!
 ADD ESI,EAX          ; Add SIN value with result
 MOV EAX,ECX          ; Restore EAX
 ADD BP,8             ; Add BP with 8 for next ! value
 CMP BP,018           ; Have we reached last ! number
 JNE SINL
 
 MOV AX,SI            ; AX contains SIN(number)
 MOV BX,DI            ; BX contains COS(number)
 POP BP,EDI,ESI,EDX,ECX    ; Restore trashed registers
 RET
