From : Arne de Bruijn                                        2:281/705.8
To   : Joe Koss                            
Subj : 64-bit math                                                           


 JK> My problem is, how do I efficiently handle division of two 64bit
 JK> numbers?

I looked at the runtime library of TP 7.0 to see how they did 32 bit divides
with 16 bit registers, and after understanding it I wrote this one, but it still

looks like the TP 7.0 one. I hope that's not a problem, it looks very standard
to me.

===
model tpascal
ideal
codeseg
p386
public dodiv64
proc dodiv64 near
 arg d1:qword,d2:qword,d:dword,r:dword
 mov eax,[dword d1]   ; Load dividend in edx:eax
 mov edx,[dword d1+4]
 mov ecx,[dword d2]   ; Load divider in ebx:ecx
 mov ebx,[dword d2+4]
 or ebx,ebx           ; Divider < 2^32?
 jnz @BigDiv          ; No -> Must do the loop
 mov ebx,eax          ; Save lo dword of dividend
 mov eax,edx          ; First divide hi dword dividend by divider
 xor edx,edx
 div ecx
 xchg ebx,eax         ; Save hi result, load lo dword of dividend in eax
 xor edx,edx
 div ecx              ; Divide it by divider
 mov ecx,edx          ; Put remainder in ecx
 mov edx,ebx          ; Put hi result in edx
 xor ebx,ebx          ; Hi dword of remainder is zero
 jmp @StoreIt
@BigDiv:
 mov esi,ecx          ; Store Divider in edi:esi
 mov edi,ebx
 mov ecx,edx          ; Divider is at least 2^32, so shift whole thing 32 bits
 mov edx,eax          ; edx:eax=lo dword of dividend*2^32, becomes result
 xor ebx,ebx          ; ebx:ecx=Temp=hi dword of dividend
 xor eax,eax
 push bp
 mov bp,32            ; Process 32 bits
@Loop:
 shl eax,1            ; (lo)Result=Result*2
 rcl edx,1            ; Both (hi)Result=Result*2 and store new bit into Temp
 rcl ecx,1            ; (lo)Temp=Temp*2+new bit from dividend
 rcl ebx,1            ; (hi)Temp=Temp*2
 inc eax              ; Result=Result+1, assume Temp>Divider
 sub ecx,esi          ; Temp=Temp-Divider
 sbb ebx,edi
 jnc @IsOk            ; Temp was greater than Divider? Yes -> @IsOk
 dec eax              ; Undo incrementing result
 add ecx,esi          ; Restore Temp (Temp=Temp+Divider)
 adc ebx,edi
@IsOk:
 dec bp
 jnz @Loop
 pop bp               ; Temp=remainder
@StoreIt:
 les di,[d]           ; Store quotient
 mov [es:di],eax
 mov [es:di+4],edx
 les di,[r]           ; Store remainder
 mov [es:di],ecx
 mov [es:di+4],ebx
 ret
endp
end
===

Greetings,
 Arne 
--- FMail/386 1.0g
 * Origin:  (2:281/705.8)

