除法(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)举例