CPU 執行除法指令時,是有可能溢出的。這在教材上,是有明顯的提示的。
如果被除數較大,或除數較小,都可能使“商”超出預定位數,此時,就會溢出。
特別是當除數為零時,必然會出現:Divide? overflow。
除法溢出,問題很嚴重。壹旦出現除法溢出,系統就崩潰了。
(補碼加減運算,也會有溢出,但是,沒有崩潰的危險。)
王爽在教材上,給出了壹個“不會溢出”編程思路。可實現“雙字/壹字”。
這程序的編程思路,本來是很簡單,但是被他寫的,簡直就是壹塌糊塗。
“字除法”的指令是:DIV? CX。
CPU 的操作,就是:( DX : AX ) / CX = AX ... DX。
按照妳的應用舉例:1000000 / 10 (即:000F 4240H / 000AH)。
如果用“字除法”,簡單說就是“把高位字、低位字,分別除以 CX”。
即,第壹步:用 0000 000FH 除以 000AH,得到高位商 0001、高位余數 0005。?
第二步:用 0005 4240H 除以 000AH,可得到低位商 86A0H、低位余數 0000。
這種計算方法,完全可以用小學用的“豎式”來描述:
以小學生的水平,就可以理解這個圖了。
-----------------------
就這麽壹個簡單問題,妳看王爽寫的多麽濫:
公式:X/N = int(H/N)*65536 + [rem(H/N)*65536 + L]/N
X:被除數,範圍
N:除數,範圍
H:X的高16位
L:X的低16位
int():描述性運算符,取商
ram():描述性運算符,取余數
功能:進行不會產生溢出的除法運算,被除數為dword型,除數為word型,結果為dword型
參數:
(ax)=dword型數據的低16位
(dx)=dword型數據的高16位
(cx)=除數
-----------------------
按照妳提供的數據,程序,應該如下編寫:
START:
MOV DX, 000FH ;被除數的高16位
MOV AX, 4240H ;被除數的低16位
MOV CX, 000AH ;16位
CALL DIVDW ;32位數除以16位數
MOV AX, 4C00H
INT 21H
;--------------
DIVDW: ;DX:AX / CX = DX:AX ... CX
PUSH BX
MOV BX,AX ;保存被除數的低16位
MOV AX,DX ;高16位放在低16
MOV DX,0 ;高16改為0
DIV CX ;
PUSH AX ;保存高16位商
;DX中是余數
MOV AX,BX ;恢復低16位數
DIV CX ;(余數與低16)除以除數
MOV CX,DX ;余數存到CX
POP DX ;商的高16位數送到DX
POP BX ;恢復現場
RET
-----------------------
通用的思路方法,如下:
按照圖中的步驟,執行四次 DIV? BL,即可實現“四個字節/壹個字節”。
只要 BL 不為零,就絕對不會發生溢出。
按此思路,被除數的字節數,可以繼續增加,僅受制於內存的大小。
絕不限於王爽所介紹的 DIVDW 所用的雙字。