![]() | ![]() ![]() ![]() |
These set of gems deals with dividing signed integers by powers of 2, and negated powers of 2. These also appear in the AMD K6 optimization guide. Please note that the gems can easily be converted to run on CPUs lower than 386:s.
These first two do signed division by powers of 2:
;
; signed division by 2
;
; input:
; eax = dividend
;
; output:
; eax = quotient
;
; destroys:
; eflags
;
cmp eax,080000000h ; CY = 1, if dividend >= 0
sbb eax,-1 ; increment dividend if it is < 0
sar eax,1 ; now do right shift
;
; signed division by d = 2^k
;
; input:
; eax = dividend
;
; output:
; eax = quotient
;
; destroys:
; edx
; eflags
;
cdq ; EDX = 0xFFFFFFFF if dividend < 0
and edx,(d-1) ; mask correction (use divisor-1)
add eax,edx ; apply correction if necessary
sar eax,k ; now do right shift by log2(divisor)The next two covers signed divison by negated power of 2:;
; signed division by -2
;
; input:
; eax = dividend
;
; output:
; eax = quotient
;
; destroys:
; eflags
;
cmp eax,080000000h ; CY = 1, if dividend >= 0
sbb eax,-1 ; increment dividend if it is < 0
sar eax,1 ; now do right shift
neg eax ; use (x / -2) == -(x / 2)
;
; signed division by d = -(2^k)
;
; input:
; eax = dividend
;
; output:
; eax = quotient
;
; destroys:
; edx
; eflags
;
cdq ; EDX = mask = 0xFFFFFFFF if divdnd < 0
and edx,(-d-1) ; mask correction (-divisor - 1)
add eax,edx ; apply correction if necessary
sar eax,k ; do right shift by log2(-divisor)
neg eax ; use (x / -(2^n)) == (- (x / 2^n))The next two gems covers remainder of signed divisons, both by powers of 2 and negated powers of 2.;
; remainder of signed division by 2 or -2
;
; input:
; eax = dividend
;
; output:
; eax = remainder
;
; destroys:
; edx
; eflags
;
cdq ; flag = EDX = 0xFFFFFFFF if divdnd < 0
and eax,1 ; compute remainder
xor eax,edx ; negate remainder if
sub eax,edx ; dividend was < 0
;
; remainder of signed division by d = 2^k or -(2^k)
;
; input:
; eax = dividend
;
; output:
; eax = remainder
;
; destroys:
; edx
; eflags
;
cdq ; EDX = mask = 0xFFFFFFFF if divdnd < 0
and edx,(abs(d)-1) ; mask correction (abs(divisor)-1)
add eax,edx ; apply pre-correction
and eax,(abs(d)-1) ; mask out remainder (abs(divisor)-1)
sub eax,edx ; apply post-correction if necessary