Annotation of mstools/samples/largeint/i386/largeint.asm, revision 1.1

1.1     ! root        1:         TITLE   "Large Integer Arithmetic"
        !             2: ;++
        !             3: ;
        !             4: ; Module Name:
        !             5: ;
        !             6: ;    largeint.s
        !             7: ;
        !             8: ; Abstract:
        !             9: ;
        !            10: ;    This module implements routines for performing extended integer
        !            11: ;    arithmtic.
        !            12: ;
        !            13: ; Environment:
        !            14: ;
        !            15: ;    Any mode.
        !            16: ;
        !            17: ; Revision History:
        !            18: ;
        !            19: ;--
        !            20: 
        !            21: .386p
        !            22:         .xlist
        !            23: include callconv.inc            ; calling convention macros
        !            24:         .list
        !            25: 
        !            26: 
        !            27: _TEXT   SEGMENT DWORD USE32 PUBLIC 'CODE'
        !            28:         ASSUME  CS:FLAT, DS:FLAT, ES:FLAT, SS:NOTHING, FS:NOTHING, GS:NOTHING
        !            29: 
        !            30:         page ,132
        !            31:         subttl  "LargeIntegerAdd"
        !            32: ;++
        !            33: ;
        !            34: ; LARGE_INTEGER
        !            35: ; LargeIntegerAdd (
        !            36: ;    IN LARGE_INTEGER Addend1,
        !            37: ;    IN LARGE_INTEGER Addend2
        !            38: ;    )
        !            39: ;
        !            40: ; Routine Description:
        !            41: ;
        !            42: ;    This function adds a signed large integer to a signed large integer and
        !            43: ;    returns the signed large integer result.
        !            44: ;
        !            45: ; Arguments:
        !            46: ;
        !            47: ;    (TOS+4) = Addend1 - first addend value
        !            48: ;    (TOS+12) = Addend2 - second addend value
        !            49: ;
        !            50: ; Return Value:
        !            51: ;
        !            52: ;    The large integer result is stored in (edx:eax)
        !            53: ;
        !            54: ;--
        !            55: 
        !            56: cPublicProc _LargeIntegerAdd ,4
        !            57: cPublicFpo 4,0
        !            58: 
        !            59:         mov     eax,[esp]+4             ; (eax)=add1.low
        !            60:         add     eax,[esp]+12            ; (eax)=sum.low
        !            61:         mov     edx,[esp]+8             ; (edx)=add1.hi
        !            62:         adc     edx,[esp]+16            ; (edx)=sum.hi
        !            63:         stdRET    _LargeIntegerAdd
        !            64: 
        !            65: stdENDP _LargeIntegerAdd
        !            66: 
        !            67: 
        !            68:         page
        !            69:         subttl  "Enlarged Integer Multiply"
        !            70: ;++
        !            71: ;
        !            72: ; LARGE_INTEGER
        !            73: ; EnlargedIntegerMultiply (
        !            74: ;    IN LONG Multiplicand,
        !            75: ;    IN LONG Multiplier
        !            76: ;    )
        !            77: ;
        !            78: ; Routine Description:
        !            79: ;
        !            80: ;    This function multiplies a signed integer by an signed integer and
        !            81: ;    returns a signed large integer result.
        !            82: ;
        !            83: ; Arguments:
        !            84: ;
        !            85: ;    (TOS+4) = Factor1
        !            86: ;    (TOS+8) = Factor2
        !            87: ;
        !            88: ; Return Value:
        !            89: ;
        !            90: ;    The large integer result is stored in (edx:eax)
        !            91: ;
        !            92: ;--
        !            93: 
        !            94: cPublicProc _EnlargedIntegerMultiply ,2
        !            95: cPublicFpo 2,0
        !            96: 
        !            97:         mov     eax,[esp]+4             ; (eax) = factor1
        !            98:         imul    dword ptr [esp]+8       ; (edx:eax) = signed result
        !            99:         stdRET    _EnlargedIntegerMultiply
        !           100: 
        !           101: stdENDP _EnlargedIntegerMultiply
        !           102: 
        !           103: 
        !           104:         page
        !           105:         subttl  "Enlarged Unsigned Integer Multiply"
        !           106: ;++
        !           107: ;
        !           108: ; LARGE_INTEGER
        !           109: ; EnlargedUnsignedMultiply (
        !           110: ;    IN ULONG Multiplicand,
        !           111: ;    IN ULONG Multiplier
        !           112: ;    )
        !           113: ;
        !           114: ; Routine Description:
        !           115: ;
        !           116: ;    This function multiplies an un signed integer by an unsigned integer and
        !           117: ;    returns a signed large integer result.
        !           118: ;
        !           119: ; Arguments:
        !           120: ;
        !           121: ;    (TOS+4) = Factor1
        !           122: ;    (TOS+8) = Factor2
        !           123: ;
        !           124: ; Return Value:
        !           125: ;
        !           126: ;    The large integer result is stored in (edx:eax)
        !           127: ;
        !           128: ;--
        !           129: 
        !           130: cPublicProc _EnlargedUnsignedMultiply ,2
        !           131: cPublicFpo 2,0
        !           132: 
        !           133:         mov     eax,[esp]+4             ; (eax) = factor1
        !           134:         mul     dword ptr [esp]+8       ; (edx:eax) = unsigned result
        !           135:         stdRET    _EnlargedUnsignedMultiply
        !           136: 
        !           137: stdENDP _EnlargedUnsignedMultiply
        !           138: 
        !           139:         page
        !           140:         subttl  "Enlarged Unsigned Integer Divide"
        !           141: 
        !           142: ;++
        !           143: ;
        !           144: ; ULONG
        !           145: ; EnlargedUnsignedDivide (
        !           146: ;    IN ULARGE_INTEGER Dividend,
        !           147: ;    IN ULONG Divisor,
        !           148: ;    IN PULONG Remainder
        !           149: ;    )
        !           150: ;
        !           151: ;
        !           152: ; Routine Description:
        !           153: ;
        !           154: ;    This function divides an unsigned large integer by an unsigned long
        !           155: ;    and returns the resultant quotient and optionally the remainder.
        !           156: ;
        !           157: ;    N.B. It is assumed that no overflow will occur.
        !           158: ;
        !           159: ; Arguments:
        !           160: ;
        !           161: ;    Dividend - Supplies the dividend value.
        !           162: ;
        !           163: ;    Divisor - Supplies the divisor value.
        !           164: ;
        !           165: ;    Remainder - Supplies an optional pointer to a variable that
        !           166: ;        receives the remainder.
        !           167: ;
        !           168: ; Return Value:
        !           169: ;
        !           170: ;    The unsigned long integer quotient is returned as the function value.
        !           171: ;
        !           172: ;--
        !           173: 
        !           174: cPublicProc _EnlargedUnsignedDivide,4
        !           175: cPublicFpo 4,0
        !           176: 
        !           177:         mov     eax, [esp+4]            ; (eax) = Dividend.LowPart
        !           178:         mov     edx, [esp+8]            ; (edx) = Dividend.HighPart
        !           179:         mov     ecx, [esp+16]           ; (ecx) = pRemainder
        !           180:         div     dword ptr [esp+12]      ; divide by Divisor
        !           181: 
        !           182:         or      ecx, ecx                ; return remainder?
        !           183:         jnz     short @f
        !           184: 
        !           185:         stdRET    _EnlargedUnsignedDivide    ; (eax) = Quotient
        !           186: 
        !           187: align 4
        !           188: @@:     mov     [ecx], edx              ; save remainder
        !           189:         stdRET    _EnlargedUnsignedDivide    ; (eax) = Quotient
        !           190: 
        !           191: stdENDP _EnlargedUnsignedDivide
        !           192: 
        !           193:         page
        !           194:         subttl  "Extended Large Integer Divide"
        !           195: 
        !           196: ;++
        !           197: ;
        !           198: ; LARGE_INTEGER
        !           199: ; ExtendedLargeIntegerDivide (
        !           200: ;     IN LARGE_INTEGER Dividend,
        !           201: ;     IN ULONG Divisor,
        !           202: ;     OUT PULONG Remainder OPTIONAL
        !           203: ;     )
        !           204: ;
        !           205: ; Routine Description:
        !           206: ;
        !           207: ;     This routine divides an unsigned 64 bit dividend by a 32 bit divisor
        !           208: ;     and returns a 64-bit quotient, and optionally the 32-bit remainder.
        !           209: ;
        !           210: ;
        !           211: ; Arguments:
        !           212: ;
        !           213: ;     Dividend - Supplies the 64 bit dividend for the divide operation.
        !           214: ;
        !           215: ;     Divisor - Supplies the 32 bit divisor for the divide operation.
        !           216: ;
        !           217: ;     Remainder - Supplies an optional pointer to a variable which receives
        !           218: ;         the remainder
        !           219: ;
        !           220: ; Return Value:
        !           221: ;
        !           222: ;     The 64-bit quotient is returned as the function value.
        !           223: ;
        !           224: ;--
        !           225: 
        !           226: cPublicProc _ExtendedLargeIntegerDivide, 4
        !           227: cPublicFpo 4,3
        !           228: 
        !           229:         push    esi
        !           230:         push    edi
        !           231:         push    ebx
        !           232: 
        !           233:         mov     eax, [esp+16]       ; (eax) = Dividend.LowPart
        !           234:         mov     edx, [esp+20]       ; (edx) = Dividend.HighPart
        !           235: 
        !           236: lid00:  mov     ebx, [esp+24]       ; (ebx) = Divisor
        !           237:         or      ebx, ebx
        !           238:         jz      short lid_zero      ; Attempted a divide by zero
        !           239: 
        !           240:         push    ebp
        !           241: 
        !           242:         mov     ecx, 64             ; Loop count
        !           243:         xor     esi, esi            ; Clear partial remainder
        !           244: 
        !           245: ; (edx:eax) = Dividend
        !           246: ; (ebx) = Divisor
        !           247: ; (ecx) = Loop count
        !           248: ; (esi) = partial remainder
        !           249: 
        !           250: align 4
        !           251: lid10:  shl     eax, 1              ; (LowPart << 1)  | 0
        !           252:         rcl     edx, 1              ; (HighPart << 1) | CF
        !           253:         rcl     esi, 1              ; (Partial << 1)  | CF
        !           254: 
        !           255:         sbb     edi, edi            ; clone CF into edi (0 or -1)
        !           256: 
        !           257:         cmp     esi, ebx            ; check if partial remainder less then divisor
        !           258:         cmc
        !           259:         sbb     ebp, ebp            ; clone CF intp ebp
        !           260:         or      edi, ebp            ; merge with remainder of high bit
        !           261: 
        !           262:         sub     eax, edi            ; merge quotient bit
        !           263:         and     edi, ebx            ; Select divisor or 0
        !           264:         sub     esi, edi
        !           265: 
        !           266:         dec     ecx                 ; dec interration count
        !           267:         jnz     short lid10         ; go around again
        !           268: 
        !           269:         pop     ebp
        !           270:         pop     ebx
        !           271:         pop     edi
        !           272: 
        !           273:         mov     ecx, [esp+20]       ; (ecx) = Remainder
        !           274:         or      ecx, ecx
        !           275:         jnz     short lid20
        !           276: 
        !           277:         pop     esi
        !           278:         stdRET  _ExtendedLargeIntegerDivide
        !           279: 
        !           280: align 4
        !           281: lid20:
        !           282:         mov     [ecx], esi          ; store remainder
        !           283:         pop     esi
        !           284:         stdRET  _ExtendedLargeIntegerDivide
        !           285: 
        !           286: lid_zero:
        !           287:         div     dword ptr [esp+24]  ; cause divide by zero exception
        !           288:         pop     ebx
        !           289:         pop     edi
        !           290:         pop     esi
        !           291:         stdRET  _ExtendedLargeIntegerDivide
        !           292: stdENDP     _ExtendedLargeIntegerDivide
        !           293: 
        !           294:         page
        !           295:         subttl  "Extended Magic Divide"
        !           296: ;++
        !           297: ;
        !           298: ; LARGE_INTEGER
        !           299: ; ExtendedMagicDivide (
        !           300: ;    IN LARGE_INTEGER Dividend,
        !           301: ;    IN LARGE_INTEGER MagicDivisor,
        !           302: ;    IN CCHAR ShiftCount
        !           303: ;    )
        !           304: ;
        !           305: ; Routine Description:
        !           306: ;
        !           307: ;    This function divides a signed large integer by an unsigned large integer
        !           308: ;    and returns the signed large integer result. The division is performed
        !           309: ;    using reciprocal multiplication of a signed large integer value by an
        !           310: ;    unsigned large integer fraction which represents the most significant
        !           311: ;    64-bits of the reciprocal divisor rounded up in its least significant bit
        !           312: ;    and normalized with respect to bit 63. A shift count is also provided
        !           313: ;    which is used to truncate the fractional bits from the result value.
        !           314: ;
        !           315: ; Arguments:
        !           316: ;
        !           317: ;   (ebp+8) = Dividend
        !           318: ;   (ebp+16) = MagicDivisor value is a 64-bit multiplicative reciprocal
        !           319: ;   (ebp+24) = ShiftCount - Right shift adjustment value.
        !           320: ;
        !           321: ; Return Value:
        !           322: ;
        !           323: ;    The large integer result is stored  in (edx:eax)
        !           324: ;
        !           325: ;--
        !           326: 
        !           327: RemdDiv     equ [ebp+8]             ; Dividend
        !           328: RemdRec     equ [ebp+16]            ; Reciprocal (magic divisor)
        !           329: RemdShift   equ [ebp+24]
        !           330: RemdTmp1    equ [ebp-4]
        !           331: RemdTmp2    equ [ebp-8]
        !           332: RemdTmp3    equ [ebp-12]
        !           333: 
        !           334: cPublicProc _ExtendedMagicDivide ,5
        !           335: 
        !           336:         push    ebp
        !           337:         mov     ebp,esp
        !           338:         sub     esp,12
        !           339:         push    esi
        !           340: 
        !           341:         mov     esi, RemdDiv+4
        !           342:         test    esi,80000000h
        !           343:         jz      remd10                  ; no sign, no need to negate
        !           344: 
        !           345:         neg     dword ptr RemdDiv+4
        !           346:         neg     dword ptr RemdDiv
        !           347:         sbb     dword ptr RemdDiv+4,0   ; negate
        !           348: 
        !           349: remd10: mov     eax,RemdRec
        !           350:         mul     dword ptr RemdDiv       ; (edx:eax) = Div.lo * Rec.lo
        !           351:         mov     RemdTmp1,edx
        !           352: 
        !           353:         mov     eax,RemdRec
        !           354:         mul     dword ptr RemdDiv+4     ; (edx:eax) = Div.hi * Rec.lo
        !           355:         mov     RemdTmp2,eax
        !           356:         mov     RemdTmp3,edx
        !           357: 
        !           358:         mov     eax,RemdRec+4
        !           359:         mul     dword ptr RemdDiv       ; (edx:eax) = Div.lo * Rec.hi
        !           360: 
        !           361: ;
        !           362: ;   Col 0 doesn't matter
        !           363: ;   Col 1 = Hi(Div.lo * Rec.lo) + Low(Div.Hi * Rec.lo) + Low(Div.lo * Rec.hi)
        !           364: ;         = RemdTmp1 + RemdTmp2 + eax
        !           365: ;         -> Only want carry from Col 1
        !           366: ;
        !           367: 
        !           368:         xor     ecx,ecx                 ; (ecx) = 0
        !           369:         add     eax,RemdTmp1
        !           370:         adc     ecx, 0                  ; save carry in ecx
        !           371:         add     eax,RemdTmp2
        !           372:         adc     ecx, 0                  ; Save Carry, all we want from Col2
        !           373: 
        !           374:         mov     RemdTmp1,edx
        !           375: 
        !           376:         mov     eax,RemdRec+4
        !           377:         mul     dword ptr RemdDiv+4     ; (edx:eax) = Div.Hi * Rec.Hi
        !           378: 
        !           379: ;
        !           380: ;   TOS = carry flag from Col 1
        !           381: ;
        !           382: ;   Col 2 = Col1 CF +
        !           383: ;           Hi(Div.Hi * Rec.Lo) + Hi(Div.Lo * Rec.Hi) + Low(Div.Hi * Rec.Hi)
        !           384: ;         = CF + RemdTmp3 + RemdTmp1 + eax
        !           385: ;
        !           386: ;   Col 3 = Col2 CF + Hi(Div.Hi * Rec.Hi)
        !           387: ;         = CF + edx
        !           388: ;
        !           389: 
        !           390:         add     eax,RemdTmp1
        !           391:         adc     edx, 0                  ; add carry to edx
        !           392:         add     eax,RemdTmp3            ; (eax) = col 2
        !           393:         adc     edx, 0                  ; add carry to edx
        !           394:         add     eax, ecx
        !           395:         adc     edx, 0                  ; (edx) = col 3
        !           396: 
        !           397: ;
        !           398: ;   (edx:eax) = the high 64 bits of the multiply, shift it right by
        !           399: ;               shift count to discard bits to right of virtual decimal pt.
        !           400: ;
        !           401: ;   RemdShift could be as large as 63 and still not 0 the result, 386
        !           402: ;   will only shift 31 bits at a time, so must do the sift multiple
        !           403: ;   times to get correct effect.
        !           404: ;
        !           405: 
        !           406:         mov     cl,RemdShift
        !           407: remd20: cmp     cl,31
        !           408:         jbe     remd30
        !           409:         sub     cl,31
        !           410:         shrd    eax,edx,31
        !           411:         shr     edx,31
        !           412:         jmp     remd20
        !           413: 
        !           414: remd30: shrd    eax,edx,cl
        !           415:         shr     edx,cl
        !           416: 
        !           417: ;
        !           418: ;   Negate the result if need be
        !           419: ;
        !           420: 
        !           421:         test    esi,80000000h
        !           422:         jz      remd40                  ; no sign, go return without negate
        !           423: 
        !           424:         neg     edx
        !           425:         neg     eax
        !           426:         sbb     edx,0
        !           427: 
        !           428: ;
        !           429: ;   Store the result
        !           430: ;
        !           431: 
        !           432: remd40:
        !           433:         ; results in (edx:eax)
        !           434: 
        !           435:         pop     esi
        !           436:         mov     esp,ebp
        !           437:         pop     ebp
        !           438:         stdRET    _ExtendedMagicDivide
        !           439: 
        !           440: stdENDP _ExtendedMagicDivide
        !           441: 
        !           442: 
        !           443:         page
        !           444:         subttl  "Extended Integer Multiply"
        !           445: ;++
        !           446: ;
        !           447: ; LARGE_INTEGER
        !           448: ; ExtendedIntegerMultiply (
        !           449: ;    IN LARGE_INTEGER Multiplicand,
        !           450: ;    IN ULONG Multiplier
        !           451: ;    )
        !           452: ;
        !           453: ; Routine Description:
        !           454: ;
        !           455: ;    This function multiplies a signed large integer by a signed integer and
        !           456: ;    returns the signed large integer result.
        !           457: ;
        !           458: ; Arguments:
        !           459: ;
        !           460: ;   (ebp+8,12)=multiplican (MCAN)
        !           461: ;   (ebp+16)=multiplier (MPER)
        !           462: ;
        !           463: ; Return Value:
        !           464: ;
        !           465: ;    The large integer result is stored in (edx:eax)
        !           466: ;
        !           467: ;--
        !           468: 
        !           469: ReimMCAN    equ [ebp+8]
        !           470: ReimMPER    equ [ebp+16]
        !           471: 
        !           472: cPublicProc _ExtendedIntegerMultiply ,3
        !           473: 
        !           474:         push    ebp
        !           475:         mov     ebp,esp
        !           476:         push    esi
        !           477: 
        !           478:         mov     esi,ReimMPER
        !           479:         xor     esi,ReimMCAN+4              ; (esi) = result sign
        !           480: 
        !           481:         test    ReimMCAN+4,80000000h
        !           482:         jz      short reim10                ; MCAN pos, go look at MPER
        !           483: 
        !           484:         neg     dword ptr ReimMCAN+4
        !           485:         neg     dword ptr ReimMCAN
        !           486:         sbb     dword ptr ReimMCAN+4,0      ; negate multiplican
        !           487: 
        !           488: reim10: test    ReimMPER,80000000h
        !           489:         jz      short reim20                ; MPER pos, go do multiply
        !           490: 
        !           491:         neg     dword ptr ReimMPER          ; negate multiplier
        !           492: 
        !           493: reim20: mov     eax,ReimMPER
        !           494:         mul     dword ptr ReimMCAN          ; (edx:eax) = MPER * MCAN.low
        !           495:         push    edx
        !           496:         mov     ecx, eax
        !           497:         mov     eax,ReimMPER
        !           498:         mul     dword ptr ReimMCAN+4        ; (edx:eax) = MPER * MCAN.high
        !           499:         add     eax,[esp]                   ; (eax) = hi part of MPER*MCAN.low
        !           500:                                             ;   plus low part of MPER*MCAN.hi
        !           501: 
        !           502:         test    esi,80000000h
        !           503:         jz      short reim30                ; result sign is OK, go return
        !           504: 
        !           505:         neg     eax
        !           506:         neg     ecx
        !           507:         sbb     eax,0                       ; negate result
        !           508: 
        !           509: reim30: add     esp,4                       ; clean eax off stack
        !           510:         pop     esi                         ; restore nonvolatile reg
        !           511:         mov     edx,eax                     ; (edx:ecx) = result
        !           512:         mov     eax,ecx                     ; (edx:eax) = result
        !           513: 
        !           514:         pop     ebp
        !           515:         stdRET    _ExtendedIntegerMultiply
        !           516: 
        !           517: stdENDP _ExtendedIntegerMultiply
        !           518: 
        !           519:         page
        !           520:         subttl  "Large Integer Shift Left"
        !           521: ;++
        !           522: ;
        !           523: ; LARGE_INTEGER
        !           524: ; LargeIntegerShiftLeft (
        !           525: ;     IN LARGE_INTEGER LargeInteger,
        !           526: ;     IN CCHAR ShiftCount
        !           527: ;     )
        !           528: ;
        !           529: ;
        !           530: ; Routine Description:
        !           531: ;
        !           532: ;     This routine does a left logical shift of a large integer by a
        !           533: ;     specified amount (ShiftCount) modulo 64.
        !           534: ;
        !           535: ; Arguments:
        !           536: ;
        !           537: ;     LargeInteger - Supplies the large integer to be shifted
        !           538: ;
        !           539: ;     ShiftCount - Supplies the left shift count
        !           540: ;
        !           541: ; Return Value:
        !           542: ;
        !           543: ;     LARGE_INTEGER - Receives the shift large integer result
        !           544: ;
        !           545: ;--
        !           546: cPublicProc _LargeIntegerShiftLeft,3
        !           547: cPublicFpo 3,0
        !           548: 
        !           549:         mov     ecx, [esp+12]           ; (ecx) = ShiftCount
        !           550:         and     ecx, 3fh                ; mod 64
        !           551: 
        !           552:         cmp     ecx, 32
        !           553:         jnc     short sl10
        !           554: ;
        !           555: ;  Shift count is less then 32 bits.
        !           556: ;
        !           557:         mov     eax, [esp+4]            ; (eax) = LargeInteger.LowPart
        !           558:         mov     edx, [esp+8]            ; (edx) = LargeInteger.HighPart
        !           559:         shld    edx, eax, cl
        !           560:         shl     eax, cl
        !           561: 
        !           562:         stdRET  _LargeIntegerShiftLeft
        !           563: 
        !           564: align 4
        !           565: sl10:
        !           566: ;
        !           567: ;  Shift count is greater than or equal 32 bits - low half of result is zero,
        !           568: ;  high half is the low half shifted left by remaining count.
        !           569: ;
        !           570:         mov     edx, [esp+4]            ; (edx) = LargeInteger.LowPart
        !           571:         xor     eax, eax                ; store lowpart
        !           572:         shl     edx, cl                 ; store highpart
        !           573: 
        !           574:         stdRET  _LargeIntegerShiftLeft
        !           575: 
        !           576: stdENDP _LargeIntegerShiftLeft
        !           577: 
        !           578:         page
        !           579:         subttl  "Large Integer Shift Right"
        !           580: 
        !           581: ;--
        !           582: ;
        !           583: ;LARGE_INTEGER
        !           584: ;LargeIntegerShiftRight (
        !           585: ;    IN LARGE_INTEGER LargeInteger,
        !           586: ;    IN CCHAR ShiftCount
        !           587: ;    )
        !           588: ;
        !           589: ;Routine Description:
        !           590: ;
        !           591: ;    This routine does a right logical shift of a large integer by a
        !           592: ;    specified amount (ShiftCount) modulo 64.
        !           593: ;
        !           594: ;Arguments:
        !           595: ;
        !           596: ;    LargeInteger - Supplies the large integer to be shifted
        !           597: ;
        !           598: ;    ShiftCount - Supplies the right shift count
        !           599: ;
        !           600: ;Return Value:
        !           601: ;
        !           602: ;    LARGE_INTEGER - Receives the shift large integer result
        !           603: ;
        !           604: ;--*/
        !           605: cPublicProc _LargeIntegerShiftRight,3
        !           606: cPublicFpo 3,0
        !           607: 
        !           608:         mov     ecx, [esp+12]           ; (ecx) = ShiftCount
        !           609:         and     ecx, 3fh                ; mod 64
        !           610: 
        !           611:         cmp     ecx, 32
        !           612:         jnc     short sr10
        !           613: 
        !           614: ;
        !           615: ;  Shift count is less then 32 bits.
        !           616: ;
        !           617:         mov     eax, [esp+4]            ; (eax) = LargeInteger.LowPart
        !           618:         mov     edx, [esp+8]            ; (edx) = LargeInteger.HighPart
        !           619:         shrd    eax, edx, cl
        !           620:         shr     edx, cl
        !           621: 
        !           622:         stdRET  _LargeIntegerShiftRight
        !           623: 
        !           624: align 4
        !           625: sr10:
        !           626: ;
        !           627: ;  Shift count is greater than or equal 32 bits - high half of result is zero,
        !           628: ;  low half is the high half shifted right by remaining count.
        !           629: ;
        !           630:         mov     eax, [esp+8]            ; (eax) = LargeInteger.HighPart
        !           631:         xor     edx, edx                ; store highpart
        !           632:         shr     eax, cl                 ; store lowpart
        !           633: 
        !           634:         stdRET  _LargeIntegerShiftRight
        !           635: 
        !           636: stdENDP _LargeIntegerShiftRight
        !           637: 
        !           638: ;++
        !           639: ;
        !           640: ;LARGE_INTEGER
        !           641: ;LargeIntegerArithmeticShift (
        !           642: ;    IN LARGE_INTEGER LargeInteger,
        !           643: ;    IN CCHAR ShiftCount
        !           644: ;    )
        !           645: ;
        !           646: ;Routine Description:
        !           647: ;
        !           648: ;    This routine does a right arithmetic shift of a large integer by a
        !           649: ;    specified amount (ShiftCount) modulo 64.
        !           650: ;
        !           651: ;Arguments:
        !           652: ;
        !           653: ;    LargeInteger - Supplies the large integer to be shifted
        !           654: ;
        !           655: ;    ShiftCount - Supplies the right shift count
        !           656: ;
        !           657: ;Return Value:
        !           658: ;
        !           659: ;    LARGE_INTEGER - Receives the shift large integer result
        !           660: ;
        !           661: ;--
        !           662: cPublicProc _LargeIntegerArithmeticShift,3
        !           663: cPublicFpo 3,0
        !           664: 
        !           665:         mov     ecx, [esp+12]           ; (ecx) = ShiftCount
        !           666:         and     ecx, 3fh                ; mod 64
        !           667: 
        !           668:         cmp     ecx, 32
        !           669:         jc      short sar10
        !           670: 
        !           671: ;
        !           672: ;  Shift count is greater than or equal 32 bits - high half of result is sign
        !           673: ;  bit, low half is the high half shifted right by remaining count.
        !           674: ;
        !           675:         mov     eax, [esp+8]            ; (eax) = LargeInteger.HighPart
        !           676:         sar     eax, cl                 ; store highpart
        !           677:         bt      eax, 31                 ; sign bit set?
        !           678:         sbb     edx, edx                ; duplicate sign bit into highpart
        !           679: 
        !           680:         stdRET  _LargeIntegerArithmeticShift
        !           681: 
        !           682: align 4
        !           683: sar10:
        !           684: ;
        !           685: ;  Shift count is less then 32 bits.
        !           686: ;
        !           687: ;
        !           688:         mov     eax, [esp+4]            ; (eax) = LargeInteger.LowPart
        !           689:         mov     edx, [esp+8]            ; (edx) = LargeInteger.HighPart
        !           690:         shrd    eax, edx, cl
        !           691:         sar     edx, cl
        !           692: 
        !           693:         stdRET  _LargeIntegerArithmeticShift
        !           694: 
        !           695: stdENDP _LargeIntegerArithmeticShift,3
        !           696: 
        !           697: 
        !           698:         page
        !           699:         subttl  "Large Integer Negate"
        !           700: ;++
        !           701: ;
        !           702: ; LARGE_INTEGER
        !           703: ; LargeIntegerNegate (
        !           704: ;    IN LARGE_INTEGER Subtrahend
        !           705: ;    )
        !           706: ;
        !           707: ; Routine Description:
        !           708: ;
        !           709: ;    This function negates a signed large integer and returns the signed
        !           710: ;    large integer result.
        !           711: ;
        !           712: ; Arguments:
        !           713: ;
        !           714: ;   (TOS+4) = Subtrahend
        !           715: ;
        !           716: ; Return Value:
        !           717: ;
        !           718: ;    The large integer result is stored in (edx:eax)
        !           719: ;
        !           720: ;--
        !           721: 
        !           722: cPublicProc _LargeIntegerNegate  ,2
        !           723: cPublicFpo 2,0
        !           724: 
        !           725:         mov     eax,[esp]+4             ; (eax) = lo
        !           726:         mov     edx,[esp]+8
        !           727:         neg     edx                     ; (edx) = 2's comp of hi part
        !           728:         neg     eax                     ; if ((eax) == 0) CF = 0
        !           729:                                         ; else CF = 1
        !           730:         sbb     edx,0                   ; (edx) = (edx) - CF
        !           731:                                         ; (edx:eax) = result
        !           732:         stdRET    _LargeIntegerNegate
        !           733: 
        !           734: stdENDP _LargeIntegerNegate
        !           735: 
        !           736: 
        !           737:         page
        !           738:         subttl  "Large Integer Subtract"
        !           739: ;++
        !           740: ;
        !           741: ; LARGE_INTEGER
        !           742: ; LargeIntegerSubtract (
        !           743: ;    IN LARGE_INTEGER Minuend,
        !           744: ;    IN LARGE_INTEGER Subtrahend
        !           745: ;    )
        !           746: ;
        !           747: ; Routine Description:
        !           748: ;
        !           749: ;    This function subtracts a signed large integer from a signed large
        !           750: ;    integer and returns the signed large integer result.
        !           751: ;
        !           752: ; Arguments:
        !           753: ;
        !           754: ;    (TOS+4) = Minuend
        !           755: ;    (TOS+12) = Subtrahend
        !           756: ;
        !           757: ; Return Value:
        !           758: ;
        !           759: ;    The large integer result is stored in (edx:eax)
        !           760: ;
        !           761: ;--
        !           762: 
        !           763: cPublicProc _LargeIntegerSubtract    ,4
        !           764: cPublicFpo 4,0
        !           765: 
        !           766:         mov     eax,[esp]+4
        !           767:         sub     eax,[esp]+12            ; (eax) = result.low
        !           768:         mov     edx,[esp]+8
        !           769:         sbb     edx,[esp]+16            ; (edx) = result.high
        !           770:         stdRET    _LargeIntegerSubtract
        !           771: 
        !           772: stdENDP _LargeIntegerSubtract
        !           773: 
        !           774:         page
        !           775:         subttl  "Convert Long to Large Integer"
        !           776: ;++
        !           777: ;
        !           778: ; LARGE_INTEGER
        !           779: ; ConvertLongToLargeInteger (
        !           780: ;     IN LONG SignedInteger
        !           781: ;     )
        !           782: ;
        !           783: ; Routine Description:
        !           784: ;
        !           785: ;     This function converts the input signed integer to a signed large
        !           786: ;     integer and returns the latter as the result.
        !           787: ;
        !           788: ; Arguments:
        !           789: ;
        !           790: ;   (TOS+4) = SignedInteger
        !           791: ;
        !           792: ; Return Value:
        !           793: ;
        !           794: ;    The large integer result is stored (edx:eax)
        !           795: ;
        !           796: ;--
        !           797: 
        !           798: cPublicProc _ConvertLongToLargeInteger   ,1
        !           799: cPublicFpo 1,0
        !           800: 
        !           801:         mov     eax,[esp]+4             ; (eax) = SignedInteger
        !           802:         cdq                             ; (edx:eax) = signed LargeInt
        !           803:         stdRET    _ConvertLongToLargeInteger
        !           804: 
        !           805: stdENDP _ConvertLongToLargeInteger
        !           806: 
        !           807: 
        !           808:         page
        !           809:         subttl  "Convert Ulong to Large Integer"
        !           810: ;++
        !           811: ;
        !           812: ; LARGE_INTEGER
        !           813: ; ConvertUlongToLargeInteger (
        !           814: ;     IN LONG UnsignedInteger
        !           815: ;     )
        !           816: ;
        !           817: ; Routine Description:
        !           818: ;
        !           819: ;     This function converts the input unsigned integer to a signed large
        !           820: ;     integer and returns the latter as the result.
        !           821: ;
        !           822: ; Arguments:
        !           823: ;
        !           824: ;   (TOS+4) = UnsignedInteger
        !           825: ;
        !           826: ; Return Value:
        !           827: ;
        !           828: ;    The large integer result is stored in (edx:eax)
        !           829: ;
        !           830: ;--
        !           831: 
        !           832: cPublicProc _ConvertUlongToLargeInteger  ,1
        !           833: cPublicFpo 1,0
        !           834: 
        !           835:         mov     eax,[esp]+4             ; store low
        !           836:         xor     edx,edx                 ; store 0 in high
        !           837:         stdRET    _ConvertUlongToLargeInteger
        !           838: 
        !           839: stdENDP _ConvertUlongToLargeInteger
        !           840: 
        !           841: 
        !           842: _TEXT   ends
        !           843:         end

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.