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