Search code examples
assemblyx86gnu-assemblerinteger-divisioncpu-registers

Assembly: division using the values in two 32-bit registers as if they were one 64-bit integer


I have a 64 bit integer I need to print in assembly, but I am working on a 32-bit machine, so I have my 64-bit integer stored in two 32-bit registers. The high part of the integer is stored in %edx and the low part is stored in %eax.

I know how to print a 32-bit integer no problem, just divide by 10 continuously and print the remainders.

I also know how to multiply my 64-bit number by a 32-bit.

But what is killing me is the division:

From what I have gathered, I think I have to divide each of my registers %edx and %eax by ten, and somehow combine the two answers, as I would with multiplication, but what do I do with the remainders and quotients of each division?

I am working with the GNU assembler using the AT&T x86 syntax on a 32-bit Linux machine. Thanks


Solution

  • This question has shown up several times recently. The algorithm is similar to doing division with pencil and paper, dividing a dividend of multiple digits by a single digit divisor. Here's a code snippet, with the 64 bit dividend kept in edi:esi. Note this same method could be extended to divide a very large dividend stored in memory to be divided by a 32 bit divisor.

            .data
    decstr  db      24 dup (0)
    pfstr   db      '%','s',0dh,0ah,0
            .code
            extrn   _printf:NEAR
    _main   proc    near
            mov     edi,000000002h          ;edi = high order dvnd
            mov     esi,04CB016EAh          ;esi = low  order dvnd
            lea     ebx,decstr+23           ;ebx = ptr to end string
            mov     ecx,10                  ;ecx = 10 (constant)
    div0:   xor     edx,edx                 ;clear edx
            mov     eax,edi                 ;divide high order
            div     ecx
            mov     edi,eax
            mov     eax,esi                 ;divide low order
            div     ecx
            mov     esi,eax
            add     dl,'0'                  ;store ascii digit
            dec     ebx
            mov     [ebx],dl
            mov     eax,edi                 ;repeat till dvnd == 0
            or      eax,esi
            jnz     div0
            push    ebx                     ;display string
            push    offset pfstr
            call    _printf
            add     sp,8
            xor     eax,eax
            ret
    _main   endp