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 25 extern 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 ;------------------------------------------------------------------------------ 36 global ASM_PFX(InternalMathDivRemU64x64) 37 ASM_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