Re: NAFCQY [Not A FastCode Question, Yay!]: Int64 DivMod



On Wed, 27 Jul 2005 17:23:30 +0200, "Kristofer Skaug"
<nospam@xxxxxxxxx> wrote:

>Yes, I would like signs to be handled like div and mod would handle it.
>i.e. the function should have identical output to
>
> Result := Dividend div Divisor;
> Remainder := Dividend mod Divisor;
>
>is it hard to do? Thanks!

Sheesh, do I have to do everything around here?! ;)

I haven't really looked at register usage, you might be able to
optimize it somewhat/a lot. I went for in-the-moment ease of coding :)

procedure DivMod64_2(Dividend, Divisor: Int64; var Result, Remainder:
Int64);
asm
push ebx
push edi
push esi

mov esi, eax // esi = Result
mov edi, edx // edi = Remainder

mov ecx, [ebp+$08]
mov ebx, [ebp+$0C]

mov eax, [ebp+$10]
mov edx, [ebp+$14]

mov ebp, 0

or ebx, ebx
jns @@noneg1
// force positive Divisor
neg ecx
adc ebx, 0
neg ebx
mov ebp, 1

@@noneg1:
or edx, edx
jns @@noneg2
// force positive Dividend
neg eax
adc edx, 0
neg edx
or ebp, 2

@@noneg2:
push ebp // store sign flags

// if both highwords are zero, use regular division
or ebx, ebx
jnz @@binary

or ecx, ecx // let div raise division by zero
jz @@regular

or edx, edx
jz @@regular

@@binary:
push edi
push esi

mov ebp, 64

xor esi, esi
xor edi, edi

@@loop:
shl eax, 1
rcl edx, 1
rcl esi, 1
rcl edi, 1

cmp edi, ebx // check high words
jb @@nosub
ja @@sub
cmp esi, ecx // check low words
jb @@nosub

@@sub:
sub esi, ecx // subtract divisor
sbb edi, ebx
inc eax // increment result

@@nosub:
dec ebp
jnz @@loop

pop ecx
pop ebx

jmp @@exit

@@regular:
div ecx
mov ecx, esi
mov ebx, edi

mov esi, edx
xor edi, edi
xor edx, edx

@@exit:
pop ebp
or ebp, ebp
jp @@signmod
// one of the parameters was negative
// so negate result
neg edx
neg eax
sbb edx,0

@@signmod:
test ebp, 2 // is dividend negative?
jz @@store
// it was, so negate remainder
neg edi
neg esi
sbb edi,0

@@store:
mov [ebx], esi
mov [ebx+4], edi
mov [ecx], eax
mov [ecx+4], edx

pop esi
pop edi
pop ebx
end;

- Asbjørn
.