Reputation: 77
I don't know what is the exact definition of overflow in the division. can you explain it first and then instruct it by the below example?
for example my book has written that this piece of code results to overflow. I don't know why??
mov dx,0087h
mov ax,6002h
mov bx,10h
div bx
but this piece of code is correct and doesn't result to overflow:
mov dx,0087h
mov ax,6000h
mov bx,100h
div bx
so why the first result into overflow but second not what is the difference?
Upvotes: 1
Views: 5607
Reputation: 5775
The dividend in registers DX
and AX
is in fact a 32bit number, in your example it is 00876002h
.
It will be divided by the divisor BX
and the result (quotient) should fit in register AX
. The remainder after unsigned division will be put into register DX
.
When you try to divide 00876002h
by the contents of BX
(10h
), the result is 87600h
and remainder is 2. Now you should see why it triggers an error: quotient 87600h
is too big to fit into 16bit register AX
.
Divide overflow (alias division by zero) happens when the divisor is too small. Your example will overflow when BX
is below DX
.
Upvotes: 8
Reputation: 364210
0x00876002 / 0x10 = 0x87600
, so the quotient of DX:AX / BX
doesn't fit in AX, thus you get a #DE exception. Intel's instruction reference manual (x86 SDM vol. 2) has detailed descriptions of every instruction, and the entry for div
explains this. There's an HTML extract of the div
entry here. See the x86 tag wiki for links to Intel's docs, and other stuff.
Dividing by 10h is a right shift by 1 hex digit, but the high-half of the input, DX, has 2 significant hex digits.
x86 Assembly: Division Floating Point Exception dividing by 11 is mostly a duplicate of this, and @rcgldr's answer has code for extended-precision division (e.g. 32-bit / 16-bit producing a 32-bit quotient and 16-bit remainder) using div
that works for an arbitrary 16-bit divisor.
In your specific case you're dividing by a power of 2. This is very inefficient with div
.
For these power-of-2 divisions, you should use
; input in DX:AX
shrd ax, dx, 4 ; right shift AX, shifting in bits from DX
shr dx, 4 ; separately right shift DX
; DX:AX = 0008:7600 = 0x87600 = 32-bit quotient
If you want the remainder, it's the low 4 bits of the original AX, which you should get with mov cl, al
/ and cl, 0Fh
.
SHRD only modifies its destination, not the source, so you need that 2nd shr
on DX. This makes sense for larger extended-precision shifts: you want to use a chain of SHRD instructions to shift bits into the top of each element in turn, and don't want to shift in zeros.
Or if you can't use 386 instructions like shrd
, you can emulate SHRD with a left and right shift and an OR. Original 8086 doesn't have immediate-count shifts either, so you'd need a count in CL.
; 8086-compatible version of 32-bit division by 10h, i.e. right shift by 4.
; input in DX:AX
mov bx, dx
mov cl, 16-4
shl bx, cl ; bx = the bits shifted across the 16-bit boundary into low half
mov cl, 4
shr ax, cl
shr dx, cl ; discards the bits shifted out
or ax, bx ; replace the 4 zeros at the top of AX with the bits from DX
; quotient in DX:AX
Or if you know that the result won't overflow, like in the divide-by 100h
(right shift by 8) case, you can use just one SHRD.
Upvotes: 3