ldi4386.asm
来自「开放源码的编译器open watcom 1.6.0版的源代码」· 汇编 代码 · 共 192 行
ASM
192 行
;*****************************************************************************
;*
;* 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: convert long double into integer
;*
;*****************************************************************************
ifdef _BUILDING_MATHLIB
include mdef.inc
include struct.inc
include xception.inc
modstart ldi4386, dword
endif
xdefp __LDI4
xdefp __LDU4
xdefp __RLDU4
;[][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][]
;[]
;[] __LDU4 convert long double [EAX] into 32-bit integer EAX
;[] Input: EAX - pointer to long double
;[] Output: EAX - 32-bit integer
;[]
;[][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][]
; convert floating double to 4-byte integer with rounding
defp __RLDU4
push EBX ; save EBX
mov BL,80h+20h ; indicate we are rounding
jmp short DtoI ; do it
defp __RLDI4
push EBX ; save EBX
mov BH,9[EAX] ; get sign
; high bit of BH is sign bit
push ECX ; save ECX
mov CX,8[EAX] ; get exponent
and CX,7FFFh ; isolate exponent
_guess ; guess: 0
_quif ne ; - quit if not 0
sub EAX,EAX ; - set result to 0
_admit ; guess: |x| < 1.0
sub CX,3FFEh ; - remove bias from exponent
_quif g ; - quit if >= 1.0
_shl BH,1 ; - get sign bit
sbb EAX,EAX ; - answer is 0 or -1
_admit ; guess: number too large
cmp CX,1Fh ; - if exponent > 31
_quif le ; - quit it not too large
mov EAX,80000000h ; - set largest integer
_admit ; admit: can fit in integer
mov CH,BH ; - save rounding/truncation bit
mov EBX,[EAX] ; - get least significant part of mantissa
mov EAX,4[EAX] ; - get most significant part of mantissa
push EDX ; - save EDX
sub EDX,EDX ; - zero result register
shld EDX,EAX,CL ; - shift answer into EDX
shl EAX,CL ; - shift rounding bit into position
or EBX,EAX ; - EBX is fraction bits
mov EAX,EDX ; - get result
pop EDX ; - restore EDX
_shl CH,1 ; - if number is negative
_if c ; - then
or EBX,EBX ; - - if fraction is non zero
_if ne ; - - then
inc EAX ; - - - increment number
_endif ; - - endif
neg EAX ; - - negate the integer
_endif ; - endif
_endguess ; endguess
pop ECX ; restore ECX
pop EBX ; restore EBX
ret ; return
defp __LDI4
push EBX ; save EBX
mov BL,1Fh ; indicate we are truncating
jmp short DtoI ; do it
; convert floating double to 4-byte integer with truncation
defp __LDU4
push EBX ; save EBX
mov BL,20h ; indicate we are truncating
DtoI: mov BH,9[EAX] ; get sign
shr BH,1 ; shift sign bit over 1
or BH,BL ; get rounding bit
; high bit of BH is rounding bit
; next bit is the sign bit
push ECX ; save ECX
mov CX,8[EAX] ; get exponent
and CX,7FFFh ; isolate exponent
sub CX,3FFEh ; remove bias from exponent
jl short DIzero ; if |real| < .5 goto DIzero
cmp CX,20h ; if exponent > 32
jg short DIo_f ; goto DIo_flow
and BL,3Fh ; isolate # of significant bits
cmp CL,BL ; quit if number too big
jg short DIo_f ; goto DIo_flow
mov CH,BH ; save rounding/truncation bit
mov EBX,[EAX] ; get least significant part of mantissa
mov EAX,4[EAX] ; get most significant part of mantissa
_shl EBX,1 ; get rounding bit
rcr CH,1 ; save rounding bit
cmp CL,32 ; if want 32 bits
_if e ; then
_shl CH,1 ; - get rounding bit
_else ; else
sub EBX,EBX ; - zero result register
shld EBX,EAX,CL ; - shift answer into EAX
shl EAX,CL ; - shift rounding bit into position
_shl CH,1 ; - get rid of rounding bit from CH
_shl EAX,1 ; - get proper rounding bit
mov EAX,EBX ; - get result
_endif ; endif
mov CL,0FFh ; get mask
rcr CL,1 ; get rounding bit
and CH,CL ; mask it with rounding control bit
_shl CH,1 ; get rounding bit
adc EAX,0 ; add it to the integer to round it up
_shl CH,1 ; get sign
_if c ; if negative
neg EAX ; - negate integer
_endif ; endif
pop ECX ; restore ECX
pop EBX ; restore EBX
ret ; return
DIo_f:
mov EAX,80000000h ; set answer to largest negative number
pop ECX ; restore ECX
pop EBX ; restore EBX
ret ; return
; jmp I4OverFlow ; report overflow
DIzero: sub EAX,EAX ; set result to zero
pop ECX ; restore ECX
pop EBX ; restore EBX
ret
endproc __LDU4
endproc __LDI4
endproc __RLDI4
endproc __RLDU4
ifdef _BUILDING_MATHLIB
endmod
endf equ end
else
endf equ <>
endif
endf
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?