0%

第二章_8086的指令系统

所有指令都有1个共同特点,就是如果有2个操作数的话,两个操作数不能同时在内存

数据传送类指令

数据传送指令都不影响标志位

通用数据传送指令

传送指令MOV

定义:

  1. 把一个字节或字的操作数从源地址传送至目的地址
  2. MOV不影响标志位

举例:

例1:立即数传送

  • mov al,4 ;al←4,字节传送,是一条将立即数4(十进制)移动到寄存器AL(即8位的累加器)的指令
  • mov cx,0ffh ;cx←00ffh,字传送,传送前要根据高位补齐一条将立即数0xFF(十六进制)移动到寄存器CX(即16位的计数器)的指令
  • mov si,200h ;si←0200h,字传送
  • mov byte ptr [si],0ah ;byte ptr 说明是字节操作,将立即数0x0A(十六进制)移动到以SI寄存器作为基址的内存位置。这里的byte ptr指定了操作数的大小为一个字节,[si]表示SI寄存器中的地址处。因此,这条指令将0x0A写入到SI寄存器指向的内存地址中。
  • mov word ptr [si+2],0bh ;word ptr 说明是字操作

注: 注意立即数是字节量还是字量,明确指令是字节操作还是字操作

例2:寄存器传送

mov ax,bx ;ax←bx,字传送 mov ah,al ;ah←al,字节传送 mov ds,ax ;ds←ax,字传送 mov [bx],al ;[bx]←al,字节传送

例3:存储器传送

mov al,[bx] mov dx,[bp] ;dx←ss:[bp] mov es,[si] ;es←ds:[si]

不存在存储器向存储器的传送指令

小结

非法传送

  • 两个操作数的类型不一致 例如源操作数是字节,而目的操作数是字;或相反

    常见错误:对于存储器单元与立即数同时作为操作数的情况,必须显式指明;byte ptr指示字节类型,word ptr指示字类型

    就是想MOV word ptr[ax] 000AH

  • 两个操作数不能都是存储器 传送指令很灵活,但主存之间的直接传送却不允许

  • 段寄存器的操作有一些限制 段寄存器属专用寄存器,对他们的操作能力有限

    1. 不允许立即数传送给段寄存器 MOV DS,100H ;非法指令:立即数不能传送段寄存器
    2. 不允许直接改变CS值 MOV CS,[SI] ;不允许使用的指令
    3. 不允许段寄存器之间的直接数据传送 MOV DS,ES ;非法指令:不允许段寄存器间传送

交换指令XCHG

XCHG不影响标志位

寄存器与寄存器之间对换数据

mov ax,1234h ;ax=1234h mov bx,5678h ;bx=5678h xchg ax,bx ;ax=5678h,bx=1234h xchg ah,al ;ax=7856h

寄存器与存储器之间对换数据

xchg ax,[2000h] ;字交换 等同于 xchg [2000h],ax xchg al,[2000h] ;字节交换 等同于 xchg [2000h],al

不能在存储器与存储器之间对换数据

换码指令XLAT

定义

  1. 将BX指定的缓冲区中、AL指定的位移处的一个字节数据取出赋给AL
  2. XLAT不影响标志位

堆栈操作指令

SS指向的基准量,SP指向的是“偏移量”,计算SP指向的物理地址需要加上SS* 10H

堆栈的操作

PUSH ;进栈指令先使堆栈指针SP减2,然后把一个字操作数存入堆栈顶部

【例】 PUSH BX 指令执行前: SS=4000H,SP=2000H,BX=3248H

POP ;出栈指令把栈顶的一个字传送至指定的目的操作数,然后堆栈指针SP加2

  • 堆栈操作的单位是字,进栈和出栈只对字量
  • 字量数据从栈顶压入和弹出时,都是低地址字节送低字节,高地址字节送高字节
  • 堆栈操作遵循先进后出原则,但可用存储器寻址方式随机存取堆栈中的数据
  • 堆栈常用来
    1. 临时存放数据
    2. 传递参数
    3. 保存和恢复寄存器

标志传送指令

