8086指令系统之算数运算指令
本篇介绍了汇编指令中如何进行运算,包括加、减、乘、除
前置问题:
- 怎么做多字节的加减法?
- 为什么加减法指令不分有符号数和无符号数,而乘除法的有符号数和无符号数运算分别是不同的指令
- 如何确定指令执行的是字节操作还是字操作?
- 符号扩展指令再什么时候会用到,如何用?
- 取负指令NEG为什么执行的是取反加一?
加法指令
ADD 加法指令
指令格式:ADD 目的, 源
指令功能:目的
ADC 带进位的加法指令
ADC: Addition with Carry
指令格式:ADC 目的, 源
指令功能:目的
用作多字节加法
注意:
- 上面两条指令的源操作数可以是寄存器、存储器或者立即数
- 目的操作数只能用寄存器和存储单元
- 源和目的操作数不能同时为存储器,而且他们的类型必须一致,同时为字节或者字
- 它们影响到的标志位:CF、OF、PF、SF、ZF、AF
INC 增量指令
INC: Increment
指令格式:INC 目的
指令功能:目的
注意:
- 目的操作数可以是通用寄存器或内存。指令执行后影响AF、OF、PF、SF和ZF,但是进位标志CF不受影响
- 指令中只有一个操作数,如果是内存单元,则要用PTR操作符说明是字节还是字
减法指令
SUB减法指令
指令格式:SUB 目的, 源
指令功能: 目的
SBB 带借位的减法指令
指令格式: SBB 目的, 源
指令功能:目的
SBB主要用于多字节减法中
DEC 减量指令
DEC: Decrement
指令功能:DEC 目的
指令功能:目的
NEG 取负指令
指令格式:NEG 目的
指令功能:目的$$0 - 目的(取反加一)
CMP 比较指令
CMP: Compare
指令格式:CMP 目的, 源
指令功能:目的 - 源
实际上是做减法,但是结果不送到目的,只改变标志位
(一般紧跟条件转移指令实现跳转)
乘法指令
MUL 无符号数乘法指令
指令格式: MUL 源
指令功能:把源操作数和累加器(Accumulater)中的数,都当成无符号数,然后将两数相乘
注意:
- 其中有一个操作数一定是累加器
- **如果源操作数是一个字节,那么AX
AX*源** - **如果源操作数是一个字,那么(DX,AX)
AX*源** - 源操作数可以是寄存器或存储单元,不能是立即数
- 源操作数是存储单元时,应使用PTR说明是字节还是字
- MUL指令执行后影响CF和OF标志
- 如果结果的高半部分不为0,则CF、OF均置1。否则CF、OF清零
- 通过测试这两个标志,可以检测并去除结果中的无效前导零
IMUL 有符号数乘法指令
指令格式:IMUL 源
指令功能:把源操作数和累加器中的数,都作为带符号数进行相乘
存放结果的方式与MUL相同,最后给乘积赋予正确的符号
指令结束后,如果乘积的高半部分不是全0或者全1,则置CF=1,OF=1.若结果高半部分为全0或者全1,则使CF=0,OF=0. 这样来决定是否需要保存积的高半部分
为什么有MUL和IMUL?
指令不知道是有符号数还是无符号数,需要程序员赋予其意义
除法指令
DIV 无符号数除法指令
指令格式: DIV 源
指令功能:对两个无符号二进制数进行除法操作。
如果源操作数是字节,被除数必须放在AX中,并且:
- AL
AX/源(字节)的商 - AH
AX/源(字节)的余数 - 要是被除数只有8位,必须将其放在AL中,并将AH清零,然后相除
如果源操作数是字,被除数必须放在DX和AX中,并且:
- AX
(DX,AX)/源(字)的商 - DX
(DX,AX)/源(字)的余数
要是被除数只有16位,除数也是16位,则必须将16位被除数送入AX中,再将DX清零,然后相除、
与被除数和除数一样,商和余数都是无符号数
IDIV 有符号数除法指令
指令格式:IDIV 源
指令功能:功能与DIV相同,但操作数都必须是带符号数,商和余数也是带符号数,而且规定余数的符号和被除数的符号相同
进行除法时,如果商超过了目标寄存器AL或AX所能存放的数的范围,计算机会自动产生除法错中断,相当于执行了除数为0的运算,得到的商和余数都不确定
对于带符号数的除法指令,字节操作时要求被除数为16位,字操作时要求被除数为32位,如果不能满足这个条件时,不能简单将高位置0/1,而应应该用符号扩展指令,再执行除法指令
CBW 把字节转换为字指令
CBW: Convert Byte to Word
指令格式:CBW
指令功能:把AL中的字节的符号位扩充到AH的所有位,这是AH被称为是AL的符号扩充
CBW不影响标志位
CWD 把字转换为双字指令
CWD: Convert Word to Double Word
指令格式:CWD
指令功能:把AX中字的符号位扩充到DX寄存器的所有位中去