写在前面:本文是承接上一篇 而作的,主要探讨常用的算术运算指令
二、算术运算指令
大多对标志位影响,对操作数的要求与MOV 一样
2.1 加法指令
【1】ADD 目标操作数 OPRD1, 源操作数 OPRD2
将两个数相加的结果赋值给目标操作数 OPRD1。(注意:由于 ADD 指令是不考虑低位向高位的进位的,因此,ADD指令多用于两个8位二进制数的相加)
【2】ADC OPRD1, OPRD2
ADC考虑了低位向高位的进位,它执行的操作是:OPRD1 + OPRD2 + CF,并且将结果赋值给目标操作数OPRD1。但是特别注意:使用 ADC 之前记得将 CF 的状态清零(CLC指令)
ADC指令常常用于多字节数的相加
【3】INC OPRD
INC 指令类似于我们 C++ 里面的自增操作,它执行的是 OPRD + 1,并将结果赋给 OPRD。
注意:INC 指令是单操作数指令,它的操作数不能是段寄存器!!,常常用于修改地址指针
2.2 减法指令
【1】SUB OPRD1, OPRD2
这个 SUB 指令对应于 ADD 指令,也是不考虑低位向高位的借位的。因此它也只适用于两个字节数的减法
【2】考虑借位的SBB
【3】DEC OPRD
对应于 INC ,这里完成的是 OPRD 的自减操作。同样,操作数不能是段寄存器!
【4】NEG OPRD
这里 NEG 执行的是用 0 去减操作数:0 - OPRD,结果再赋给OPRD。NEG 指令常常用于求补码
一般,NEG指令执行后会使CF=1,除非OPRD=0,这样 CF 就是0
【5】CMP OPRD1, OPRD2
这个CMP指令执行的是 :OPRD1 - OPRD2。但是大家注意:仅仅是减而已,CMP 将会把结果丢弃
OPRD1-OPRD2 减完了结果不要,只是为了影响标志位,两个操作数不影响。
CMP 最大的作用是用于比较两个操作数的大小,但是比大小也分为 无符号数的比较和有符号数的比较
- 如果 AX, BX 是无符号数,那么对于 CMP AX, BX 如果 AX ≥ BX,那么 CF = 0;如果 AX < BX,那么,CF = 1。进一步讲:如果 AX == BX ,那么,我们这时无法通过CF 确定,需要看 ZF(当相减结果为0时,ZF = 1)
- 对于有符号数 AX, BX的比较:CMP AX, BX 两个数的大小由 OF、SF共同决定:如果 OF, SF 一样,那么 AX ≥ BX;如果 OF, SF 不一样,那么 AX < BX
2.3 乘法指令
有分别针对无符号数和有符号数的运算指令,之前是靠我们自己的
乘法指令中,结果的长度是操作数长度的2倍。也就是说如果是两个单字节数相乘,结果就是16位的;如果是两个16位数相乘,结果就是 32 位的。
【1】无符号数指令MUL:MUL OPRD
注意:
- 不能是立即数
- 如果 OPRD 是8位的 ,那么隐含的操作数应该在 AL 里面,执行 ALx OPRD->AX
- 如果 OPRD 是16位的,那么隐含操作数在 AX 里面,则执行AXxOPRD->DX AX(注意,因为结果是32位的,所以需要用上 DX,高 16 位存在 DX里面,低16位存在 AX 里面)
【2】IMUL OPRD
关于对操作数的一些要求和 MUL 一样。IMUL 的执行过程是:
- 将两个操作数取补码;
- 做乘法运算
- 将乘积取补码
2.4 除法指令
要求被除数一定是除数的双倍字长
如果是 OPRD 字节数,执行 AX/OPRD(即被除数事先存放在 AX 里面)
如果操作数是双字节数:DX AX/OPRD(即被除数是 32 位的,高 16 位存放在 DX 里面,低 16 位存放在 AX 里面)
【1】 DIV(无符号数除法)
【2】IDIV(有符号数除法)
注意:这里再声明一下,对于 OPRD 是字节的,被除数在 AX 里面,结果的商在 AL 里面,余数在 AH 里面;
对于 OPRD 是字的,被除数 32 位,高 16 位在DX,低 16 位在AX ,商在 AX 里面,余数在 DX 里面。如果商超过了寄存器的容量,产生 0 型中断