Reputation: 75
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.
Upvotes: 2
Views: 2941
Reputation: 11
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...
Upvotes: 1
Reputation: 9899
DI:SI:CX:BX
on 8086This 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!
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
Upvotes: 4
Reputation: 28826
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
Upvotes: 2