Reputation: 201
I try to divide 32 bit number in 16 bit number. For example 10000000h divide by 2000h.According the desgin I try to do I divide 4 right digits with the divisor and then the 4 left digit by the divisor.
This is my code :
.DATA
num dd 10000000h
divisor dw 2000h
result dd ?
remainder dw ?
.CODE
main:
mov ax,@DATA
mov ds,ax
xor dx,dx
mov cx ,word ptr divisor
mov bx,offset num
mov ax,[bx]
div cx
mov bx,offset result
mov [bx],ax
mov bx,offset num
mov ax,[bx+2]
mov ax,[bx+2]
div cx
mov bx,offset result
mov [bx+2],ax
I got zero in variable result. Not sure if the problem with the design of the divide or just a little mistake.
Upvotes: 2
Views: 18969
Reputation: 126203
With the 16-bit div
instruction, you need to put the upper 16 bits of the dividend into dx
and the lower 16 bits in ax
. You've done the latter for the first div
, but you set dx
to 0, so you end up computing 0h/2000h, which is 0.
Instead, you want something like:
mov bx, offset num
mov ax, [bx]
mov dx, [bx+2]
mov cx, word ptr divisor
div cx
Of course, this only works as long as the result fits in 16 bits—if it does not, the div
instruction will raise a #DE exception.
Upvotes: 5
Reputation: 365
The code written in answer 1 is the only exact. I written similar code, that divide D1 by D2:
Function Div32Bit(D1:LongInt;D2:Word):LongInt; Assembler;
Asm
LEA SI,D1
Mov CX,[SS:SI]
Mov AX,[SS:SI+2]
{AX:CX contains number to divide by}
Mov BX,D2
{BX contains number that divide}
XOr DX,DX
Div BX
XChg AX,CX
Div BX
{CX:AX contains the result of division}
{DX contains the rest of division}
Mov DX,CX
{DX:AX contains the result of division and is the function's result}
End;
But this method isn't valid to divide two signed number. To divide two signed number:
Function IDiv32Bit(D1:LongInt;D2:Integer):LongInt; Assembler;
Asm
LEA SI,D1
Mov CX,[SS:SI]
Mov AX,[SS:SI+2]
{AX:CX contains number to divide by}
Cmp AX,32768
CmC
SbB SI,SI
XOr CX,SI
XOr AX,SI
Sub CX,SI
SbB AX,SI
{AX:CX contains the absolute value of the number to divide by}
Mov BX,D2
{BX contains number that divide}
Cmp BX,32768
CmC
SbB DX,DX
XOr BX,DX
Sub BX,DX
{BX contains the absolute value of the number that divide}
XOr SI,DX
{SI contains the sign of division}
XOr DX,DX
Div BX
XChg AX,CX
Div BX
{CX:AX contains the absolute value of the result of division}
{DX contains the absolute value of the rest of division}
XOr AX,SI
XOr CX,SI
Sub AX,SI
SbB CX,SI
{CX:AX contains the result of division}
Mov DX,CX
{DX:AX contains the result of division and is the function's result}
End;
Upvotes: 1
Reputation: 28828
The method below is similar to long hand division on pencil and paper, dividing a 2 digit numerator by a single digit divisor. For example 99/4:
2 4 (quotient)
-----
4 | 9 9
8
-
1 9
1 6
-
3 (remainder)
Start off with dx = 0 and ax = high order of numerator. After the first div instruction, the remainder in dx is what's left of the high order of the numerator for the second divide. This method could be enhanced to handle a numerator and quotient of any size, as long as the divisor is a 16 bit value.
num dd 10000000h
dvsr dw 2000h
quot dd ?
rmdr dw ?
; ...
mov cx,dvsr ;cx = dvsr
xor dx,dx ;dx = 0
mov ax,word ptr [num+2] ;ax = high order numerator
div cx ;dx = rem, ax = high order quotient
mov word ptr [quot+2],ax ;store high order quotient
mov ax,word ptr [num] ;ax = low order numerator
div cx ;dx = rem, ax = low order quotient
mov word ptr [quot],ax ;store low order quotient
mov word ptr [rmdr],dx ;store remainder
Upvotes: 4