e86fprem.inc
来自「开放源码的编译器open watcom 1.6.0版的源代码」· INC 代码 · 共 182 行
INC
182 行
modstart e86fprem
xdefp __fprem
; int __fprem( LD *x, LD *modulus )
;
defp __fprem
push SI ; save SI
push DI ; save DI
push CX ; save CX
push BX ; save BX
mov SI,AX ; op1
mov DI,DX ; op2
mov AX,8[SI] ; get exponent of op1
mov DX,8[DI] ; get exponent of op2
_guess ; guess: op1 is 0
mov CX,[SI] ; - quit if op1 is not 0
or CX,2[SI] ; - check the higher order words
or CX,4[SI] ; - ...
or CX,6[SI] ; - ...
_quif ne ; - ...
test AX,7FFFh ; - quit if exponent not 0
_quif ne ; - ...
_return_0:
sub AX,AX ; - quotient is 0
pop BX ; - restore registers
pop CX ; - ...
pop DI ; - ...
pop SI ; - ...
ret ; - return
_endguess ; endguess
_guess ; guess: op2 is 0
mov CX,[DI] ; - quit if op2 is not 0
or CX,2[DI] ; - check the higher order words
or CX,4[DI] ; - ...
or CX,6[DI] ; - ...
_quif ne ; - quit if op2 is not 0
test DX,7FFFh ; - quit if exponent is not 0
_quif ne ; - ...
mov [SI],CX ; - set result to 0
mov 2[SI],CX ; - ...
mov 4[SI],CX ; - ...
mov 6[SI],CX ; - ...
mov 8[SI],CX ; - ...
jmp _return_0 ; - return 0
_endguess ; endguess
push BP ; save BP
push SI ; save address for remainder
push 6[DI] ; push divisor
push 4[DI] ; ...
push 2[DI] ; ...
push [DI] ; ...
mov BP,SP ; point to divisor
push AX ; save sign+exponent of op1
push DX ; save sign+exponent of op2 (modulus)
mov DI,DX ; get exponent of op2
and DI,7FFFh ; isolate exponent of op2
mov BX,4[SI] ; load dividend
mov CX,2[SI] ; ...
mov DX,[SI] ; ...
mov SI,6[SI] ; ...
xchg AX,SI ; get difference of exponents in SI
and SI,7FFFh ; isolate exponent of op1
sub SI,DI ; calculate difference in exponents
_if ge ; if operand >= modulus
mov DI,0 ; - set quotient to 0
_loop ; - loop
_guess ; - - guess
cmp 6[BP],AX ; - - - The purpose of this guess is to
jb try ; - - - determine if the divisor will subtract
ja didnt_go ; - - - from the dividend without a borrow, and to
cmp 4[BP],BX ; - - - branch to the appropriate routine
jb try ; - - -
ja didnt_go ; - - -
cmp 2[BP],CX ; - - -
_quif ne ; - - -
cmp 0[BP],DX ; - - -
je try ; - - -
_endguess ; - - endguess
_if c ; - - if the carry is set (ie the modulus will
; - - - definitely subtract from the dividend
; - - - without a borrow
try:
sub DX,0[BP] ; - - - subtract divisor from dividend
sbb CX,2[BP] ; - - - . . .
sbb BX,4[BP] ; - - - . . .
sbb AX,6[BP] ; - - - . . .
stc ; - - - set carry to indicate that modulus was
; - - - successfully subtracted from dividend
_endif ; - - endif
didnt_go: _rcl DI,1 ; - - rotate 1 (if carry set) into quotient word
dec SI ; - - adjust difference in exponents
jl _done ; - - quit if done
_shl DX,1 ; - - shift dividend left
_rcl CX,1 ; - - . . .
_rcl BX,1 ; - - . . .
_rcl AX,1 ; - - . . .
jc try
;<> If bit 5 of dividend is set here, we didnt subtract the modulus from the
;<> dividend (recall that the divisor has a 1 in the msb -- if we subtracted
;<> it from the dividend without a borrow, the dividend would not have a one
;<> in its msb to be shifted into bit 5 tested for in the condition above. If
;<> we are rotating a bit into bit 5, the dividend is now big enough that we
;<> can be sure of subtracting out the divisor without a borrow, as we have
;<> shifted it left one digit.
or AX,AX ; - - check top bit of dividend
_until ns ; - until
jmp short didnt_go ; - continue
_done: sub SI,SI ; - set SI to 0
; normalize the remainder in AX:BX:CX:DX
_guess ; - guess: number is zero
or AX,AX ; - - quit if not zero
_quif ne ; - - ...
or BX,BX ; - - ...
_quif ne ; - - ...
or CX,CX ; - - ...
_quif ne ; - - ...
or DX,DX ; - - ...
_quif ne ; - - ...
_admit ; - admit: not zero
_loop ; - - loop
or AX,AX ; - - - quit if number is normalized
_quif s ; - - - . . .
_shl DX,1 ; - - - shift result left
_rcl CX,1
_rcl BX,1
_rcl AX,1
dec SI ; - - - decrement exponent
_endloop ; - - endloop
pop BP ; - - restore exponent+sign of modulus
push BP ; - - save it again
and BP,7FFFh ; - - isolate exponent of modulus
add SI,BP ; - - adjust exponent of result
_endguess ; - endguess
_else ; else
add SI,DI ; - restore exponent
sub DI,DI ; - set quotient to 0
_endif ; endif
mov BP,SP ; get access to temps
mov BP,2[BP] ; get sign+exponent of op1
and BP,8000h ; isolate sign
or SI,BP ; merge it with exponent
pop BP ; restore sign+exponent of modulus
xor BP,SI ; calculate sign of quotient
_if s ; if quotient should be negative
neg DI ; - negate quotient
_endif ; endif
or AX,AX ; test high word of remainder
_if e ; if remainder is zero
sub SI,SI ; - zero sign and remainder
_endif ; endif
add SP,10 ; clean up the stack
_return:
pop BP ; restore address for remainder
xchg BP,SI ; ....
mov [SI],DX ; store remainder
mov 2[SI],CX ; ...
mov 4[SI],BX ; ...
mov 6[SI],AX ; ...
mov 8[SI],BP ; ...
mov AX,DI ; get quotient
pop BP ; restore BP
pop BX ; restore registers
pop CX ; ...
pop DI ; ...
pop SI ; ...
ret ; return
endproc __fprem
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?