user manual

Efficient 64-Bit Integer Arithmetic 89
22007E/0November 1999 AMD Athlon Processor x86 Code Optimization
MOV ECX, EAX ;save quotient
IMUL EDI, EAX ;quotient * divisor hi-word
; (low only)
MUL DWORD PTR [ESP+20];quotient * divisor lo-word
ADD EDX, EDI ;EDX:EAX = quotient * divisor
SUB EBX, EAX ;dividend_lo – (quot.*divisor)_lo
MOV EAX, ECX ;get quotient
MOV ECX, [ESP+16] ;dividend_hi
SBB ECX, EDX ;subtract divisor * quot. from dividend
SBB EAX, 0 ;adjust quotient if remainder negative
XOR EDX, EDX ;clear hi-word of quot(EAX<=FFFFFFFFh)
POP EDI ;restore EDI as per calling convention
POP EBX ;restore EBX as per calling convention
RET ;done, return to caller
_ulldiv ENDP
Example 8 (Remainder):
;_ullrem divides two unsigned 64-bit integers, and returns
; the remainder.
;
;INPUT: [ESP+8]:[ESP+4] dividend
; [ESP+16]:[ESP+12] divisor
;
;OUTPUT: EDX:EAX remainder of division
;
;DESTROYS: EAX,ECX,EDX,EFlags
_ullrem PROC
PUSH EBX ;save EBX as per calling convention
MOV ECX, [ESP+20] ;divisor_hi
MOV EBX, [ESP+16] ;divisor_lo
MOV EDX, [ESP+12] ;dividend_hi
MOV EAX, [ESP+8] ;dividend_lo
TEST ECX, ECX ;divisor > 2^32–1?
JNZ $r_big_divisor ;yes, divisor > 32^32–1
CMP EDX, EBX ;only one division needed? (ECX = 0)
JAE $r_two_divs ;need two divisions
DIV EBX ;EAX = quotient_lo
MOV EAX, EDX ;EAX = remainder_lo
MOV EDX, ECX ;EDX = remainder_hi = 0
POP EBX ;restore EBX as per calling convention
RET ;done, return to caller