forked from KolibriOS/kolibrios
43bd1e645f
git-svn-id: svn://kolibrios.org@554 a494cfbc-eb01-0410-851d-a64ba20cac60
266 lines
12 KiB
NASM
266 lines
12 KiB
NASM
;*****************************************************************************
|
|
;*
|
|
;* 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: WHEN YOU FIGURE OUT WHAT THIS FILE DOES, PLEASE
|
|
;* DESCRIBE IT HERE!
|
|
;*
|
|
;*****************************************************************************
|
|
|
|
|
|
include mdef.inc
|
|
include struct.inc
|
|
|
|
modstart i64tos
|
|
|
|
;
|
|
;
|
|
; int _CmpBigInt( int sigdigits, int near *bigint )
|
|
; EAX EDX
|
|
;
|
|
xdefp __CmpBigInt
|
|
xdefp __Rnd2Int
|
|
xdefp __Bin2String
|
|
|
|
defpe __CmpBigInt
|
|
push EDI ; save EDI
|
|
push ECX ; save ECX
|
|
call getpow10 ; get address of Power of 10 table
|
|
inc EAX ; ++sigdigits
|
|
lea EDI,[EDI+EAX*8] ; point to Pow10Table[sigdigits+1]
|
|
mov ECX,[EDX] ; get 64-bit integer
|
|
mov EDX,4[EDX] ; ...(high part)
|
|
sub EAX,EAX ; set adjustment to 0
|
|
_loop ; loop
|
|
cmp EDX,cs:[EDI] ; - check against 10**k
|
|
_if e ; - if high parts equal
|
|
cmp ECX,cs:4[EDI] ; - - compare low part
|
|
_endif ; - endif
|
|
_quif b ; - quit if num < 10**k
|
|
add EDI,8 ; - set pointer to 10**(k+1)
|
|
inc EAX ; - increment adjustment word
|
|
_endloop ; endloop
|
|
sub EDI,8 ; point at 10**(k-1)
|
|
_loop ; loop
|
|
cmp EDX,cs:[EDI] ; - check against 10**k
|
|
_if e ; - if high parts equal
|
|
cmp ECX,cs:4[EDI] ; - - compare low part
|
|
_endif ; - endif
|
|
_quif nb ; - quit if num >= 10**(k-1)
|
|
sub EDI,8 ; - set pointer to 10**(k-2)
|
|
dec EAX ; - increment adjustment word
|
|
_endloop ; endloop
|
|
pop ECX ; restore ECX
|
|
pop EDI ; restore EDI
|
|
ret ; return to caller
|
|
endproc __CmpBigInt
|
|
|
|
;[][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][]
|
|
;[]
|
|
;[] Rnd2int rounds the real pointed to by EAX to a 64 bit integer.
|
|
;[]
|
|
;[][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][]
|
|
; void _Rnd2Int( double near *realnum, int near *bigint )
|
|
; EAX EDX
|
|
;
|
|
defpe __Rnd2Int
|
|
push EBX ; save registers
|
|
push ECX ; save ECX
|
|
push EDX ; save EDX
|
|
push EBP ; save EBP
|
|
push ESI ; save ESI
|
|
push EDX ; save address of bigint array
|
|
mov EBP,EAX ; get address of realnum
|
|
mov ECX,[EBP] ; load the number
|
|
mov EBX,4[EBP] ; . . .
|
|
mov EBP,EBX ; save high word
|
|
and EBP,0FFF00000h ; isolate exponent in EBP
|
|
xor EBX,EBP ; isolate mantissa in EDX
|
|
xor EBX,00100000h ; turn on implied '1' bit in mantissa
|
|
shr EBP,20 ; move exponent to bottom part of word
|
|
sub EBP,0433h ; calculate difference from 2**53
|
|
_if ne ; if not already the right size
|
|
_if a ; - if too big
|
|
_loop ; - - loop
|
|
shl ECX,1 ; - - - shift real left by one
|
|
rcl EBX,1 ; - - - . . .
|
|
dec EBP ; - - - decrement count
|
|
_until e ; - - until count = 0
|
|
_else ; - else
|
|
sub EAX,EAX ; - - clear remainder
|
|
sub ESI,ESI ; - - clear remainder bit bucket
|
|
_loop ; - - loop
|
|
shr EBX,1 ; - - - shift real right by one
|
|
rcr ECX,1 ; - - - . . .
|
|
rcr EAX,1 ; - - - save remainder
|
|
adc ESI,ESI ; - - - remember if any bits fell off end
|
|
inc EBP ; - - - increment count
|
|
_until e ; - - until e
|
|
_guess rup ; - - do we have to round up?
|
|
cmp EAX,80000000h;- - - compare remainder with .5000000
|
|
_quif b,rup ; - - - kick out if less than .5
|
|
_if e ; - - - magical stuff if looks like a .5
|
|
or ESI,ESI ; - - - any bits dropped off the bottom
|
|
_if e ; - - - if not
|
|
test ECX,1 ; - - - - - is bottom digit even?
|
|
_quif e,rup ; - - - - - kick out if it is
|
|
_endif ; - - - - endif
|
|
_endif ; - - - endif
|
|
add ECX,01 ; - - - round up the number
|
|
adc EBX,00 ; - - - . . .
|
|
_endguess ; - - endguess
|
|
_endif ; - endif
|
|
_endif ; endif
|
|
pop EBP ; get address of bigint array
|
|
mov [EBP],ECX ; store 64-bit integer
|
|
mov 4[EBP],EBX ; . . .
|
|
pop ESI ; restore ESI
|
|
pop EBP ; restore EBP
|
|
pop EDX ; restore EDX
|
|
pop ECX ; restore ECX
|
|
pop EBX ; restore EBX
|
|
ret ; return
|
|
endproc __Rnd2Int
|
|
|
|
;[][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][]
|
|
;[]
|
|
;[] Bin2string converts a binary integer into a string
|
|
;[]
|
|
;[][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][]
|
|
; void _Bin2String(
|
|
; int near *bigint, /* EAX */
|
|
; char near *bufptr, /* EDX */
|
|
; int sigdigits ) /* EBX */
|
|
;
|
|
defpe __Bin2String
|
|
push EBP ; save EBP
|
|
push EDI ; save EDI
|
|
push ECX ; save ECX
|
|
push EBX ; save EBX
|
|
mov EBP,EAX ; get address of bigint array
|
|
mov ECX,[EBP] ; get 64-bit integer
|
|
mov EAX,4[EBP] ; . . .
|
|
mov EBP,EDX ; get buffer pointer
|
|
add EBP,EBX ; point to end of buffer
|
|
mov byte ptr [EBP],0; put in null character
|
|
;
|
|
; input:
|
|
; EAX:ECX - 64-bit integer
|
|
; EBP - pointer to buffer for digits
|
|
; EBX - digit count
|
|
|
|
push EAX ; save high word of quotient
|
|
_loop ; loop
|
|
pop EAX ; - restore high word of quotient
|
|
mov EDI,10000 ; - divisor is 10000
|
|
sub EDX,EDX ; - zero high word
|
|
or EAX,EAX ; - check high word
|
|
jne div1 ; - do all divides
|
|
or ECX,ECX ; - check low order word
|
|
jne div2 ; - skip first divide
|
|
push EAX ; - save high word of quotient
|
|
jmp short div5 ; - result is 0
|
|
div1: div EDI ; - divide EAX:ECX by 10000
|
|
div2: xchg ECX,EAX ; - ...
|
|
div EDI ; - ...
|
|
|
|
; quotient is in ECX:EAX
|
|
; remainder is in EDX
|
|
|
|
xchg ECX,EAX ; - move quotient to EAX:ECX
|
|
push EAX ; - save high word of quotient
|
|
mov EAX,EDX ; - get remainder
|
|
mov DL,100 ; - get divisor
|
|
div DL ; - split remainder into 2 parts
|
|
mov DL,AH ; - save low order part
|
|
mov AH,0 ; - zero
|
|
aam ; - split top part into 2 digits
|
|
xchg EDX,EAX ; - DH, DL gets top 2 digits, AX gets low part
|
|
mov AH,0 ; - zero
|
|
aam ; - split low part into 2 digits
|
|
div5: add AX,3030h ; - make ASCII digits
|
|
add DX,3030h ; - ...
|
|
sub EBP,4 ; - move back 4
|
|
mov 3[EBP],AL ; - put low order digit in buffer
|
|
dec EBX ; - decrement digit count
|
|
_quif e ; - quit if done
|
|
mov 2[EBP],AH ; - ...
|
|
dec EBX ; - decrement digit count
|
|
_quif e ; - quit if done
|
|
mov 1[EBP],DL ; - ...
|
|
dec EBX ; - decrement digit count
|
|
_quif e ; - quit if done
|
|
mov [EBP],DH ; - put high order digit in buffer
|
|
dec EBX ; - decrement digit count
|
|
_until e ; until done
|
|
|
|
pop EAX ; remove high word of quotient
|
|
pop EBX ; restore EBX
|
|
pop ECX ; restore ECX
|
|
pop EDI ; restore EDI
|
|
pop EBP ; restore EBP
|
|
ret ; return
|
|
endproc __Bin2String
|
|
|
|
;<><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><>
|
|
;<> <>
|
|
;<> 64-bit integer powers of 10 table <>
|
|
;<> <>
|
|
;<><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><>
|
|
getpow10 proc near ; get address of powers of 10 table
|
|
call pow10end ; call around the table
|
|
pow10table: ; powers of 10 table
|
|
dd 000000000h,000000000h ; 0
|
|
dd 000000000h,000000001h ; 10**00
|
|
dd 000000000h,00000000ah ; 10**01
|
|
dd 000000000h,000000064h ; 10**02
|
|
dd 000000000h,0000003e8h ; 10**03
|
|
dd 000000000h,000002710h ; 10**04
|
|
dd 000000000h,0000186a0h ; 10**05
|
|
dd 000000000h,0000f4240h ; 10**06
|
|
dd 000000000h,000989680h ; 10**07
|
|
dd 000000000h,005f5e100h ; 10**08
|
|
dd 000000000h,03b9aca00h ; 10**09
|
|
dd 000000002h,0540be400h ; 10**10
|
|
dd 000000017h,04876e800h ; 10**11
|
|
dd 0000000e8h,0d4a51000h ; 10**12
|
|
dd 000000918h,04e72a000h ; 10**13
|
|
dd 000005af3h,0107a4000h ; 10**14
|
|
dd 000038d7eh,0a4c68000h ; 10**15
|
|
dd 0002386f2h,06fc10000h ; 10**16
|
|
dd 001634578h,05d8a0000h ; 10**17
|
|
dd 00de0b6b3h,0a7640000h ; 10**18
|
|
dd 08ac72304h,089e80000h ; 10**19
|
|
dd 0ffffffffh,0ffffffffh ; MAX
|
|
|
|
pow10end proc near
|
|
pop EDI ; get address of table
|
|
ret ; return
|
|
endproc pow10end
|
|
endproc getpow10
|
|
|
|
endmod
|
|
end
|