benz
benz

Reputation: 201

Assembler 8086 divide 32 bit number in 16 bit number

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

Answers (3)

Chris Dodd
Chris Dodd

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

Paolo Fassin
Paolo Fassin

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

rcgldr
rcgldr

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

Related Questions