|
|
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
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.