8086/8088指令系统
补充内容:标志寄存器FLAG
CF:进位标志位
PF:奇偶标志位
AF:辅助进位标志位
ZF:零标志位
SF:符号标志位
OF:溢出标志位
TF:跟踪(陷阱)标志位,如果为1,则CPU处于单步工作方式。
IF:中断允许标志位,如果为1,屏蔽中断的控制标志位。
DF:方向标志位,如果为1,则操作的地址自动递减,否则递增。
1. 8086/8088指令寻址方式
1.1操作数的种类
1. 数据操作数是与数据有关的操作数,即指令操作的**对象是数据**。
2. 对于数据操作数,有的指令有两个操作数,一个称为源操作数,在操作过程中,其值不发生改变;另一个称为目的操作数,操作后一般被操作结果所代替。
(1)立即数操作数:要操作的数据包含在指令中。
(2)寄存器操作数:要操作的数据存放在指定的寄存器中。
(3)存储器操作数:要操作的数据存放在存储单元中。
(4)I/O操作数:要操作的数据来自或送到I/O端口。
1. 地址操作数是与程序转移地址有关的操作数,即指令中的操作对象不是数据,而是**要转移的目标地址**。它也分为**立即数操作数**、**寄存器操作数**和**存储器操作数**,即要转移的目标地址包含在**指令中**,或者**寄存器**,或者**存储单元**中。
2. 对于地址操作数,指令只有**一个目的操作数**,它是一个提供程序转移的**目标地址**。
1.2 寻址方式
1.2.1立即数寻址方式
立即数寻址方式又分为立即数寻址方式、寄存器寻址方式、存储器寻址方式和IO端口寻址方式四种类型。
1. 立即数寻址方式(immediate addressing)
MOV BL,80H
MOV AX,1090H
2. 寄存器寻址方式(register addressing)
MOV CL,DL
MOV AX,BX
3. 存储器寻址方式(memory addressing)
(1) 直接寻址方式:MOV AL,[10H],数据段寄存器(DS)= 2000H,物理存储单元地址:2000H × 10H + 10H = 210H,将该地址内的数据存放到AL寄存器中。
(2)寄存器间接寻址方式:MOV AX,[SI],根据物理存储地址,将其值赋值为AX寄存器。
(3)寄存器相对寻址方式:MOV AL,[BP + TABLE],TABLE是一个8位或16位的位移量。
(4)基址变址寻址方式:MOV AH,[BP][SI],根据基址寄存器BP、变址寄存器SI运算的和,将其内容赋值到AH寄存器中。
(5)基址变址相对寻址方式:MOV AX,[BX + SI + COUNT],COUNT表示8位或16位常量。
4. IO端口寻址方式
(1)IO端口直接寻址方式:IN AL,21H。从地址为21H的端口读取数据送到AL中。
(2)IO端口间接寻址方式:OUT DX,AX。将AX的内容送到由DX寄存器内容所指定的端口号中。
(7)
1.2.2 地址寻址方式
- 段内直接寻址方式
- 段内间接寻址方式
- 段间直接寻址方式
- 段间间接寻址方式
2. 8086/8088指令系统
8086/8088的指令系统可以分为六种类型
- 数据传送指令;
- 算术运算指令;
- 位操作指令;
- 串操作指令;
- 程序控制指令;
- 处理器控制指令;
2.1 数据传送指令
2.1.1通用数据传送指令
MOV dst, src
PUSH src
POP dst
XCHG dst, src
XLAT src_table
2.1.2输入输出指令
IN acc, port
IN acc, DX
OUT port, acc //将AL或AX的8位/16位数据输出到指定的I/O端口,端口地址不大于FFH
OUT DX, acc
2.1.3目的地址传送指令
- 取有效地址指令LEA(load effective address)
LEA reg16, mem //将一个近地址指针写入指定的寄存器中。目的操作数必须为16位通用寄存器
LEA BX, BUFFER
MOV BX, BUFFER
//LEA是将BUFFER的偏移地址赋值给BX,而MOV是将BUFFER的值赋值给BX,LEA等同于下面的操作
MOV BX, OFFSET BUFFER //OFFSET BUFFER表示存储器地址的偏移地址
- 地址指针装入DS指令LDS(load pointer into DS)
LDS reg16, mem32 //LDS用于传送一个32位的远地址指针,包括一个偏移地址和一个段地址。偏移地址送入reg16的目的寄存器,段地址送入数据段寄存器DS。
- 地址指针装入ES指令(load pointer into ES)
LES reg16, mem32
2.1.4标志传送指令
8086/8088 CPU有一标志寄存器FLAG,其中6个状态标志位和3个控制位。
- 取标志指令LAHF(load AH from Flags)
LAHF
- 置标志指令SAHF(store AH into Flags)
SAHF
- 标志压入堆栈指令PUSHF(PUSH Flags onto stack)
PUSHF
- 标志弹出堆栈指令POPF(POP Flags off stack)
POPF
2.2 算术运算指令
2.2.1二进制数运算指令
- 不带进位加法指令
ADD dst, src //将源操作数和目的操作数相加然后赋值给dst目的操作数
- 带进位加法指令ADC
ADC dst, src //将源操作数和目的操作数相加,再加上进位标志CF的内容,赋值给目的操作数。
- 加1指令
INC dst //将目的操作数+1赋值给目的操作数。
- 不带借位减法指令
SUB dst, src //将目的操作数减源操作数,结果赋值给目的操作数。
- 带借位的减法指令
SBB dst, src //将目的操作数减源操作数,然后在减进位标志CF,结果赋值给目的操作数。
- 减1指令
DEC dst //将目的操作数减1,然后赋值给操作数。
- 求补指令
NEG dst //用“0” - dst,结果赋值给目的操作数。
- 比较指令CMP
CMP dst, src //用dst减src,结果影响标志位,不影响dst和src。
- 无符号乘法
MUL src //MUL指令的另一个操作数在累加器(8位AL,16位AX)中,是隐含的。
- 带符号的乘法指令IMUL
IMUL src //IMUL操作与MUL操作类似,只是src表示的范围是带符号的。
- 无符号数除法指令DIV
DIV src //字节除法中,AX除以src,被除数16位,除数8位,商在AL,余数在AH中。字除法,DX:AX除以src,被除数32位,除数为16位。商在AX,余数在DX中。
- 带符号除法指令IDIV
IDIV src //如果除数为0,会发生类型为0的终端。
- 符号扩展指令
字节扩展指令CBW:将一个字节(8位)按其符号扩展为字(16位)。它隐含的操作数为寄存器AL和AH。
字扩展指令CWD:将一个字(16位)按其符号位扩展为双字(32位)。它隐含的操作数为寄存器AX和DX。
2.3 位操作指令
2.3.1 逻辑运算指令
AND dst, src
TEST dst, src
OR dst, src
OR指令和AND指令:如果将一个寄存器和本身进行运算,不改变寄存器的值,只影响状态标志位。
经常用寄存器与自身按位与AND或者按位或OR,根据状态标志位来判断数据是否为0,用CMP指令虽然能达到同样的效果,但是指令字节较多,执行速度慢。
XOR dst, src
XOR指令的一个用途是:将寄存器或存储器某些特定的位”求反“,使其余位不变。**求反的位与”1“异或,不变的位与”0“异或。
NOT dst
2.3.2 移位指令
SHL dst, 1/CL
SAL dst, 1/CL
SHL和SAL操作完全相同,左移一次可以实现dst乘以2操作。
SHR dst, 1/CL
SAR dst, 1/CL
2.3.3 循环移位指令
ROL dst, 1/CL
ROR dst, 1/CL
RCL dst, 1/CL
RCR dst, 1/CL
2.4 串操作指令
MOVS dst_string, src_string
MOVSB
MOVSW
例子: SI和DI分贝是源变址寄存器和目的变址寄存器
LEA SI, BUFFER1 ;源串首地址指针
LEA DI, BUFFER2 ;目的串首地址指针
MOV CX, 200 ;字符串长度
CLD ;清除方向标志DF
REP MOVSB ;传送200字节 REP是重复前缀
HLT ;停止
LODS src_string
LODSB
LODSW
STOS dst_string
STOSB
STOSW
例子:将字符”#“装入以AREA为首地址的100个字节中
LEA DI, AREA
MOV AX, '##'
MOV CX, 50
CLD
REP STOSW
HTL
SCAS dst_string
SCASB
SCASW
2.5 控制转移指令
2.5.1 转移指令
- 段内直接转移
JMP near_label //代码段寄存器CS的内容不变,JMP指令计算出下一条指令的地址到目标地址之间的16位相对位移量disp,disp可正可负。范围-32768 - 32767
- 段内直接短转移
JMP short_label //相对位移量disp的范围为-128 - 127,属于短标号。
- 段内间接转移
JMP reg16/mem16 //用指定的寄存器或存储器的内容取代当前IP的值,以实现程序的转移。
- 段间直接转移
JMP far_label //操作数是一个远标号,该标号在另一个代码段内。IP和CS内容会被该代码段标号信息取代。
- 段间间接转移
JMP mem32 //将存储器的前两个字节赋值给IP,后两个字节赋值给CS。
Jcc short_babel //”cc“表示条件,首先测试规定条件,如果满足则跳转到目标地址,否则,继续执行。条件可以是无符号位的高 | 低(Above | Below),带符号数的大 | 小(Great | Less)等等。
2.5.2 循环控制指令
LOOP short_label
LOOPE short_label
LOOPZ short_label
LOOPNE short_label
LOOPNE short_label
2.5.3 过程调用与返回指令
- 段内直接调用
CALL near_proc
- 段内间接调用
CALL reg16/mem16
- 段间直接调用
CALL far_proc
- 段间间接调用
CALL mem32
- 过程返回指令RET
一般将堆栈之前保存的断点值弹出,程序返回原来调用的地方。RET允许带一个弹出只(pop_value),范围是0 - K大小,表示返回时从堆栈舍弃的字节数大小。
2.6 处理器控制指令
CLC:清进位标志
STC:置进位标志
CMC:对进位标志求反
CLD:清方向标志
STD:置方向标志
CLI:清中断允许位标志
STI:置中断允许标志
- HLT //使CPU进入暂停状态
- WAIT //使CPU进入等待状态
- ESC //ESC ext_op, src 使其他处理器使用8086的寻址方式,并取得指令。
- LOCK //使CPU总线锁定低电平有效,直到执行完下一条指令。
- 空操作指令NOP
NOP指令不进行任何操作,但是会占用3个时钟周期。