汇编双字型除法

来源(编程爱好者论坛)

汇编双字型除法
点击数:695 发布日期:2007-9-16 11:17:00

;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;名称:divdw
;功能:不会溢出的除法运算
;参数:ax=dword的低16位
;     dx=dword的高16位
;     cx=除数
;返回:ax=结果的低16位
;     dx=结果的高16位
;     cx=余数
;;;;;;;;;;;;;;;;;;;;;;;;;;;;
divdw:
      push bx
      push ax   ;保存低16位
      mov ax,dx
      mov dx,0
      div cx
      mov bx,ax
      pop ax
      div cx
      mov cx,dx
      mov dx,bx
      pop bx
      ret 

====================================
该段程序截取自一个程序,按照程序运行结果是正确的
a.CBW,字节型扩展成字型数据
b.CWD,字型扩展成双字型数据
c.CWDE,是80386新增的指令。格式:CWDE。功能:将AX的符号位扩展到EAX的高16位中。
d.CDQ,是80386新增的指令。格式:CDQ。功能,将EAX的符号位扩展到EDX中。
e.以上四条指令均不影响标志位。
--------------------------
mov eax,600000
mov ecx,1000
idiv ecx 

--------------------------
上面会出现除法溢出错误
查找资料是这样解决的
--------------------------
mov     eax, 600000
cdq
mov     ecx, 1000
idiv    ecx 

--------------------------
还有一个人是这样的解决的
这种情况下,用
xor edx, edx
代替cdq也可以,因为被除数是正数
总之,注意edx寄存器的值!

这种理解就深刻的多了
--------------------------
mov eax,6527363 
mov ecx,28732 
div ecx 

--------------------------
被除数达到了双精度值,所以不能用符号扩展,而只能将高16位送0
我们只要保证edx为0就可以了
--------------------------
xor edx,edx 
mov eax,6527363 
mov ecx,28732 
div ecx 

--------------------------
由此推断
xor  edx, edx

代替cdq也可以,因为“被除数是正数”。这样就不影响符号位了
问题一:但是假既是负数又是双精度值呢?符号位如何处理呢?怎么解决的呢?
看来只能按高位低位分别扩展,去除符号位后做无符号除法。

废话说了那么多,起初那个程序的意思也就可以明白了
--------------------------
divdw:
      push bx
      push ax   ;保存低16位
      mov ax,dx ;高16位值送入ax做除法
      mov dx,0  ;dx置0,[xor dx,dx]
      div cx    ;ax为高16位商,dx为高16位余数
      mov bx,ax ;保存高16位结果在bx中
      pop ax    ;低16位值放入ax
      div cx    ;这里与上面的区别就是dx未置零,这是理解的关键
                ;此时的除法包含了上次余数与低16位拼合的值
                ;求出的余数就是32位值的余数,并保存在dx中
                ;ax中此时是低16位的商
      mov cx,dx ;cx中保存余数
      mov dx,bx ;高16位结果放入dx中
      pop bx
      ret 

--------------------------

不会溢出的除法(32位除16位,商如果只能是16位,则可能溢出,比如FFFFF div 1)
;因此,把商也要增大到32位
;输入参数:ax 保存被除数低16位,dx 保存被除数高16位,cx 保存除数
;输出参数:ax 保存商低16位,dx 保存商高16位,cx保存余数
;计算方法:商的高16位=被除数高16位 div 除数 的 商
; 商的低16位=((被除数高16位 div 除数 的 余数)*FFFF+被除数低16位)div 除数 的 商
; 余数=上式的余数
public divdw
segdivdw segment 'code'
divdw proc far
    push bx   ;保存bx
    mov bx,ax ;先把低16位保存
    mov ax,dx ;高16位移到低16位
    mov dx,0  ;高16位置零
    div cx    ;除
    push ax   ;保存商
    mov ax,bx ;取出原来保存的低16位,高16位是上次除法的余数,已经在dx里面了
    div cx    ;再除
    mov cx,dx ;把余数保存到cx
    pop dx    ;把第一次除的商,放入dx,作为结果的高16位
    pop bx    ;恢复bx
    ret       ;返回
divdw endp
segdivdw ends
end 

Link: http://www.asm32.net/article_details.aspx?id=4394


浏览次数 123 发布时间 2009-01-07 08:46:27 从属分类 ASM/ASM32 【评论】【 】【打印】【关闭
 
| www.asm32.net | 2006版 | 资料中心 | linux | asm/asm32 | C/C++ | VC++ | java | Python | 书签 | ASP.Net书签 | 京ICP备09029108号-1