定义

  • 标志寄存器传送指令用来传送标志寄存器FLAGS的内容
  • 标志位操作指令直接对CF、DF、IF标志进行复位或置位

标志寄存器传送

标志低字节进出AH指令

1
LAHF	;AH←FLAGS的低字节

LAHF指令将标志寄存器的低字节送寄存器AH SF/ZF/AF/PF/CF状态标志位分别送入AH的第7/6/4/2/0位,而AH的第5/3/1位任意

1
SAHF	;FLAGS的低字节←AH

SAHF将AH寄存器内容送FLAGS的低字节 用AH的第7/6/4/2/0位相应设置SF/ZF/AF/ PF/CF标志

标志寄存器进出堆栈指令

1
2
PUSHF	 ;SP←SP-2
;SS:[SP]←FLAGS

PUSHF指令将标志寄存器的内容压入堆栈,同时栈顶指针SP减2

1
2
3
POPF
;FLAGS←SS:[SP]
;SP←SP+2

POPF指令将栈顶字单元内容送标志寄存器,同时栈顶指针SP加2

举例

1
2
3
4
5
6
7
pushf	;保存全部标志到堆栈
pop ax ;堆栈中取出全部标志
or ax,0100h ;设置D8=TF=1,
;ax其他位不变
push ax ;将ax压入堆栈
popf ;FLAGS←AX
;将堆栈内容取到标志寄存器

标志位操作

进位标志操作指令

用于任意设置进位标志

CLC(Clear Carry Flag) ;复位进位标志:CF←0

STC(Set Carry Flag) ;置位进位标志:CF←1

CMC(Complement Carry Flag) ;求反进位标志:CF←~CF

方向标志操作指令

串操作指令中,需要使用

CLD ;复位方向标志:DF←0

STD ;置位方向标志:DF←1

中断标志操作指令

在编写中断服务程序时,需要控制可屏蔽中断的允许和禁止 CLI ;复位中断标志:DF←0 STI ;置位中断标志:DF←1

地址传送指令

定义:

  1. 地址传送指令将存储器单元的逻辑地址送至指定的寄存器
    • 有效地址传送指令 LEA
    • 指针传送指令 LDS和LES
  2. 注意不是获取存储器单元的内容

有效地址传送指令LEA(load EA)

定义:

将存储器操作数的有效地址传送至指定的16位寄存器中

举例:

1
2
3
4
mov bx,0400h
mov si,3ch
lea bx,[bx+si+0f62h]
;BX=0400h+003ch+0f62h=139EH

  • 获得主存单元的有效地址;不是物理地址,也不是该单元的内容
  • 可以实现计算功能

LDS

格式

1
2
3
LDS r16,mem
;r16←mem
;DS←mem+2

LDS指令将主存中mem指定的字送至r16,并将mem的下一个字,地址就是在MEM基础上加2送DS寄存器

1
2
3
4
5
比如
ADR DW 1234H, 5678H
LDS BX, ADR
;BX <- [ADR] BX = 1234H
;DS <- [ADR + 2] DS = 5678H

LES

格式

1
2
3
LES r16,mem
; r16←mem
; ES←mem+2

LES指令将主存中mem指定的字送至r16,并将mem的下一字送ES寄存器

算术运算类指令

状态标志

常用状态标志: 进位标志CF、溢出标志OF 零位标志ZF、符号标志SF 奇偶标志PF

进位标志CF(Carry Flag)

定义:

当运算结果的最高有效位有进位(加法)或借位(减法)时,进位标志置1,即CF = 1;否则CF = 0。

注:最高有效位不一定非要是16位寄存器AX等的最高位

举例:

1
2
3AH + 7CH=B6H	;没有进位:CF = 0
AAH + 7CH=(1)26H ;有进位:CF = 1

溢出标志OF(Overflow Flag)

若算术运算的结果有溢出,则OF=1; 否则 OF=0

溢出和进位的区别

首先什么是溢出

