i64ts286.asm

来自「开放源码的编译器open watcom 1.6.0版的源代码」· 汇编 代码 · 共 327 行

ASM
327
字号
;*****************************************************************************
;*
;*                            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 )
;                               AX              DX
;
        xdefp   __CmpBigInt
        xdefp   __Rnd2Int
        xdefp   __Bin2String

        defpe   __CmpBigInt
        push    BP              ; save BP
        push    SI              ; save SI
        push    DI              ; save DI
        push    CX              ; save CX
        push    BX              ; save BX
        call    getpow10        ; get address of Power of 10 table
        inc     AX              ; ++sigdigits
        shl     AX,1            ; sigdigits times 8
        shl     AX,1            ; . . .
        shl     AX,1            ; . . .
        add     DI,AX           ; point to Pow10Table[sigdigits+1]
        mov     BP,DX           ; get address of 64-bit integer
        mov     DX,[BP]         ; get 64-bit integer
        mov     CX,2[BP]        ; . . .
        mov     BX,4[BP]        ; . . .
        mov     AX,6[BP]        ; . . .
        sub     BP,BP           ; set adjustment to 0
        _loop                   ; loop
          call  DoCmpBigInt     ; - check against 10**k
          _quif b               ; - quit if num < 10**k
          add   DI,8            ; - set pointer to 10**(k+1)
          inc   BP              ; - increment adjustment word
        _endloop                ; endloop
        sub     DI,8            ; point at 10**(k-1)
        _loop                   ; loop
          call  DoCmpBigInt     ; - check against 10**(k-1)
          _quif nb              ; - quit if num >= 10**(k-1)
          sub   DI,8            ; - set pointer to 10**(k-2)
          dec   BP              ; - increment adjustment word
        _endloop                ; endloop
        mov     AX,BP           ; place adjustment in AX
        pop     BX              ; restore BX
        pop     CX              ; restore CX
        pop     DI              ; restore DI
        pop     SI              ; restore SI
        pop     BP              ; restore BP
        ret                     ; return to caller
        endproc __CmpBigInt

;[][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][]
;[]
;[] DoCmpbigint compares AL BX CX DX with the integer in the code segment
;[] pointed to by SI
;[]
;[][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][]

DoCmpbigint proc near
        _guess
          cmp   AX,cs:[DI]      ; compare high words
          _quif ne              ;
          cmp   BX,cs:2[DI]     ; compare next words
          _quif ne              ;
          cmp   CX,cs:4[DI]     ; compare next words
          _quif ne              ;
          cmp   DX,cs:6[DI]     ; compare low words
        _endguess               ;
        ret
        endproc DoCmpbigint

;[][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][]
;[]
;[] Rnd2int rounds the real pointed to by AX to a 64 bit integer.
;[] register use: AX BX CX DX
;[]
;[][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][]
;       void _Rnd2Int( double near *realnum, int near *bigint )
;                               AX                 DX
;
        defpe   __Rnd2int
        push    DX              ; save registers
        push    CX              ; . . .
        push    BX              ; . . .
        push    BP              ; save BP
        push    SI              ; save SI
        push    DI              ; save DI
        push    DX              ; save address of array
        mov     BP,AX           ; get address of realnum
        mov     DI,[BP]         ; load the number
        mov     CX,2[BP]        ; . . .
        mov     BX,4[BP]        ; . . .
        mov     SI,6[BP]        ; . . .
        mov     DX,SI           ; save SI
        and     DX,0FFF0h       ; isolate exponent in DX
        xor     SI,DX           ; isolate mantissa in SI
        xor     SI,0010h        ; turn on implied '1' bit in SI
        shr     DX,1            ; move exponent to bottom part of word
        shr     DX,1            ; . . .
        shr     DX,1            ; . . .
        shr     DX,1            ; . . .
        sub     DX,0433h        ; calculate difference from 2**53
        _if     ne              ; if not already the right size
          _if   a               ; - if too big
            _loop               ; - - loop
              shl DI,1          ; - - - shift real left by one
              rcl CX,1          ; - - - . . .
              rcl BX,1          ; - - - . . .
              rcl SI,1          ; - - - . . .
              dec DX            ; - - - decrement count
            _until e            ; - - until count = 0
          _else                 ; - else
            sub AX,AX           ; - - zero remainder
            sub BP,BP           ; - - zero remainder bit bucket
            _loop               ; - - loop
              shr       SI,1    ; - - - shift real right by one
              rcr       BX,1    ; - - - . . .
              rcr       CX,1    ; - - - . . .
              rcr       DI,1    ; - - - . . .
              rcr       AX,1    ; - - - save remainder
              adc       BP,0    ; - - - remember if any bits fell off end
              inc       DX      ; - - - increment count
            _until e            ; - - until e
            _guess      rup     ; - - have to round up number?
              cmp       AX,8000h; - - - compare remainder to .500000
              _quif     b,rup   ; - - - kick out if less than .5
              _if       e       ; - - - magicial stuff if looks like a .5
                 or     BP,BP   ; - - - any bits dropped off bottom?
                _if     e       ; - - - - if not
                  test  DI,1    ; - - - - - is bottom digit even?
                  _quif e,rup   ; - - - - - kick out if it is
                _endif          ; - - - - endif
              _endif            ; - - - endif
              add       DI,01   ; - - - round up the number
              adc       CX,00   ; - - - . . .
              adc       BX,00   ; - - - . . .
              adc       SI,00   ; - - - . . .
            _endguess           ; - - endguess
          _endif                ; - endif
        _endif                  ; endif
        pop     BP              ; get address of integer array
        mov     [BP],DI         ; store 64-bit integer
        mov     2[BP],CX        ; . . .
        mov     4[BP],BX        ; . . .
        mov     6[BP],SI        ; . . .
        pop     DI              ; restore DI
        pop     SI              ; restore SI
        pop     BP              ; restore BP
        pop     BX              ; restore BX
        pop     CX              ; restore CX
        pop     DX              ; restore DX
        ret                     ; return
        endproc __Rnd2Int

