;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;名称: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
--------------------------
绿色文字是结果,与文章开始描述一致,红色文字是理解的关键!