处理器内部以补码表示有符号数 8位表示的整数范围是:-128~+127 16位表示的整数范围是:-32768~+32767 如果运算结果超出这个范围,就产生了溢出 有溢出,说明有符号数的运算结果不正确

举例:

3AH+7CH=B6H,就是58+124=182, 已经超出-128~+127范围,产生溢出,故OF=1; 另一方面,补码B6H表达真值是-74, 显然运算结果也不正确

本质区别

进位标志表示无符号数运算结果是否超出范围,超出范围后加上进位或借位运算结果仍然正确; 溢出标志表示有符号数运算结果是否超出范围,超出范围后运算结果不正确。

溢出和进位的对比

举例:

例1:3AH + 7CH=B6H 无符号数运算: 58+124=182 范围内,无进位 有符号数运算: 58+124=182 范围外,有溢出

用二进制运算表示

例2:AAH + 7CH=(1)26H 无符号数运算: 170+124=294 范围外,有进位 有符号数运算: -86+124=38 范围内,无溢出

二进制表示

如何运用溢出和进位

如果将参加运算的操作数认为是无符号数,就应该关心进位;

认为是有符号数,则要注意是否溢出

溢出的判断

当两个相同符号数相加(包括不同符号数相减),而运算结果的符号与原数据符号相反时,产生溢出

零标志ZF(Zero Flag)

若运算结果为0,则ZF = 1; 否则ZF = 0

符号标志SF(Sign Flag)

运算结果最高位为1,则SF = 1;否则SF = 0

奇偶标志PF(Parity Flag)

当运算结果最低字节中“1”的个数为零或偶数时,PF = 1;否则PF = 0

辅助进位标志AF(Auxiliary Carry Flag)

运算时第3位(低半字节)有进位或借位时,AF = 1;否则AF = 0。

加法

加法指令ADD

定义:

ADD指令将源与目的操作数相加,结果送到目的操作数

举例:

1
2
3
4
5
6
mov al,0fbh	;al=0fbh
add al,07h ;00FB + 0007 = 0102H, AL = 02H
mov word ptr [200h],4652h ;[200h]=4652h(重复就是重要,涉及到内存的时候必须要告知是wordptr还是byteptr)
mov bx,1feh ;bx=1feh
add al,bl ;al=00h
add word ptr [bx+2],0f0f0h ;[200h]=3742h

带进位加法指令ADC

定义:

  • ADC指令将源与目的操作数相加,再加上进位CF标志,结果送到目的操作数

  • ADC指令主要与ADD配合,实现多精度加法运算

1
2
3
4
5
6
7
mov ax,4652h	;ax=4652h
add ax,0f0f0h ;ax=3742h,CF=1
mov dx,0234h ;dx=0234h
adc dx,0f0f0h ;dx=f324h,CF=0
;DX.AX= 0234 4652H
+F0F0 F0F0H
=F325 3742H

增量指令INC(increment)

  1. INC指令对操作数加1(增量)
  2. INC指令不影响进位CF标志,按定义设置其他状态标志

减法

减法指令SUB(subtract)

定义:

SUB指令将目的操作数减去源操作数,结果送到目的操作数

1
2
3
4
5
6
7
mov al,0fbh	;al=0fbh
sub al,07h ;al=0f4h,CF=0
mov word ptr [200h],4652h ;[200h]=4652h
mov bx,1feh ;bx=1feh
sub al,bl ;al=0f6h
sub word ptr [bx+2],0f0f0h
;[200h]=5562h,CF=1

带借位减法指令SBB

1
2
3
4
5
6
7
mov ax,4652h	;ax=4652h
sub ax,0f0f0h ;ax=5562h,CF=1
mov dx,0234h ;dx=0234h
sbb dx,0f0f0h ;dx=1143h,CF=1
;DX.AX= 0234 4652H
-F0F0 F0F0H
=1143 5562H

减量指令DEC(decrement)

定义

  • DEC指令对操作数减1(减量)
  • DEC指令不影响进位CF标志,按定义设置其他状态标志

求补指令NEG(negative)