;[][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][]
;[]
;[] Bin2string  converts a binary integer into a string
;[]
;[][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][]
;       void _Bin2String(
;               int near *bigint,       /* AX */
;               char near *bufptr,      /* DX */
;               int sigdigits )         /* BX */
;
        defpe   __Bin2string
        push    BP              ; save registers
        push    DI              ; ...
        push    SI              ; ...
        push    CX              ; ...
        push    BX              ; ...
        mov     DI,BX           ; get # of digits
        mov     BP,AX           ; get pointer to 64-bit integer
        mov     AX,6[BP]        ; get the integer
        mov     BX,4[BP]        ; ...
        mov     CX,2[BP]        ; ...
        mov     SI,[BP]         ; ...
        mov     BP,DX           ; get pointer to output buffer
        add     BP,DI           ; point to end of buffer
        mov     byte ptr [BP],0 ; put in null character
;
; input:
;       AX:BX:CX:SI - 64-bit integer
;       BP - pointer to buffer for digits
;       DI - digit count

        push    AX              ; save high word of quotient
        _loop                   ; loop
          pop   AX              ; - restore high word of quotient
          push  DI              ; - save # of digits left to go
          mov   DI,10000        ; - divisor is 10000
          sub   DX,DX           ; - zero high word
          or    AX,AX           ; - check high word
          jne   div1            ; - do all divides
          or    BX,BX           ; - check next word
          jne   div2            ; - skip first divide
          or    CX,CX           ; - check third word
          jne   div3            ; - skip first 2 divides
          or    SI,SI           ; - check low order word
          jne   div4            ; - go do last divide
          pop   DI              ; - restore # of digits
          push  AX              ; - save high word of quotient
          jmp   short div5      ; - result is 0
div1:     div   DI              ; - divide AX:BX:CX:SI by 10000
div2:     xchg  BX,AX           ; - ...
          div   DI              ; - ...
div3:     xchg  CX,AX           ; - ...
          div   DI              ; - ...
div4:     xchg  SI,AX           ; - ...
          div   DI              ; - ...

;   quotient is in BX:CX:SI:AX
;   remainder is in DX

          xchg  SI,AX           ; - move quotient to AX:BX:CX:SI
          xchg  CX,AX           ; - ...
          xchg  BX,AX           ; - ...
          pop   DI              ; - restore # of digits
          push  AX              ; - save high word of quotient
          mov   AX,DX           ; - 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  DX,AX           ; - 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   BP,4            ; - move back 4
          mov   3[BP],AL        ; - put low order digit in buffer
          dec   DI              ; - decrement digit count
          _quif e               ; - quit if done
          mov   2[BP],AH        ; - ...
          dec   DI              ; - decrement digit count
          _quif e               ; - quit if done
          mov   1[BP],DL        ; - ...
          dec   DI              ; - decrement digit count
          _quif e               ; - quit if done
          mov   [BP],DH         ; - put high order digit in buffer
          dec   DI              ; - decrement digit count
        _until  e               ; until done

        pop     AX              ; restore high word of quotient
        pop     BX              ; restore registers
        pop     CX              ; ...
        pop     SI              ; ...
        pop     DI              ; ...
        pop     BP              ; ...
        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
        dw      00000h,00000h,00000h,00000h ; 0
        dw      00000h,00000h,00000h,00001h ; 10**00
        dw      00000h,00000h,00000h,0000ah ; 10**01
        dw      00000h,00000h,00000h,00064h ; 10**02
        dw      00000h,00000h,00000h,003e8h ; 10**03
        dw      00000h,00000h,00000h,02710h ; 10**04
        dw      00000h,00000h,00001h,086a0h ; 10**05
        dw      00000h,00000h,0000fh,04240h ; 10**06
        dw      00000h,00000h,00098h,09680h ; 10**07
        dw      00000h,00000h,005f5h,0e100h ; 10**08
        dw      00000h,00000h,03b9ah,0ca00h ; 10**09
        dw      00000h,00002h,0540bh,0e400h ; 10**10
        dw      00000h,00017h,04876h,0e800h ; 10**11
        dw      00000h,000e8h,0d4a5h,01000h ; 10**12
        dw      00000h,00918h,04e72h,0a000h ; 10**13
        dw      00000h,05af3h,0107ah,04000h ; 10**14
        dw      00003h,08d7eh,0a4c6h,08000h ; 10**15
        dw      00023h,086f2h,06fc1h,00000h ; 10**16
        dw      00163h,04578h,05d8ah,00000h ; 10**17
        dw      00de0h,0b6b3h,0a764h,00000h ; 10**18
        dw      08ac7h,02304h,089e8h,00000h ; 10**19
        dw      0ffffh,0ffffh,0ffffh,0ffffh ; MAX

pow10end proc   near
        pop     DI              ; get address of table
        ret                     ; return
        endproc pow10end
        endproc getpow10

        endmod
        end

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?