1;------------------------------------------------------------------------------ 2; 3; Copyright (c) 2006, Intel Corporation. All rights reserved.<BR> 4; This program and the accompanying materials 5; are licensed and made available under the terms and conditions of the BSD License 6; which accompanies this distribution. The full text of the license may be found at 7; http://opensource.org/licenses/bsd-license.php. 8; 9; THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, 10; WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. 11; 12; Module Name: 13; 14; DivU64x64Remainder.nasm 15; 16; Abstract: 17; 18; Calculate the quotient of a 64-bit integer by a 64-bit integer and returns 19; both the quotient and the remainder 20; 21;------------------------------------------------------------------------------ 22 23 SECTION .text 24 25extern ASM_PFX(InternalMathDivRemU64x32) 26 27;------------------------------------------------------------------------------ 28; UINT64 29; EFIAPI 30; InternalMathDivRemU64x64 ( 31; IN UINT64 Dividend, 32; IN UINT64 Divisor, 33; OUT UINT64 *Remainder OPTIONAL 34; ); 35;------------------------------------------------------------------------------ 36global ASM_PFX(InternalMathDivRemU64x64) 37ASM_PFX(InternalMathDivRemU64x64): 38 mov ecx, [esp + 16] ; ecx <- divisor[32..63] 39 test ecx, ecx 40 jnz _@DivRemU64x64 ; call _@DivRemU64x64 if Divisor > 2^32 41 mov ecx, [esp + 20] 42 jecxz .0 43 and dword [ecx + 4], 0 ; zero high dword of remainder 44 mov [esp + 16], ecx ; set up stack frame to match DivRemU64x32 45.0: 46 jmp ASM_PFX(InternalMathDivRemU64x32) 47 48_@DivRemU64x64: 49 push ebx 50 push esi 51 push edi 52 mov edx, dword [esp + 20] 53 mov eax, dword [esp + 16] ; edx:eax <- dividend 54 mov edi, edx 55 mov esi, eax ; edi:esi <- dividend 56 mov ebx, dword [esp + 24] ; ecx:ebx <- divisor 57.1: 58 shr edx, 1 59 rcr eax, 1 60 shrd ebx, ecx, 1 61 shr ecx, 1 62 jnz .1 63 div ebx 64 mov ebx, eax ; ebx <- quotient 65 mov ecx, [esp + 28] ; ecx <- high dword of divisor 66 mul dword [esp + 24] ; edx:eax <- quotient * divisor[0..31] 67 imul ecx, ebx ; ecx <- quotient * divisor[32..63] 68 add edx, ecx ; edx <- (quotient * divisor)[32..63] 69 mov ecx, dword [esp + 32] ; ecx <- addr for Remainder 70 jc @TooLarge ; product > 2^64 71 cmp edi, edx ; compare high 32 bits 72 ja @Correct 73 jb @TooLarge ; product > dividend 74 cmp esi, eax 75 jae @Correct ; product <= dividend 76@TooLarge: 77 dec ebx ; adjust quotient by -1 78 jecxz @Return ; return if Remainder == NULL 79 sub eax, dword [esp + 24] 80 sbb edx, dword [esp + 28] ; edx:eax <- (quotient - 1) * divisor 81@Correct: 82 jecxz @Return 83 sub esi, eax 84 sbb edi, edx ; edi:esi <- remainder 85 mov [ecx], esi 86 mov [ecx + 4], edi 87@Return: 88 mov eax, ebx ; eax <- quotient 89 xor edx, edx ; quotient is 32 bits long 90 pop edi 91 pop esi 92 pop ebx 93 ret 94 95