定义:

  • NEG指令对操作数执行求补运算:用零减去操作数,然后结果返回操作数

  • 求补运算也可以表达成:将操作数按位取反后加1

  • NEG指令对标志的影响与用零作减法的SUB指令一样

    NEG对CF和OF的影响

    根本原因:虽然人在计算的时候是求反加1,但CPU运算是用0-操作数

1
2
3
4
5
6
mov ax,0ff64h
neg al ;ax=ff9ch,OF=0、SF=1、ZF=0、PF=1、CF=1
sub al,9dh ;ax=ffffh,OF=0、SF=1、ZF=0、PF=1、CF=1
neg ax ;ax=0001h,OF=0、SF=0、ZF=0、PF=0、CF=1
dec al ;ax=0000h,OF=0、SF=0、ZF=1、PF=1、CF=1
neg ax ;ax=0000h,OF=0、SF=0、ZF=1、PF=1、CF=0

比较指令CMP(compare)

  1. CMP指令将目的操作数减去源操作数,按照定义相应设置状态标志
  2. CMP指令执行的功能与SUB指令相同,但结果不回送目的操作数
1
2
3
4
5
	cmp al,100	;al-100
jb below ;al<100,跳转到below执行
sub al,100 ;al≥100,al←al-100
inc ah ;ah←ah+1
below: ...

经典例题

题1:

【例】: 设X、Y、Z均为双精度数。其存放地址为:X,X+2,Y,Y+2,Z,Z+2。存放时,高位字在高位地址,低位字存放在低地址中。 试编程完成 W←X+Y+24-Z ,结果存放在W和W+2单元。

总结

1. 用DX、AX表示双精度数

2. 低位用AX,高位用DX

3. 先用非进位运算低位,再用进位运算高位

1
2
3
4
5
6
7
8
9
10
MOV   AX,X       ;用DX,AX来表示双精度数
MOV DX,X+2 ;低位用AX,高位用DX
ADD AX,Y ;先低位运算
ADC DX,Y+2 ;完成X+Y
ADD AX,24 ;低位运算
ADC DX,0 ;高位运算,该语句不能少
SUB AX,Z ;先低位减法
SBB DX,Z+2 ;完成运算
MOV W,AX ;存储结果
MOV W+2,DX

乘法指令(MUL/IMUL)

  1. 乘法指令的源操作数显式给出,隐含使用另一个操作数AX和DX

    • 字节量相乘:AL与r8/m8相乘,得到16位的结果,存入AX
    • 字量相乘:AX与r16/m16相乘,得到32位的结果,其高字存入DX,低字存入AX
  2. 乘法指令如下影响OF和CF标志

    • MUL指令——若乘积的高一半(AH或DX)为0,则OF=CF=0;否则OF=CF=1

      解释:

      1. OF = 1表示溢出,因为原来是8(或者16位),高一半不为0说明现在的乘积超过8位(或者16位)。原来是8位现在就是16位,原来是16位现在就是32位

      2. CF = 1表示进位,因为原来是8位(或者16位),高一半不为0说明原来的8位(或者16位)的有效位的最高位发生进位

    • IMUL指令——若乘积的高一半是低一半的符号扩展,则OF=CF=0;否则均为1

举例:

1
2
3
4
5
6
7
8
mov al,0b4h	;al=b4h=180
mov bl,11h ;bl=11h=17
mul bl ;ax=Obf4h=3060
;OF=CF=1,AX高8位不为0
mov al,0b4h ;al=b4h=-76
mov bl,11h ;bl=11h=17
imul bl ;ax=faf4h=-1292
;OF=CF=1,AX高8位含有效数字

除法指令(DIV/IDIV)

  1. 除法指令的除数显式给出,隐含使用另一个操作数AX和DX作为被除数

    • 字节量除法:AX除以r8/m8,8位商存入AL,8位余数存入AH

    • 字量除法:DX.AX除以r16/m16,16位商存入AX,16位余数存入DX

  2. 被除数位数至少是除数1倍

  3. 被除数远大于除数时,所得的商就有可能超出它所能表达的范围。如果存放商的寄存器AL/AX不能表达

    便产生溢出,8086CPU中就产生编号为0的内部中断——除法错中断

    • 对DIV指令,除数为0,或者在字除时商超过8位,或者在字除时商超过16位
    • 对IDIV指令,除数为0,或者在字节除时商不在-128~127范围内,或者在字除时商不在-32768~32767范围内

