除法(DIV/IDIV)
目錄
- 除法(DIV/IDIV)
- `DIV`(unsigned divide)無符號數除法
- `IDIV`(signed divide)有符號數除法
DIV
(unsigned divide)無符號數除法
格式:DIV SRC
操作:
- SRCSRCSRC為字節時,(AL)←(AX)/(SRC)(AL)\gets (AX)/(SRC)(AL)←(AX)/(SRC)的商,(AH)←(AX)/(SRC)(AH)\gets (AX)/(SRC)(AH)←(AX)/(SRC)的余數
- SRCSRCSRC為字時,(AX)←(DX,AX)/(SRC)(AX)\gets (DX,AX)/(SRC)(AX)←(DX,AX)/(SRC)的商,(DX)←(DX,AX)/(SRC)(DX)\gets (DX,AX)/(SRC)(DX)←(DX,AX)/(SRC)的余數
該指令將參與運算的數據默認為無符號數,則商和余數都是無符號數
除法貌似并不會影響標志位(進位標志CFCFCF和溢出標志OFOFOF)的改變,但通過上述操作可知,被除數位數總是除數的兩倍,而相除的商和余數是存儲在和除數位數相同的空間里,顯然余數是肯定夠存的,但是商是有可能存不下的(例如:0300H÷02H=0180H0300H\div 02H=0180H0300H÷02H=0180H,這里商僅依靠字節存儲是無法存下的)。商出現溢出時,系統轉0號類型中斷處理,提示“divide overflow”,并退出程序,返回到操作系統,程序便已經崩潰了。要想避免出現這種情況,必須在作除法前對溢出作出預判
由于商需要更大空間來存儲,而字節長度的除數無法滿足,因此需要將其擴展為字長度,這樣商便有了字長度空間存儲
MOV AX, 300H
CWD ;這里書上使用CWD指令進行字到雙字的符號擴展(將AX的符號位即最高位填充至DX的所有位),而這里使用的是無符號數除法,當被除數的最高位為1時顯然會擴大被除數的大小,我認為應當使用零擴展(即將DX所有位置0),這樣便不會改變原數的大小,但我未查詢到匯編零擴展的相關指令,或許沒有該指令,也許只能自己手動零擴展(MOV DX, 0)
MOV BX, 2
DIV BX ;這里的SRC為字長
這里使用CWD
進行符號擴展是因為SRCSRCSRC為字長時,被除數則為(DX,AX)(DX,AX)(DX,AX),因此需將這兩寄存器一起看作被除數,于是使用CWD
將DXDXDX置0,使其整體等于300H300H300H,這里個人認為因采用類似MOV DX, 0
的指令去處理更為合理
等到的結果商為180H(AX)180H(AX)180H(AX),余數為0H(DX)0H(DX)0H(DX)
IDIV
(signed divide)有符號數除法
指令格式和操作與無符號數除法相同,用來作有符號數除法。最終商的符號應是兩個操作數符號的異或,而余數的符號和被除數符號一致
這里用FF80H(?128)÷03H(+3)=D6H(?42)??FEH(?2)FF80H(-128)\div 03H(+3)=D6H(-42)\cdots \cdots FEH(-2)FF80H(?128)÷03H(+3)=D6H(?42)??FEH(?2)舉例