組合語言中div運算如果被除數為32位,除數則為16位,被除數放在DX和AX中,商放在AX中,餘數放在DX中。如果被除數為16位,除數則為8位,被除數放在AX中,商放在ah,餘數放在al。
但會產生一個問題,那就是當除出來的商大於AX或者AH的時候,就會產生除法溢出的錯誤。例如1000/1,被除數可以放在16位的AX中,1可以放在8位的寄存器中,得到的商為1000,超過了AH能容納的最大值,因此會造成除法溢出的問題。
王爽的書中提供一個公式,可以避免除法溢出的問題
子程式要求
名稱:divdw
功能:進行不會產生溢出的除法運算,被除數為dword型,除數為word型,結果為dword型
參數:(ax)=dword型資料的低16位
(dx)=dword型資料的高16位
(cx)=除數
返回:(ax)=商的低16位
(dx)=商的高16位
(cx)=餘數
公式
X:被除數,範圍:[0, FFFFFFFF]
N:除數,範圍:[0, FFFF]
H:X高16位,範圍:[0, FFFF]
L:X低16位,範圍:[0, FFFF]
int():描述性運算子,取商,比如,int(38/10)=3
rem():描述性運算子,取餘數,比如,rem(38/10)=8
公式:X/N = int(H/N)*65536+[rem(H/N)*65536+L]/N
分析
首先來看看公式中的65536,很多新手的話可能不能理解這個65536是什麼意思,其實65536就是10000H,相當於2^16,也就是說是乘以2^16,意思就是左移16位。
式中int(H/N)和rem(H/N)代表著X的高16位的商和餘數。
等式右邊的int(H/N)*65536表示將H/N的商作為最終結果商的高位字。
rem(H/N)*65536+L表示將H/N的餘數左移16位,形成一個新的dword資料的高16位,L作為低16位。
最後的結果是DX中存放int(H/N)的結果,AX中存放(rem(H/N)*65536+L)/N的商,CX中存放(rem(H/N)*65536+L)/N的餘數。
子程式
;子程式描述
;名稱: divdw
;功能: 進行不會產生溢出的除法運算,被除數為dword型,除數為word型,結果為dword型.
;參數: (dx)=dword型資料的高16位 (ax)=dword型資料的低16位 (cx)=除數
;返回: (dx)=結果的高16位 (ax)=結果的低16位 (cx)=餘數
;應用舉例: 計算1000000/10(F4240H/0AH)
divdw:
push ax ;被除數的低16位入棧
mov ax,dx
mov dx,0
mov cx,10
div cx ;得到的結果商放在AX中,餘數放在DX中
mov cx,ax;暫時儲存商
pop ax ;取出低16位的值
push cx ;儲存商入棧
mov cx,10
div cx
mov cx,dx ;餘數放入cx中
pop dx ;商的高16位存入dx中,ax中的結果就為商的低16位
ret