举例

1
2
3
4
5
6
7
8
mov ax,0400h	;ax=400h=1024
mov bl,0b4h ;bl=b4h=180
div bl ;商al=05h=5
;余数ah=7ch=124
mov ax,0400h ;ax=400h=1024
mov bl,0b4h ;bl=b4h=-76
idiv bl ;商al=f3h=-13
;余数ah=24h=36

对进位标志CF的影响

  • 会修改CF
    1. ADD/ADC
    2. SUB/SBB
  • 不会修改CF
    1. INC
    2. DEC
  • 不确定
    1. MUC/IMUL
    2. DIV/IDIV

符号扩展指令(CBW/CWD)

定义:

符号扩展是指用一个操作数的符号位(即最高位)形成另一个操作数,后一个操作数的各位是全0(正数)或全1(负数)。符号扩展不改变数据大小

种类:

1
2
3
4
5
6
7
CBW		;AL的符号扩展至AH
;如AL的最高有效位是0,则AH=00
;AL的最高有效位为1,则AH=FFH。AL不变

CWD ;AX的符号扩展至DX
;如AX的最高有效位是0,则DX=00
;AX的最高有效位为1,则DX=FFFFH。AX不变

举例:

1
2
3
4
mov al,80h	;al=80h
cbw ;ax=ff80h
add al,255 ;al=7fh
cbw ;ax=007fh

典型例题:指令的综合运用

【例】:综合运算举例。计算: (V-(X*Y+Z-540))/X 其中X、Y、Z、V均为16位带符号数,已分别装入X、Y、Z、V单元中,要求计算结果把商存入AX,余数存入DX。

十进制算术运算指令

十进制数的运算步骤: 1.对BCD码进行二进制运算 2.用十进制调整指令进行调整

压缩的BCD码调整指令(无操作数,默认对放在AL的数据操作)

常用来处理数字,所以D:decimal,A:adjust,A表示加法add,S表示减法sub

BCD码的运算逻辑还是十进制,只不过是用二进制表示

DAA(加法)

解释:为什么第②点是加60H:因为只要当前位表示的数大于等于10都要加6,但是当AL中高四位超过时,直接加6会误解,所以就要加60H,6分配给高4位,0分配给低4位。如果高低一起超过就加66H

DAS(减法)

就是将上面加法中减换成加

小结:就是看每个半字是否有进位或者借位,对于低半字就是看AF和低半字是否大于等于10,对于高半字就是看CF和高半字是否大于等于10

非压缩的BCD码调整指令

常用来处理字符,所以A:表示ASCII码,A表示调整adjust,其他就是加(ADD)减(sub)乘(mul)除(div)

压缩的BCD码就是通常的8421码,非压缩的BCD码是用8个二进制位表示一个十进制位

AAA(加法)

注:AAA调整的时候一定还要根据AF判断是否调整的原因如下:

AAS(减法)

就是将上图加1改成减1,加6改成减6

小结:无论是压缩还是非压缩的BCD码的加减调整就是看低位有没有向高位进位和借位

AAM(乘法)

二进制乘法的结果调整成十进制非压缩的形式所以跟在乘法操作后面

举例:

视频讲解

AAD(除法)

先将十进制表示的被除数调整成二进制形式,再做除法,所以放在除法前面

举例:

视频讲解

位操作类指令

位操作指令都是将CF和OF设置为0,因为位操作不会产生进位,不会溢出

逻辑与指令AND

AND指令设置CF = OF = 0,根据结果设置SF、ZF和PF状态,而对AF未定义

逻辑或指令OR

OR指令设置CF = OF = 0,根据结果设置SF、ZF和PF状态,而对AF未定义

逻辑异或指令XOR

与0异或不变,与1异或得相反数

