fsmth386.asm
来自「开放源码的编译器open watcom 1.6.0版的源代码」· 汇编 代码 · 共 454 行 · 第 1/2 页
ASM
454 行
;*****************************************************************************
;*
;* Open Watcom Project
;*
;* Portions Copyright (c) 1983-2002 Sybase, Inc. All Rights Reserved.
;*
;* ========================================================================
;*
;* This file contains Original Code and/or Modifications of Original
;* Code as defined in and that are subject to the Sybase Open Watcom
;* Public License version 1.0 (the 'License'). You may not use this file
;* except in compliance with the License. BY USING THIS FILE YOU AGREE TO
;* ALL TERMS AND CONDITIONS OF THE LICENSE. A copy of the License is
;* provided with the Original Code and Modifications, and is also
;* available at www.sybase.com/developer/opensource.
;*
;* The Original Code and all software distributed under the License are
;* distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
;* EXPRESS OR IMPLIED, AND SYBASE AND ALL CONTRIBUTORS HEREBY DISCLAIM
;* ALL SUCH WARRANTIES, INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF
;* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR
;* NON-INFRINGEMENT. Please see the License for the specific language
;* governing rights and limitations under the License.
;*
;* ========================================================================
;*
;* Description: REAL*4 math library.
;*
;*****************************************************************************
;
; inputs: EAX - operand 1 (high word, low word resp. ) (op1)
; EDX - operand 2 (op2)
;
; operations are performed as op1 (*) op2 where (*) is the selected
; operation
;
; output: EAX - result
;
; F4Add, F4Sub - written 28-apr-84
; - modified by A.Kasapi 15-may-84
; - to: Calculate sign of result
; - Guard bit in addition for extra accuracy
; Add documentation
; F4Mul - written 16-may-84
; - by Athos Kasapi
; F4DIV - written may-84 by "
;
include mdef.inc
include struct.inc
.287
modstart fsmth386
xref __8087 ; indicate that NDP instructions are present
xref __fdiv_m32
datasegment
extrn __real87 : byte ; cstart
extrn __chipbug : byte
fsadd dd _chkadd
fsmul dd _chkmul
fsdiv dd _chkdiv
enddata
xref F4DivZero ; Fstatus
xref F4OverFlow ; Fstatus
xref F4UnderFlow ; Fstatus
xdefp __FSA ; add real*4 to real*4
xdefp __FSS ; subtract real*4 from real*4
xdefp __FSM ; 4-byte real multiply
xdefp __FSD ; 4-byte real divide
defpe __FSS
or EDX,EDX ; if op2 is 0
je short ret_op1 ; then return operand 1
xor EDX,80000000h ; flip the sign of op2 and add
defpe __FSA
or EDX,EDX ; if op2 is 0
je short ret_op1 ; then return operand 1
or EAX,EAX ; if op1 is 0
_if e ; then
mov EAX,EDX ; - return operand 2
ret_op1: ret ; - return
_endif ; endif
jmp fsadd
__FSA87:
push EBP ; save EBP
mov EBP,ESP ; get access to stack
push EAX ; push operand 1
fld dword ptr -4[EBP]; load operand 1
push EDX ; push operand 2
fadd dword ptr -8[EBP]; add operand 2 to operand 1
_ret87:
fstp dword ptr -4[EBP]; store result
add ESP,4 ; clean up stack
fwait ; wait
pop EAX ; load result into EAX
cmp EAX,80000000H ; is result -0.0
_if e ; if it is then
xor EAX,EAX ; - make it positive
_endif ; endif
pop EBP ; restore EBP
ret ; return
__FSAemu:
push ECX ; save ECX
push EBX ; save EBX
;<> Scheme for calculating sign of result:
;<> The sign word is built and kept in CL
;<> Bits 0 and 1 hold the sum of the sign bits
;<> shifted out of op_1 and op_2
;<> Bit 2 holds the sign of the larger operand. It is assumed to be
;<> op_1 until op_2 is found larger
sub ECX,ECX ; clear ECX
_shl EAX,1 ; get sign of op1
_rcl CL,1 ;
mov CH,CL ;
_shl CL,1 ;
_shl CL,1 ;
add CL,CH ;
rol EAX,8 ; get exponent of op1 into AL
_shl EDX,1 ; get sign of op2
adc CL,0 ; place in CL
rol EDX,8 ; get exponent of op2 in DL
mov BL,AL ; get exponent of op1
mov BH,DL ; get exponent of op2
mov AL,0 ; zero rest of fraction
stc ; put implied 1 bit into top bit of
rcr EAX,1 ; ... fraction
mov DL,0 ; zero rest of fraction
stc ; put implied 1 bit into top bit
rcr EDX,1 ; ... of fraction
mov CH,BL ; assume op1 > op2
sub BL,BH ; calculate difference in exponents
_if ne ; if different
_if b ; - if op1 < op2
mov CH,BH ; - - get larger exponent for result
neg BL ; - - negate the shift count
xchg EAX,EDX ; - - flip operands
xor CL,4
;<> op_2 is larger, so its sign now occupies bit 2 of sign word. This
;<> information is only correct if the signs of op-1 and op-2 are different.
;<> Since we look past bit 1 for sign only if the signs are different, bit2
;<> will supply the correct information when it is needed. We get the sign of
;<> op_2 by flipping the sign of op_1, already in bit 2
_endif ; - endif
xchg CL,BL ; - get shift count
cmp CL,32 ; - if count >= 32
_if ge ; - then
sub EDX,EDX ; - - answer is 0
_else ; - else
shr EDX,CL ; - - align fraction
_endif ; - endif
xchg CL,BL ; - put back
_endif ; endif
shr CL,1 ; get bit 0 of sign word - value is 0 if
; both operands have same sign, 1 if not
_if nc ; if signs are the same
add EAX,EDX ; - add the fractions
_if c ; - if carry
rcr EAX,1 ; - - shift fraction right 1 bit
inc CH ; - - increment exponent
_if z ; - - if we overflowed
ror CL,1 ; - - - set sign of infinity
rcr EAX,1 ; - - - . . .
jmp short add_oflow;- - - handle overflow
_endif ; - - endif
_endif ; - endif
_else ; else (signs are different)
shr CL,1 ; - skip junk bit
sub EAX,EDX ; - subtract the fractions
_guess ; - guess
_quif nc ; - - quit if no borrow
inc CL ; - - sign := sign of op_2
neg EAX ; - - negate the fraction
_admit ; - admit
or EAX,EAX ; - - quit if answer is not 0
_quif ne ; - - . . .
pop EBX ; - - restore EBX
pop ECX ; - - restore ECX
ret ; - - return (answer is 0)
_endguess ; - endguess
_endif ; endif
; normalize the fraction
add EAX,00000080h ; round up fraction if required
mov AL,0 ; zero bottom 8 bits 10-jul-89
_guess underflow ; guess
_quif nc ; - quit if round up didn't overflow frac
inc CH ; - adjust exponent
_admit ; admit
_loop ; - loop (shift until high bit appears)
_shl EAX,1 ; - - shift fraction left
_quif c,underflow ; - - quit if carry has appeared
dec CH ; - - decrement exponent
_until e ; - until underflow
jmp short add_uflow ; - handle underflow
_endguess ; endguess
mov AL,CH ; get exponent
ror EAX,8 ; rotate into position
ror CL,1 ; get sign bit
rcr EAX,1 ; shift it into result
pop EBX ; restore EBX
pop ECX ; restore ECX
ret ; return
add_uflow: ; handle underflow
pop EBX ; restore EBX
pop ECX ; restore ECX
jmp F4UnderFlow ; goto underflow routine
add_oflow: ; handle overflow
pop EBX ; restore EBX
pop ECX ; restore ECX
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?