Search code examples
assemblyx8664-bit32bit-64bit32-bit

Assembly IA-32: How to divide 64-bit signed number by odd number (stored in 2 registers)


On a IA-32 architecture how can i divide a signed number by 3 (e.g.) a value stored in 2 registers, edx:eax (a 64-bit value). I want to divide the whole value (64-bits) by 3, not only 32-bits, and store it in 2 registers.

I'm assuming this can only be done using shifts operations since imul only works for multiplying 32-bits numbers. But only found solutions for dividing by 2^n numbers.

How can i achieve this?


Solution

  • You can divide any length number by a 32 bit number with successive divides, using the remainder of the prior divide as the most significant 32 bits of the dividend for the next divide, similar to long hand division

    Note I need to fix this code to handle negative divisors, but it should work with positive divisors and signed dividend.

    Note this code rounds towards negative infinity: -10/3 : quotient = -4, remainder = +2. To handle negative divisors, the code could negate both divisor and dividend, then negate the remainder after.

            mov     ecx,000000003h  ;ecx = signed dvsr (must be positive)
            mov     edi,0fedcba98h  ;edi:esi = signed dvnd
            mov     esi,076543210h
            ;; inputs
    
            mov     eax,edi         ;eax = upper 32 bits dvnd
            cdq                     ; sign-extend that into EDX:EAX
    
            idiv    ecx
            test    edx,edx         ;br if sign rmdr == sign dvsr
            jns     short div0
            dec     eax             ;dec quot
            add     edx,ecx         ;rem += dvsr
    
    div0:   mov     edi,eax         ;edi = upper 32 bits quot
            mov     eax,esi         ;eax = lower 32 bits dvnd
            div     ecx           
            mov     esi,eax         ;esi = lower 32 bits quot
    ;                               ;edx = remainder