fsmth386.asm
来自「开放源码的编译器open watcom 1.6.0版的源代码」· 汇编 代码 · 共 454 行 · 第 1/2 页
ASM
454 行
jmp F4OverFlow ; handle overflow
endproc __FSA
endproc __FSS
;=====================================================================
defpe __FSM
;<> multiplies X by Y and places result in C.
;<> X2 and X1 represent the high and low words of X. Similarly for Y and C
;<> Special care is taken to use only six registers, so the code is a bit
;<> obscure
_guess ; guess: answer not 0
or EAX,EAX ; - see if first arg is zero
_quif e ; - quit if op1 is 0
or EDX,EDX ; - quit if op2 is 0
_quif e ; - . . .
jmp fsmul ; - perform multiplication
_endguess ; endguess
sub EAX,EAX ; set answer to 0
ret ; return
__FSM87:
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
fmul dword ptr -8[EBP]; mulitply operand 1 by operand 2
jmp _ret87 ; goto common epilogue
__FSMemu:
push ECX ; save ECX
_shl EAX,1 ; get sign of op1
_rcl ECX,1 ; save it
_shl EDX,1 ; get sign of op2
adc ECX,0 ; calc sign of result
ror ECX,1 ; move to the top
rol EAX,8 ; move exponent of op1 into AL
rol EDX,8 ; move exponent of op2 into DL
sub AL,7Fh ; remove bias from exponents
sub DL,7Fh ; . . .
add DL,AL ; add exponents
_if o ; if over or underflow
js short mul_oflow ; - report overflow if signed
jmp short mul_uflow ; - handle underflow
_endif ; endif
cmp DL,81h ; check for underflow
jle short mul_uflow ; quit if underflow
add DL,7fh+1 ; bias exponent
mov CL,DL ; save exponent
mov AL,0 ; zero rest of fraction
mov DL,0 ; ...
stc ; turn on implied 1 bit in fraction
rcr EAX,1 ; ...
stc ; turn on implied 1 bit in fraction
rcr EDX,1 ; ...
mul EDX ; calc fraction
or EDX,EDX ; check top bit
_if ns ; if not set
_shl EDX,1 ; - move left 1
dec CL ; - decrement exponent
_endif ; endif
sar EDX,8 ; place fraction in correct location
adc EDX,0 ; round up
adc CL,0 ; increment exponent if necessary
jz short mul_oflow ; report overflow if required
shl EDX,9 ; get rid of implied 1 bit
mov DL,CL ; get exponent
ror EDX,8 ; rotate into position except for sign
_shl ECX,1 ; get sign
rcr EDX,1 ; place sign in result
mov EAX,EDX ; place in correct register
pop ECX ; restore ECX
ret ; return
mul_uflow: ; underflow
pop ECX ; restore ECX
jmp F4UnderFlow ; . . .
mul_oflow: ; overflow
mov EAX,ECX ; get sign
pop ECX ; restore ECX
jmp F4OverFlow ; report overflow
endproc __FSM
;====================================================================
defpe __FSD
jmp fsdiv
__FSDbad_div:
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
call __fdiv_m32 ; divide operand 1 by operand 2
push EDX ; __fdiv_m32 popped operand 2, _ret87 wants it
jmp _ret87 ; goto common epilogue
__FSD87:
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
fdiv dword ptr -8[EBP]; divide operand 1 by operand 2
jmp _ret87 ; goto common epilogue
__FSDemu:
_shl EDX,1 ; shift sign of divisor into carry
_if e ; if divisor is zero
jmp F4DivZero ; - handle divide by zero
_endif ; endif
push ECX ; save ECX
_rcl ECX,1 ; save sign in ECX
_shl EAX,1 ; shift sign of dividend into carry
_if e ; if dividend is 0, then
pop ECX ; - restore ECX
ret ; - return
_endif ; endif
adc ECX,0 ; now calculate save sign of result in ECX
ror ECX,1 ; rotate sign to top
rol EAX,8 ; get exponent into AL
rol EDX,8 ; get exponent into DL
sub AL,7Fh ; calculate exponent of result
sub DL,7Fh ; . . .
sub AL,DL ; . . .
_if o ; if over or underflow
jns short div_uflow ; - handle underflow
_shl ECX,1 ; - get sign of infinity
rcr EAX,1 ; - . . .
jmp short div_oflow ; - handle overflow
_endif ; endif
cmp AL,81h ; check for underflow
jle short div_uflow ; . . .
add AL,7Fh ; restore bias to exponent
mov CH,AL ; save calculated exponent
mov AL,0 ; zero bottom of fraction
mov DL,0 ; ...
stc ; rotate implied '1'bit back into divisor
rcr EDX,1 ; . . .
stc ; rotate implied '1' bit into dividend
rcr EAX,1 ; . . .
push ECX ; save sign and exponent
mov ECX,EDX ; save divisor
mov EDX,EAX ; place dividend into EDX
sub EAX,EAX ; set rest to 0
shr EDX,1 ; so we don't get a divide overflow trap
div ECX ; do the divide
pop ECX ; restore sign and exponent
or EAX,EAX ; check top bit
_if ns ; if not set
_shl EAX,1 ; - move left 1
dec CH ; - decrement exponent
_endif ; endif
sar EAX,8 ; place fraction in correct location
adc EAX,0 ; round up
_guess ; guess have to inc exponent
_quif nc ; - quit if no carry
inc CH ; - increment exponent
_quif nz ; - quit if no overflow
mov EAX,ECX ; - get sign of infinity
jmp short div_oflow ; - handle overflow
_endguess ; endguess
shl EAX,9 ; get rid of implied 1 bit
mov AL,CH ; get exponent
ror EAX,8 ; rotate into position except for sign
_shl ECX,1 ; get sign
rcr EAX,1 ; place sign in result
pop ECX ; restore ECX
ret ; return to caller
div_uflow: ; handle underflow
pop ECX ; restore ECX
jmp F4UnderFlow ; handle underflow
div_oflow: ; handle overflow
pop ECX ; restore ECX
jmp F4OverFlow ; handle overflow
endproc __FSD
_chkadd: call _chk8087
jmp fsadd
_chkmul: call _chk8087
jmp fsmul
_chkdiv: call _chk8087
jmp fsdiv
_chk8087 proc near
push eax ; save AX
cmp byte ptr __real87,0 ; if real 80x87 NDP present
_if ne ; then
mov eax,offset __FSA87 ; - get addr of add rtn
mov fsadd,eax ; - ...
mov eax,offset __FSM87 ; - get addr of mul rtn
mov fsmul,eax ; - ...
test byte ptr __chipbug, 1 ; - if we've got a bad divider
_if ne ; - then
mov eax,offset __FSDbad_div ; - - get addr of div rtn
_else ; - else
mov eax,offset __FSD87 ; - - get addr of div rtn
_endif ; - endif
mov fsdiv,eax ; - ...
_else ; else
mov eax,offset __FSAemu ; - get addr of add rtn
mov fsadd,eax ; - ...
mov eax,offset __FSMemu ; - get addr of mul rtn
mov fsmul,eax ; - ...
mov eax,offset __FSDemu ; - get addr of div rtn
mov fsdiv,eax ; - ...
_endif ; endif
pop eax ; restore AX
ret ; return
endproc _chk8087
endmod
end
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?