1
votes

I'm working on an assignment and I'm stuck on divide overflow.
It's giving an error because I'm dividing a 64 bit number DX AX by a 32 bit number. The answer doesn't fit in AX so it gives an error.

Is there any way to overcome this overflow ? I want to convert this number into decimal so I'm trying to divide it by 10.

3
You can implement a division algorithm or use repeated subtraction of powers of 10.Jester
ax and dx are 16-bit registers. Two of them can only form a 32-bit pseudo-register, not a 64-bit one. You need eax:edx, which is only available from the 80386 onwards.EOF
EOF's reply is why comments needs the downvoting-functionality. It's not very helpful and doesn't seem to understand the question. Obviously you can do arithmetic operations on numbers that are too large for the registers available - as seen in the correct answers below.Christoffer Bubach

3 Answers

3
votes

Displaying the 64-bit number in DI:SI:CX:BX on

Step 1. Calculating the digits

This requires using a chain of divisions starting at the Most Significant Word of the 64-bit number. The remainder of every division is re-used on the next division.

  mov  bp, 10  ;Constant divider 10
  push bp      ;Will signal the end of the PUSHed remainders
Next:
  xor  dx, dx
  xchg ax, di  ;Most Significant Word is in DI
  div  bp      ;Divide Word3
  xchg di, ax
  xchg ax, si
  div  bp      ;Divide Word2
  xchg si, ax
  xchg ax, cx
  div  bp      ;Divide Word1
  xchg cx, ax
  xchg ax, bx  ;Least Significant Word is in BX
  div  bp      ;Divide Word0
  mov  bx, ax

  push dx      ;Every remainder is [0,9]

  or   ax, cx  ;OR all quotients together
  or   ax, si
  or   ax, di
  jnz  Next    ;Repeat while 64-bit number not zero

Please note that the xchg instruction was used to reduce code size!

Step 2. Displaying the digits

To display the characters I'll presume this is running on DOS.
Should be real easy to adapt this to another OS...

  pop  dx      ;This is digit for sure
More:
  add  dl, '0' ;Convert from remainder [0,9] to character ["0","9"]
  mov  ah, 02h
  int  21h     ;DisplayCharacter
  pop  dx
  cmp  dx, bp  ;Repeat until it was the 'signal (bp=10)' that was POPed
  jb   More
2
votes

Start with edx = 0, and eax = upper bits of the dividend. Divide by 10, and eax will be the upper dividend for the next loop so save it. edx will have the remainder, which is used for the next divide: eax = lower bits of the dividend. Divide by 10, and eax will be the lower dividend for the next loop so save it. edx will be the remainder of the 64 bit dividend divided by 10, which will be the least significant decimal digit of the number. Repeat the loop to get the digits in reverse order.

In response to the comment below, assume the 64 bit number is in EDI:ESI (high:low):

        mov     ecx,10
loop0:  xor     edx,edx         ;divide high order by 10
        mov     eax,edi
        div     ecx
        mov     edi,eax
        mov     eax,esi         ;divide low  order by 10
        div     ecx
        mov     esi,eax
;                               ;at this point edx contains one decimal digit
;       ...                     ;store the digit and continue with the loop
1
votes

Got the inspiration from rcgldr

here is how it would be done in 8086 since all registers in 8086 are all 16bit

                                ;here we have a 64bit number in si:di:cx:bx
loop0:  xor dx,dx
        mov ax,si               ;divide highes order by 10
        div diver
        mov si,ax
        mov ax,di               ;divide high order by 10
        div diver
        mov di,ax
        mov ax,cx               ;divide low oreder by 10
        div diver
        mov cx,ax
        mov ax,bx               ;divide lowest order by 10
        div diver
        mov bx,ax
                                ;right now we have the wanted number in dx
        mov temp,si             ;keep value of si for later
        mov si,[bp+4]           ;make si point to wanted string
        add si,18               ;move to end of string
        sub si,counter          ;move back the amount of times used
        add dx,'0'
        mov byte ptr [si],dl
        inc counter
        mov si,temp             ;put back saved value in si and go again
        cmp si,0
        jne loop0
        cmp di,0
        jne loop0
        cmp cx,0
        jne loop0
        cmp dx,0
        jne loop0
        mov counter,0           ;reset counter

I was trying to solve a similar problem for 2 days!! until I read rcgldr's answer. THANK YOU! the only difference was that I needed to divide a 64bit number by 10 in 386 environment and not 8086 but its all the same and since your question helped me i wrote this code for you in 8086.

Hope it helps someone...