XOR指令设置CF = OF = 0,根据结果设置SF、ZF和PF状态,而对AF未定义

逻辑非指令NOT

NOT指令是一个单操作数指令 NOT指令不影响标志位

测试指令TEST

  1. 对两个操作数执行逻辑与运算,结果不回送到目的操作数
  2. TEST指令设置CF = OF = 0,根据结果设置SF、ZF和PF状态,而对AF未定义

移位指令(shift)

逻辑左移(SHL)

SHL reg/mem,1/CL ;逻辑左移,最高位进入CF,最低位补0

算术左移(SAL)

SAL reg/mem,1/CL ;算术左移,最高位进入CF,最低位补0

注:逻辑左移和算术左移没什么区别

逻辑右移(SHR)

SHR reg/mem,1/CL ;逻辑右移,最低位进入CF,最高位补0

举例

算术右移(SAR)

SAR reg/mem,1/CL ;算术右移,最低位进入CF,补符号位

举例

算术左移和算术右移主要用来进行有符号数的倍增、减半;

逻辑左移和逻辑右移主要用来进行无符号数的倍增、减半。

注:移位指令的第一个操作数是指定的被移位的操作数,可以是寄存器或存储单元 后一个操作数表示移位位数,该操作数为1,表示移动一位;当移位位数大于1时,用且只能用CL寄存器值表示,该操作数表达为CL

循环移位指令(rotate)

ROL reg/mem,1/CL ;不带进位循环左移

ROR reg/mem,1/CL ;不带进位循环右移

RCL reg/mem,1/CL ;带进位循环左移

RCR reg/mem,1/CL ;带进位循环右移

带进位和不带进位的区别:

比如不带进位的左移,是将最高位移动到CF里

带进位的左移,是将CF和要移动的8位合起来看做一个整体一起移动

带进位一般用来处理多精度数的移动

举例:

题1:高精度移位

视频讲解

题2:BCD码合并

控制转移类指令

非条件转移

段内寻址

相对寻址

1
JMP LABEL

效果就是将当前IP指针加上LABEL表示的位移量

间接寻址

1
JMP R16/M16

注:R16表示16进制寄存器,M16表示16进制内存

效果就是将IP修改为R16/M16中内容

段间寻址

直接寻址

1
JMP FAR PTR LABEL

效果是将IP修改为LABEL的偏移地址,CS修改为LABEL的段地址

间接寻址

1
JMP FAR PTR MEM

效果就是将IP修改为MEM的低2位字节[MEM],将CS修改为LABEL的高2位字节[MEM+2](所以MEM是四个字节)

注:段间间接寻址只能用内存,如果是寄存器的话是寄存器中保存的是对应内存中的地址,举例如下

1
2
3
4
MOV WORD PTR [BX], 0
MOV WORD PTR [BX + 2], 1500H
JMP FAR PTR [BX]
; 转移到1500H:0

条件转移指令

条件转移指令的判断条件:PF, CF, OF, SF, ZF

举例:

题1:

1
2
3
4
5
6
7
8
9
10
11
12
	test al,80h	;测试最高位
jz next0 ;D7=0(ZF=1),转移
mov ah,0ffh ;D7=1,顺序执行
jmp done ;无条件转向
next0: mov ah,0
done: ...
test al,80h ;测试最高位
jnz next1 ;D7=1(ZF=0),转移
mov ah,0 ;D7=0,顺序执行
jmp done ;无条件转向
next1: mov ah,0ffh
done: ...

题2:

1
2
3
4
5
6
7
8
;计算|X-Y|(绝对值)
;X和Y为存放于X单元和Y单元的16位操作数
;结果存入result
mov ax,X
sub ax,Y
jns nonneg
neg ax ;neg是求补指令
nonneg: mov result,ax

条件转移指令大全

  1. A(above)/B(below)适用于无符号数
  2. G(greater)/L(lower)适用于有符号数
  3. 比如JNBE:not below and not equal,非小于等于就是大于。然后是前操作数减后操作数,如果前比后大,那么就不用借位,CF = 0,ZF = 0