Annotation of mstools/samples/largeint/i386/largeint.asm, revision 1.1.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.