;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;名稱: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
--------------------------
綠色文字是結果,與文章開始描述一致,紅色文字是理解的關鍵!