汇编器8086以16位数分割32位数

时间:2017-01-06 08:06:55

标签: assembly x86 division x86-16

我尝试将16位数除以16位数。 例如10000000h除以2000h。根据设计,我尝试做分裂 带有除数的4个右数字,然后是除数的4个左数字。

这是我的代码:

.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 

我在变量结果中得零。不确定是否存在划分设计的问题或只是一点点错误。

3 个答案:

答案 0 :(得分:4)

使用16位div指令,您需要将被除数的高16位置于dxax的低16位。您已为第一个div完成后者,但您将dx设置为0,因此最终计算0h / 2000h,即0。

相反,你需要类似的东西:

mov bx, offset num
mov ax, [bx]
mov dx, [bx+2]
mov cx, word ptr divisor
div cx

当然,只有结果符合16位才有效 - 如果不符合,div指令将引发#DE异常。

答案 1 :(得分:3)

下面的方法类似于铅笔和纸上的长手划分,将2位数分子除以单位数除数。例如99/4:

    2 4    (quotient)
  -----
4 | 9 9
    8
    -
    1 9
    1 6
      -
      3    (remainder)

从dx = 0开始,ax =高阶分子。在第一个div指令之后,dx中的余数是第二个除法的分子的高阶左边。只要除数是16位值,就可以增强此方法来处理任何大小的分子和商。

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

答案 2 :(得分:1)

答案1中写的代码是唯一的。我写了类似的代码,将D1除以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;

但是这种方法无法划分两个带符号的数字。 划分两个签名号码:

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;