【微机原理与接口技术】学习笔记3 8086的寻址方式和指令系统

文章目录

  • 3.1 8086的寻址方式
    • 3.1.1 立即数寻址方式 (Immediate Addressing)
    • 3.1.2 寄存器寻址方式 (Register Addressing)
    • 3.1.3 直接寻址方式 Direct Addressing
    • 3.1.4 寄存器间接寻址方式 Register Indirect Addressing
    • 3.1.5 寄存器相对寻址方式 Register Relative Addressing
    • 3.1.6 基址变址寻址方式 Based Indexed Addressing
    • 3.1.7 相对基址变址寻址方式 Relative Based Indexed Addressing
    • 3.1.8 其它寻址方式
      • 1. 隐含寻址
      • 2. I/O端口寻址
        • 1)直接端口寻址方式
        • 2)间接端口寻址方式
      • 3. 一条指令有几种寻址方式
      • 4. 转移类指令寻址
    • 3.1.9 总结★★★
  • 3.2 指令的机器码表示方法 * 本节内容供选用
    • 3.2.1 机器语言指令的编码目的和特点
      • 1.机器语言指令
      • 2.机器语言指令的编码特点
    • 3.2.2 机器语言指令代码的编制
  • 3.3 8086的指令系统
    • 3.3.1 数据传送指令
      • 1.通用数据传送指令 (General Purpose Data Transfer)
        • 1) MOV 传送指令 (Move)
        • 2) 进栈指令PUSH (Push Word onto Stack)
        • 3) 出栈指令POP (Pop Word off Stack)
        • 4) 交换指令XCHG (Exchange)
        • 5) 表转换指令XLAT (Table Lookup-Translation)
      • 2. 输入输出指令 (Input and Output)
        • 1) IN 输入指令 (Input)
        • 2) OUT 输出指令 (Output)
      • 3. 地址目标传送指令 (Address Object Transfers)
        • 1) LEA 取有效地址指令 (Load Effective Address)
        • 2) LDS 将双字指针送到寄存器和DS指令 (Load Pointer using DS)
        • 3) LES 将双字指针送到寄存器和ES指令 (Load Pointer using ES)
      • 4. 标志传送指令(Flag Transfers)
        • 1) LAHF 标志送到AH指令 (Load AH from Flags)
        • 2) SAHF AH送标志寄存器 (Store AH into Flags)
        • 3) PUSHF 标志入栈指令 (Push Flags onto Stack)
        • 4) POPF 标志出栈指令 (Pop Flags off Stack)
    • 3.3.2 算术运算指令
      • 1. 加法指令 (Addition)
        • 1) ADD 加法指令
        • 2) ADC 带进位的加法指令 (Addition with Carry)
        • 3) INC 增量指令 (Increment)
        • 4) AAA 加法的ASCII调整指令 (ASCII Adjust for Addition)
        • 5) DAA 加法的十进制调整指令 (Decimal Adjust for Addition)
      • 2. 减法指令 (Subtraction)
        • 1) SUB 减法指令 (Subtraction)
        • 2) SBB 带借位的减法指令 (Subtract with Borrow)
        • 3) DEC 减量指令 (Decrement)
        • 4) NEG 取负指令 (Negate)
        • 5) CMP 比较指令 (Compare)
        • 6) AAS 减法的ASCII调整指令 (ASCII Adjust for Subtraction)
        • 7) DAS 减法的十进制调整指令 (Decimal Adjust for Subtraction)
      • 3. 乘法指令 (Multiply)
        • 1) MUL 无符号数乘法指令 (Multiply)
        • 2) IMUL 整数乘法指令 (Integer Multiply)
        • 3) AAM 乘法的ASCII调整指令 (ASCII Adjust for Multiply)
      • 4. 除法指令 (Division)
        • 1) DIV 无符号数除法指令 (Division,unsigned)
        • 2) IDIV 整数除法指令 (Integer Division)
        • 3) CBW 把字节转换为字指令 (Convert Byte to Word)
        • 4) CWD 把字转换成双字指令 (Convert Word to Double Word)
        • 5) AAD 除法的ASCII调整指令 (ASCII Adjust for Division)
    • 3.3.3 逻辑运算和移位指令
      • 1. 逻辑运算指令 (Logical Operations)
        • 1) NOT 取反指令 (Logical Not)
        • 2) AND 逻辑与指令 (Logical AND)
        • 3) OR 逻辑或指令 (Logical OR)
        • 4) XOR 异或操作指令 (Exclusive OR)
        • 5) TEST 测试指令 (Test)
      • 2. 算术逻辑移位指令 (Shift Arithmetic and Shift Logical)
        • 1) SAL 算术左移指令 (Shift Arithmetic Left)
        • 2) SHL 逻辑左移指令 (Shift Logic Left)
        • 3) SHR 逻辑右移指令 (Shift Logic Right)
        • 4) SAR 算术右移指令 (Shift Arithmetic Right)
      • 3. 循环移位指令 (Rotate)
        • 1) ROL 循环左移指令 (Rotate Left)
        • 2) ROR 循环右移指令 (Rotate Right)
        • 3) RCL 通过进位位循环左移 (Rotate through Carry Left)
        • 4) RCR 通过进位位循环右移 (Rotate through Carry Right)
    • 3.3.4 字符串处理指令
      • 1. MOVS字符串传送指令 (Move String)
      • 2. CMPS 字符串比较指令 (Compare String)
      • 3. SCAS 字符串扫描指令 (Scan String)
      • 4. LODS 数据串装入指令(Load String)
      • 5. STOS 数据串存储指令 (Store String)
    • 3.3.5 控制转移指令
      • 1. 无条件转移和过程调用指令 (Unconditional Transfer and Call)
        • 1) JMP 无条件转移指令 (Jump)
          • (1) 段内直接转移指令
          • (2) 段内间接转移指令
          • (3) 段间直接(远)转移指令
          • (4) 段间间接转移指令
        • 2) 过程调用和返回指令 (Call and Return)
          • (1) 段内直接调用和返回
          • (2) 段内间接调用和返回
          • (3) 段间直接调用
          • (4) 段间间接调用
      • 2. 条件转移指令 (Conditional Transfer)
        • 1) 直接标志转移指令
        • 2) 间接标志转移 ★★
      • 3. 循环控制指令 (Iteration Control)
        • 1) LOOP循环指令 (Loop)
        • 2) LOOPE/LOOPZ 相等或结果为0时循环 (Loop If Equal/Zero)
        • 3) LOOPNE/LOOPNZ 不相等或结果不为0循环 (Loop If Not Equal/Not Zero)
        • 4) JCXZ 若CX为0跳转 (Jump If CX Zero)
      • 4. 中断指令 (Interrupt)
        • 1) 中断概念
        • 2) 中断指令
        • (1) INT n 软件中断指令 (Interrupt)
        • (2) INTO 溢出中断指令 (Interrupt on Overflow)
        • (3) IRET (Interrupt Return)
    • 3.3.6 处理器控制指令
      • 1. 标志操作指令
        • 1) CLC,CMC和STC
        • 2) CLD和STD
        • 3) CLI和STI
      • 2. 外部同步指令
        • 1) ESC 换码指令 (Escape)
        • 2) WAIT 等待指令 (Wait)
        • 3) LOCK 封锁总线指令 (Lock Bus)
      • 3. 停机指令和空操作指令
        • 1) HLT 停机指令 (Halt)
        • 2) NOP 空操作或无操作指令 (No Operation)

指令Instruction和寻址方式:

  • 计算机的指令,通常包含操作码(Opcode)和操作数(Operand)两部分,操作码指出操作的性质,操作数给出操作的对象
  • 指令有单操作数、双操作数和无操作数之分。如果是双操作数,要用逗号分开,左边的为源操作数,右边的为目的操作数。

寻址方式:

  • 寻址方式就是指令中说明操作数所在地址的方法。
  • 8086的寻址方式有以下几种:
    • 立即数寻址:可直接从指令队列中取数,指令执行速度较快;
    • 寄存器寻址:操作数在寄存器中,执行速度最快;
    • 存储器寻址:操作数在存储器中,又分几种形式,执行速度较慢;
    • 其它寻址:如隐含寻址、I/O端口寻址、转移类指令寻址

下面主要以 MOV 指令(源操作数)为例来说明8086的寻址方式。8088的指令与8086完全兼容,各种寻址方式也完全相同。


3.1 8086的寻址方式

3.1.1 立即数寻址方式 (Immediate Addressing)

操作数直接包含在指令中,它是一个 8 位或 16 位的常数,也叫立即数。

  • 立即数可以送到寄存器中,还可送到一个存储单元( 8 位)中或两个连续的存储单元( 16 位)中去。
  • 立即数只能作源操作数,不能作目的操作数。
  • A~F 打头的 16 进制数字出现在指令中时,前面一定要加一个数字 0

例如:MOV AL, 26H 。将 8 位立即数 26H 送到 AL 寄存器中。
例如,将 FF00H 送到 AX 的指令必须写成:MOV AX,0FF00H
例如:MOV CX, 2A50H。将立即数 2A50H 送到 CX 中,指令的机器码存放及执行过程如图3。
【微机原理与接口技术】学习笔记3 8086的寻址方式和指令系统_第1张图片

立即数寻址说是寻址,但是和地址没有太大关系。

3.1.2 寄存器寻址方式 (Register Addressing)

操作数包含在寄存器中,由指令指定寄存器的名称

  • 16位寄存器可以是:AX、BX、CX、DX、SI、DI、SP、BP
  • 8位寄存器为:AH、AL、BH、BL、CH、CL、DH、DL

例:MOV DX,AX 。设指令执行前AX = 3A68H,DX=18C7H。则指令执行后 DX=3A68HAX=3A68H (保持不变)
例:MOV CL, AH。 将 AH 中的 8 位数据传送到 CL 寄存器。

注意:源操作数的长度必须与目的操作数一致,否则会出错。 例如,MOV CX,AH是错误的。虽然 CX 放得下 AH 中的 8 位数据,但汇编程序不知道应该将它放入 CH 还是 CL


以下几种寻址方式,操作数都放在存储器中,需用不同的方法求出操作数的物理地址,来获得操作数。

3.1.3 直接寻址方式 Direct Addressing

操作数的偏移地址也称为有效地址 EA(Effective Address)。在直接寻址方式下,存储单元的有效地址直接由指令给出默认使用的段寄存器为数据段寄存器 DS。操作数的物理地址 = 16 × D S + E A 16×DS+EA 16×DS+EA
例:MOV AX, [2000H]。指令中直接给出有效地址 EA ,这里右边 EA=2000H,必须加 [ ]表示不是立即数,而是偏移地址。左边当然还是寄存器寻址。设 DS=3000H ,则源操作数的物理地址=
16 × 3000 H + 2000 H = 32000 H 16×3000H+2000H=32000H 16×3000H+2000H=32000H

因目的操作数16 位寄存器 AX 寻址,所以将存储单元中的一个字送进 AX 。若(32000H)=34H(数据的低位字节的地址),(32001H)=12H,则执行指令后,AX=1234H

例:MOV AL, [2000H]。假设条件同上例,指令执行后将 32000H 单元中的字节送到 AL ,结果使 AL=34H 。执行过程示意图如下:

【微机原理与接口技术】学习笔记3 8086的寻址方式和指令系统_第2张图片

段超越前缀:如果要对代码段、堆栈段或附加段寄存器所指出的存储区进行直接寻址,应在指令中指定段超越前缀。例如,数据若放在附加段中,则应在有效地址前加说明符 ES: ,计算物理地址时要用 ES 作基地址,而不是默认值 DS

例如:MOV AX, ES:[500H]。该指令的源操作数的物理地址 =16×ES+500H

符号地址:允许用符号地址代替数值地址,也就是给存储单元起一个名字,如 AREA1 ,寻址时只要使用其名字,不必记住具体数值

例如:MOV AX,AREA1。指令执行后,将从有效地址为 AREA1 的存储单元中取出一个字送到 AX 中去。程序中事先应用说明语句也叫做伪指令来加以说明。例:

AREA1 DW 0867H
...
MOV AX, AREA1

这里的 DW 伪指令语句用来定义变量MOV 指令执行后将 AREA1 单元中内容送到 AX ,结果 AX=0867H 。比起直接寻址用方括号+数值,我们更推荐使用符号地址。

3.1.4 寄存器间接寻址方式 Register Indirect Addressing

指令中给出的寄存器中的值不是操作数本身,而是操作数的有效地址 EA ,需要求出地址并根据地址得到操作数。寄存器名称外同样必须加方括号,可用的寄存器有:BX、BP、SI、DI 。应遵守以下约定:

  • 约定1:如果指令中指定的寄存器是 BXSIDI ,则默认操作数存放在数据段中,则物理地址=16×DS+BX;或 =16×DS+SI ;或 =16×DS+DI
    MOV BX, [SI]。设 DS=1000HSI=2000H(12000H)=318BH,则:物理地址 = 16×DS+SI = 10000H+2000H = 12000H。指令执行后,BX = 318BH,指令执行过程如图:
    【微机原理与接口技术】学习笔记3 8086的寻址方式和指令系统_第3张图片
  • 约定2:如果指令中用 BP 进行间接寻址,则默认操作数在堆栈段中。例如:MOV AX, [BP] 。操作数的物理地址 =16×SS+BP 。指令中也可以指定段超越前缀。例如:MOV BX,DS: [BP] 源操作数物理地址 =16×DS+BPMOV AX,ES: [SI] 源操作数物理地址 16×ES+SI

3.1.5 寄存器相对寻址方式 Register Relative Addressing

它与寄存器间接寻址十分相似,,可用的寄存器有:BX、BP、SI、DI,但在有效地址上还要加一个 8/16 位的位移量
例:MOV BX, COUNT[SI]

  • DS=3000H,SI=2000H ,位移量 COUNT=4000H(36000H)=5678H
  • 则物理地址 = 16×DS+SI+COUNT=30000H+2000H+4000H=36000H。执行结果 BX=5678H ,执行过程如图。
  • 可以理解为 DS * 16 + SI 为数组首地址,后面的 COUNT 为数组偏移量。
    【微机原理与接口技术】学习笔记3 8086的寻址方式和指令系统_第4张图片

上述指令也可用 MOV BX, [COUNT+SI] 这种形式来表示。

3.1.6 基址变址寻址方式 Based Indexed Addressing

有效地址是一个基址寄存器( BXBP )和一个变址寄存器( SIDI )的内容之和,两个寄存器均由指令指定

  • 若基址寄存器为 BX 时,代表数据段,段址寄存器用 DS ,则:物理地址 = 16×DS+BX+SI 或 =16×DS+BX+DI
  • 若基址寄存器为 BP 时,代表堆栈段,段址寄存器应使用 SS ,则:物理地址 = 16×SS+BP+SI 或 = 16×SS+BP+DI

例:MOV AX, [BX][SI]。设 DS=3000HBX=1200HSI=0500H(31700H)=ABCDH ,则:物理地址 = 16×DS+BX+SI = 30000H+1200H+0500H = 31700H 。执行结果:AX=ABCDH ,指令执行过程如图。

【微机原理与接口技术】学习笔记3 8086的寻址方式和指令系统_第5张图片

3.1.7 相对基址变址寻址方式 Relative Based Indexed Addressing

有效地址是基址变址寄存器的内容,再加上 8/16 位位移量之和。

  • 当基址寄存器为 BX 时,用 DS 作段寄存器,则: 物理地址 = 16×DS+BX+SI+8位或16位位移量 或 = 16×DS+BX+DI+8位或16位位移量
  • 当基址寄存器为 BP 时,应使用 SS 作段寄存器,则: 物理地址 = 16×SS+BP+SI+8位或16位位移量 或 = 16×SS+BP+DI+8位或16位位移量

例:MOV AX,MASK[BX][SI]

  • DS=2000HBX=1500HSI=0300HMASK=0200H(21A00H)=26BFH
  • 则物理地址 = 16×DS+BX+SI+MASK = 20000H+1500H+0300H+0200H=21A00H
  • 执行结果:AX=26BFH,指令执行过程如图:
【微机原理与接口技术】学习笔记3 8086的寻址方式和指令系统_第6张图片

相对基址变址寻址:涉及操作数的地址时,常使用方括号,带 [ ] 的地址必须遵循下列规则:

  • 立即数可以出现在方括号内,表示直接地址,例如 [2000H]
  • 只有 BX、BP、SI、DI 可以出现在 [] 内,既可单独出现,也可几个寄存器组合(只能相加),或寄存器与常数相加,但 BXBP 不允许出现在同个[]内SIDI不能同时出现
  • 方括号有相加的含义,故下面几种写法是等价的:6[BX][SI] / [BX+6][SI] / [BX+SI+6]
  • [ ] 内包含BP,则隐含使用 SS 提供基地址,它们的物理地址 = 16×SS+EA

包含 BP 的操作数有 3 3 3 种形式:

  • DISP[BP+SI] ;EA=BP+SI+DISP
  • DISP[BP+DI] ;EA=BP+DI+DISP
  • DISP[BP] ;EA=BP+DISP

其中,DISP 表示 8 8 8 位或 16 16 16 位位移量,也可以为 0 0 0 。这种情况下,也允许用段超越前缀SS 修改为 CSDSES 中的一个,计算物理地址时,应将上式中的 SS 改为相应的段寄存器其余情况均隐含使用DS提供基地址,它们的物理地址计算方法 = 16×DS+EA

这类操作数可以有以下几种形式:

  • [DISP] ;EA=DISP
  • DISP[BX+SI] ;EA=BX+SI+DISP
  • DISP[BX+DI] ;EA=BX+DI+DISP
  • DISP[BX] ;EA=BX+DISP
  • DISP[SI] ;EA=SI+DISP
  • DISP[DI] ;EA=DI+DISP

同样,也可用段超越前缀将式中的DS修改为CS、ES或SS中的一个。

3.1.8 其它寻址方式

1. 隐含寻址

指令中不指明操作数,但具有隐含规定的寻址方式。例如,DAA 它对 AL 中的数据进行十进制调整,结果仍保留在 AL 中。

隐含寻址方式常常用于BIOS和DOS系统调用中。

2. I/O端口寻址

8086有直接端口和间接端口两种寻址方式:

1)直接端口寻址方式

端口地址由指令直接提供,它是一个 8 位立即数 n= 00 ~ FFH 。例 IN AL, 63HAL←端口 63H 中的内容。

2)间接端口寻址方式

被寻址的端口号由寄存器 DX 提供,端口号 =0000~ FFFFH 。例:

MOV  DX, 213H	; DX = 端口地址号213H
IN AL, DX	    ; AL ← 端口213H中的内容

3. 一条指令有几种寻址方式

上述寻址方式都针对源操作数目的操作数可用除了立即寻址方式之外的所有寻址方式指定,所以一条指令可以有几种寻址方式。例:MOV [BX], AL。这里,源操作数为寄存器寻址,目的操作数为寄存器间接寻址方式

4. 转移类指令寻址

将在本章后面讨论控制转移指令时介绍。

3.1.9 总结★★★

总结一下,上面的七种寻址方式,有几条原则:

  • 立即数寻址,直接将一个数送进寄存器,只能够用于源操作数;
  • 寄存器寻址,用一个寄存器即可;
  • [直接寻址 符号地址][BX BP][SI DI] 三组任意搭配。比如说:
    • 三组可以单独抽一个出来:
      • 抽一个直接寻址,写成 [立即数] 或者 符号地址,就是直接寻址
      • 抽第二组中的一个,写成 [BX][BP] ,就是寄存器间接寻址,除了 BP ,寄存器间接寻址都是默认与数据段搭配;
      • 抽第三组中的一个,写成 [SI][DI] ,也是寄存器间接寻址
    • 三组中分别抽两个搭配:
      • 抽第一组的一个和第二组的一个搭配,写成 直接数[BX], 符号地址[BX] 或者 直接数[BP], 符号地址[BP] 就是寄存器相对寻址
      • 抽第二组的一个和第三组的一个搭配,写成 [BX][SI], [BX][DI] 或者 [BP][SI], [BP][DI] ,就是基址变址寻址
      • 抽第一组的一个和第三组的一个搭配,写成 直接数[SI], 符号地址[SI] 或者 直接数[DI], 符号地址[DI] 就是寄存器相对寻址
    • 三组中分别抽一个搭配:就是相对基址变址寻址
  • 如果基址寄存器为 BX 时,段址寄存器用 DS ;如果基址寄存器为 BP 时,段址寄存器应使用 SS
  • 可以使用段超越前缀改变段地址寄存器为 CSES

3.2 指令的机器码表示方法 * 本节内容供选用

3.2.1 机器语言指令的编码目的和特点

1.机器语言指令

计算机只能识别二进制表示的机器语言指令,也称为机器码。编程时,一般可不必了解指令的机器码

若要透彻了解计算机的工作原理,看懂包含机器码的程序清单,对程序进行正确的调试、排错等,就要了解机器语言。

2.机器语言指令的编码特点

对8086指令进行二进制编码时,可以对每种基本类型给出一个编码格式,对照格式填入不同的数字来表示不同的寻址方式、数据类型等,就能求得每条指令的机器码

  • 指令通常由操作码和操作数两部分组成:
  • 操作码很容易从指令编码表中查到;
  • 操作数采用寄存器和存储器寻址方式时,可以列表给出编码方式。
  • 操作数采用立即数和端口地址时,可直接填入指令的编码格式表中。

3.2.2 机器语言指令代码的编制

(略)


3.3 8086的指令系统

8086的指令共有六大类:数据传送指令、算术运算指令、逻辑运算和移位指令、字符串处理指令、控制转移指令、处理器控制指令。

本章除详细介绍各类指令外,还将介绍部分伪指令,并给出许多短小的程序设计例子,以便更好理解指令功能。

3.3.1 数据传送指令

【微机原理与接口技术】学习笔记3 8086的寻址方式和指令系统_第7张图片

SAHFPOPF 指令外,对标志位均没有影响

1.通用数据传送指令 (General Purpose Data Transfer)

1) MOV 传送指令 (Move)

指令格式:MOV 目的, 源
指令功能:目的操作数←源操作数
注意:MOV 指令允许数据传送的途径如下图。但 CS 不能做目的操作数。指令中至少要有一项明确说明传送的是字节还是字
【微机原理与接口技术】学习笔记3 8086的寻址方式和指令系统_第8张图片
例: 由于 DATA 表示数据段的段址,是一个 16 16 16 位立即数,不能被直接送进 DS,需要先送进另一个数据寄存器(如 AX ),再传到 DS 中。

MOV    AL, 'B'   ;AL←将字符B的ASCII码(42H)
MOV    AX, DATA	 ;DATA为直接寻址, 取DATA的内容; AX为寄存器寻址
MOV    DS, AX

在汇编语言程序中,数据通常存放在数据段中。下面将举例介绍数据段的基地址、段中各变量的偏移地址变量定义等概念。例如,下面是某个程序的数据段:

DATA	SEGMENT		       ;数据段开始
	AREA1	DB	14H, 3BH       ;定义了两个字节define byte
	AREA2	DB	3 DUP(0)       ;定义了三个字节, 都是重复的0 define byte
	ARRAY	DW	3100H, 01A6H   ;定义了两个字,四个字节
	STRING	DB	'GOOD'         ;定义了一系列字节ASCII码
DATA	ENDS			   ;数据段结束

数据占用存储空间的情况如图:

  • AREA1 的偏移地址为 0000H
  • AREA2 的偏移地址为 0002H
  • ARRAY 的偏移地址为 0005H
  • 字符串 'GOOD'0009H 开始存放。
    【微机原理与接口技术】学习笔记3 8086的寻址方式和指令系统_第9张图片

代码说明如下:

  • 数据段以段说明符 SEGMENT 开始,ENDS 结束, DATA \text{DATA} DATA 是数据段的段名。
  • DB 伪操作符用来定义字节变量
  • DW 定义字变量低字节在低位地址,高字节在高位地址
  • DUP 复制操作符,前面的 3 说明在存储器中保留 3 个字节单元,初值均为 0 0 0

汇编后, DATA \text{DATA} DATA赋予具体的段地址各变量将自偏移地址 0000H 开始依次存放,各符号地址也被赋予确定的值,等于它们在数据段中的偏移量。

还有一个必须掌握的用法:MOV DX,OFFSET ARRAY。 这里不是直接寻址!

  • ARRAY 的偏移地址送到 DX ,其中,OFFSET 为属性操作符,表示应把其后的符号地址的值(而不是内容)作为操作数
  • ARRAY 的值如上图,则指令执行后,符号地址 ARRAY偏移量 0005H 被送到了 DX 中。
  • 除了偏移地址,还可以送段地址,替换 OFFSETSEG

例:设 AREA1AREA2 的值如上图,说明以下指令功能:

MOV  AL, AREA1	;AL ← AREA1中的内容 14H
MOV  AREA2, AL	;0002H单元 ← 14H
MOV  AX, TABLE[BP][DI] ;将地址为16×SS+BP+DI+TABLE的字单元中的内容送进AX

注意,不能直接把一个内存单元中的值直接送到另一个内存单元之中,需要用一个寄存器中转


2) 进栈指令PUSH (Push Word onto Stack)

指令格式: PUSH 源
指令功能: 将操作数推入堆栈源操作数必须是一个字

  • 源操作数可以是 16 位通用寄存器、段寄存器或存储器中的数据字,但不能是立即数(后来开放了,能够进栈立即数)。
  • 执行 PUSH 操作后,使 SP←SP-2 ,再把源操作数压入 SP 指示的位置上。

3) 出栈指令POP (Pop Word off Stack)

指令格式: POP 目的
指令功能:把当前 SP 所指向的一个字送到目的操作数中

  • 目的操作数可以是 16 位通用寄存器、段寄存器或存储单元,但不能是 CS
  • 每执行一次出栈操作,SP←SP+2SP 向高地址方向移动,指向新的栈顶。

例:设 SS=2000H SP=40H AX=25FEH BX=3120H,依次执行指令:

PUSH  BX
PUSH  AX
POP   BX

堆栈中的数据和 SP 的变化情况如图3.14所示。
【微机原理与接口技术】学习笔记3 8086的寻址方式和指令系统_第10张图片

4) 交换指令XCHG (Exchange)

指令格式:XCHG 目的, 源
指令功能: 源操作数和目的操作数相交换
注意:交换可以在寄存器之间、寄存器与存储器之间进行,但段寄存器不能作为操作数,也不能直接交换两个存储单元中的内容

例:设AX=2000H,DS=3000H,BX=1800H,(31A00H)=1995H,执行指令 XCHG AX,[BX+200H]

  • 源操作数物理地址=3000×10H+1800H+200H=31A00H,其中数据=1995H
  • 指令执行后,AX=1995H,(31A00H)=2000H

5) 表转换指令XLAT (Table Lookup-Translation)

指令格式:

  • XLAT 转换表 :“转换表”为表格首地址
  • XLAT :“转换表”可省略不写

指令功能: 将 1 1 1 个字节从一种代码转换成另一种代码。

  • 使用 XLAT 指令前,应建立一个表格,最多 256 个字节;
  • 且置:BX ← 转换表始址AL ← 表头地址到要找的某项间的位移量
  • 指令执行时,根据位移量从表中查到转换后的代码值,送入 AL 中。

整个过程见下面的例子。

例:下表是十进制数字 0~9LED 七段码对照表,试用 XLAT 指令求数字 5 的七段码值。
【微机原理与接口技术】学习笔记3 8086的寻址方式和指令系统_第11张图片

先用 DB 伪指令建 1 1 1 个表格,存放 0~9 的七段码值。表格起始地址为 TABLE,数字 0~9 的七段码存放在相对于 TABLE 的位移量为 0~9 的单元中。
程序如下:

TABEL  DB	40H, 79H, 24H, 30H, 19H      ;七段码表格
	   DB	12H, 02H, 78H, 00H, 18H
...
MOV	  AL, 5			    ;AL ← 数字5的位移量
MOV	  BX, OFFSET  TABLE	;BX ← 表格首地址
XLAT  TABLE			    ;查表得AL=12H

2. 输入输出指令 (Input and Output)

1) IN 输入指令 (Input)

指令格式:
IN AL, 端口地址AL←从 8 位端口读入 1 字节;或 IN AX, 端口地址 :AX←从 16 位端口的地址读入1 个字。属于直接端口寻址。
IN AL, DX :端口地址存放在 DX 中或 IN AX, DX 。属于间接端口寻址。

格式① ,端口地址(00~FFH)直接包含在 IN 指令里,共允许寻址 256 个端口。当端口地址大于 FFH 时,必须用格式②寻址,即先将端口号送入 DX ,再执行输入操作,DX 允许范围 0000~ FFFFH

例:用 IN 指令从输入端口读取数据的例子。

;以A~F打头的16进制数字出现在指令中时,前面一定要加一个数字0
IN AL, 0F1H	   ; AL←从F1H端口读入1字节
IN AX, 80H	   ; AL←80H端口内容
			   ; AH←81H端口内容
MOV DX, 310H   ; 端口地址310H先送入DX
IN AL, DX	   ; AL←310H端口内容

例: IN 指令也可以用符号表示地址。例如要求从一个模/数(A/D)转换器中读取 1 字节数字到 AL 中。

ATOD EQU   54H   ;A/D转换器端口地址为54H 
;EQU类似于C语言的#define预编译指令,不存在54H这一个内存单元
IN AL, ATOD      ;54H端口的内容读入AL中

2) OUT 输出指令 (Output)

指令格式:
OUT 端口地址, AL8 位端口← AL 内容;或 OUT 端口地址, AX16 位端口 ← AX 内容;
OUT DX,ALDX=端口地址;或 OUT DX, AX

例:用 OUT 指令对输出端口进行操作的例子。

OUT	  85H, AL		;85H端口←AL内容
 
MOV	  DX, 0FF4H	    ;DX指向端口0FF4H
OUT	  DX, AL		;FF4H端口←AL内容
 
MOV	  DX, 300H		;DX指向16位端口
OUT	  DX, AX		;300H端口←AL内容
					;301H端口←AH内容

3. 地址目标传送指令 (Address Object Transfers)

这是一类专用于传送地址码的指令,可以用来传送操作数的段地址偏移地址

1) LEA 取有效地址指令 (Load Effective Address)

指令格式:LEA 目的,源
指令功能: 取源操作数地址偏移量,送到目的操作数
源操作数必须是存储单元,目的操作数是一个除段寄存器之外16 位寄存器。

例 设:SI=1000H,DS=5000H,(51000H)=1234H,指令执行结果如下:

LEA	BX, [SI] ;[SI]的偏移地址为1000H,BX←1000H
MOV	BX, [SI] ;偏移地址为1000H单元的内容为1234H ;指令执行后,BX←1234H 
			 ;MOV BX, OFFSET [SI] 这样写是语法错误

例 下面两条指令是等价的,它们都取(存储单元) TABLE 的偏移地址,送到 BX 中。 OFFSET 是一个预编译操作,必须在编译的时候要知道 TABLE 的偏移地址。

LEA	BX, TABLE
MOV	BX, OFFSET TABLE

例 某数组含 20 个元素,每个元素占一个字节,序号为 0~19 。设 DI 指向数组开头处,如要把序号为 6 的元素的偏移地址送到 BX 中,不能直接用 MOV 指令来实现,因为 MOVOFFSET 是一个预编译指令,必须要求后面的偏移地址可以在预编译时确定下来。需要使用下面指令:

LEA	BX, 6[DI]

2) LDS 将双字指针送到寄存器和DS指令 (Load Pointer using DS)

指令格式:LDS 目的, 源
指令功能: 从源操作数指定的存储单元中,取出 1 1 14 字节地址指针,后两个字节(事先设置好的段地址)送进目的寄存器 DS ,前两个字节(事先设置好的偏移地址)送入指令中指定的目的寄存器中。

源操作数必须是存储单元,目的操作数必须是 16 位寄存器,常用 SI 寄存器,但不能用段寄存器

例 设:DS=1200H,(12450H)=F346H,(12452H)=0A90H。执行指令:

LDS SI, [450H]		

结果: 存储单元前 2 字节内容为 F346HSI←F346H,后 2 字节内容为 0A90H ,DS←0A90H

3) LES 将双字指针送到寄存器和ES指令 (Load Pointer using ES)

指令格式:LES 目的, 源
指令功能:与 LDS 指令的操作基本相同,但段寄存器为 ES,目的操作数常用 DI
例 设 DS=0100H,BX=0020H,(01020H)=0300H,(01022H)=0500H

LES	 DI, [BX]		

存储单元前 2 字节内容为 0300H ,DI←0300H ,后 2 字节内容为 0500H ,ES←0500H


4. 标志传送指令(Flag Transfers)

1) LAHF 标志送到AH指令 (Load AH from Flags)

指令格式:LAHF
指令功能:把标志寄存器(16位)的 SF、ZF、AF、PFCF 传送AH 寄存器的相应位。操作示意图如图。
【微机原理与接口技术】学习笔记3 8086的寻址方式和指令系统_第12张图片

2) SAHF AH送标志寄存器 (Store AH into Flags)

指令格式:SAHF
指令功能:把 AH 内容存入标志寄存器。指令功能与 LAHF 的操作相反。

3) PUSHF 标志入栈指令 (Push Flags onto Stack)

指令格式:PUSHF
指令功能:把整个标志寄存器(一个字)的内容推入堆栈,并使 SP←SP-2

4) POPF 标志出栈指令 (Pop Flags off Stack)

指令格式:POPF
指令功能:把 SP 所指的一个字,传送给标志寄存器 FLAGS,并使得 SP←SP+2


3.3.2 算术运算指令

算术运算指令可处理四种类型的数,表示方法见下表:

  • 无符号二进制整数
  • 带符号二进制整数
  • 无符号压缩十进制整数(Packed Decimal)
  • 无符号非压缩十进制整数(Unpacked Decimal)
    【微机原理与接口技术】学习笔记3 8086的寻址方式和指令系统_第13张图片

注意:

  • 二进制数可以是 8 位或 16 位,如果是带符号数,则用补码表示。 可以写成十六进制。
  • 压缩十进制数:在一个字节中存放两个 BCD 码十进制数。
  • 非压缩十进制数:低半字节存放一个十进制数高半字节为全零

系统提供加、减、乘、除四种基本运算指令,还有各种调整指令,见表。
【微机原理与接口技术】学习笔记3 8086的寻址方式和指令系统_第14张图片

1. 加法指令 (Addition)

1) ADD 加法指令

指令格式:ADD 目的, 源
指令功能:目的←源+目的

2) ADC 带进位的加法指令 (Addition with Carry)

指令格式:ADC 目的,源
指令功能:目的←源+目的+CF
说明:

  • 它们的源操作数可以是寄存器、存储器或立即数。
  • 目的操作数只能用寄存器和存储单元,存储单元可以有表3.2中所示的24种表示方法。
  • 源和目的操作数不能同时为存储器,而且它们的类型必须一致,即都是字节或字。
  • 如果有两个 32 的数相加,就先加低十六位数,然后连同进位参与到高十六位数的相加中。

例 列举上述两加法指令的实例,说明其用法。

ADD	AL, 18H		;AL←AL+18H
ADC	BL, CL		;BL←BL+CL+CF
ADC	AX, DX		;AX←AX+DX+CF
ADD	AL, COST[BX]		
	;将AL内容和物理地址=DS:(COST+BX)的存储字节相加,结果送到AL中
ADD	COST[BX], BL ;将BL与物理地址=DS:(COST+BX)的存储字节相加,结果留在该存储单元

它们影响标志位:CF、OF、PF、SF、ZFAF

例 试用加法指令对两个 816 进制数 5EH3CH 求和,分析指令执行后对标志位的影响。程序如下:

MOV	   AL, 5EH		;AL=5EH (94)
MOV	   BL, 3CH		;BL=3CH (60)
ADD	   AL, BL		;结果AL=9AH

相加过程的算式表示:
【微机原理与接口技术】学习笔记3 8086的寻址方式和指令系统_第15张图片
运算后的标志位:

  • ZF=0,运算结果非0;
  • AF=1,低 4 位向高 4 位有进位;
  • CF=0D7 位没有向前产生进位;
  • SF=1,D7=1
  • PF=1,结果中有偶数1
  • OF=1,由两个数以及它们结果的符号决定,当两个加数符号相同,而结果的符号与之相反时,OF=1
  • 如何对这些标志进行解释,取决于编写的程序,或者说是人为决定的。

3) INC 增量指令 (Increment)

指令格式:INC 目的
指令功能:目的 ← 目的 + 1
目的操作数可以是通用寄存器或内存(存储单元)。指令执行后影响 AF、OF、PF、SF和ZF,但进位标志 CF 不受影响。

例 INC指令的例子。

INC  BL		;BL寄存器中内容增1
INC  CX		;CX寄存器中内容增1
INC  BYTE PTR[BX]  ;内存字节单元内容增1
INC  WORD PTR[BX]  ;内存字单元内容增1

指令中只有一个操作数,如果是内存单元,则要用 PTR 操作符说明是字还是字节。

4) AAA 加法的ASCII调整指令 (ASCII Adjust for Addition)

指令格式:AAA
指令功能: 用 ADDADC 指令对两个非压缩 BCD或以 ASCII 码表示的十进制做加法后,结果在 AL 中,用此指令将 AL 中的结果进行调整。另外,若 AF=1 ,表示有进位,则进到 AH

非压缩十进制数9 可表示成 0000 10015 则为 0000 0101,高 4 位均为 0 。设AH=0 ,若 AL= BCD 9,BL= BCD 5,求两数之和。运算过程:
【微机原理与接口技术】学习笔记3 8086的寻址方式和指令系统_第16张图片
例 求 ASCII 码表示的数 9(39H)5(35H) 之和。设 AH=0 ,则运算过程:
【微机原理与接口技术】学习笔记3 8086的寻址方式和指令系统_第17张图片
如想把 AX 中的结果表示成 ASCII 码,只要在 AAA 指令后加一条指令:

OR AX, 3030H

就可使 AX 中的结果变成了ASCI码 3134H

5) DAA 加法的十进制调整指令 (Decimal Adjust for Addition)

指令格式:DAA
指令功能:对两个压缩 BCD相加后的结果(已在 AL 中)进行调整。
注意:要对 AL 中高半字节和低半字节分别进行调整。

例 若 AL=BCD 38,BL=BCD 15 ,求两数之和。运算过程:
【微机原理与接口技术】学习笔记3 8086的寻址方式和指令系统_第18张图片
例 若 AL=BCD 88,BL=BCD 49,求两数之和。运算过程:
【微机原理与接口技术】学习笔记3 8086的寻址方式和指令系统_第19张图片


2. 减法指令 (Subtraction)

1) SUB 减法指令 (Subtraction)

指令格式:SUB 目的, 源
指令功能:目的 ← 目的 - 源
例:

SUB  AX, BX		;AX←AX-BX
SUB  DX, 1850H	;DX←DX-1850H
SUB  BL, [BX]	;BL中内容减去物理地址=DS:BX处的字节,结果存入BL

2) SBB 带借位的减法指令 (Subtract with Borrow)

指令格式:SBB 目的, 源
指令功能: 目的 ← 目的 - 源 - CF
例:

SBB AL, CL  ;AL←AL-CL-CF

SBB主要用于多字节减法中。

3) DEC 减量指令 (Decrement)

指令格式:DEC 目的
指令功能:目的 ← 目的 - 1
例:

DEC BX	           ;BX←BX-1
DEC WORD PTR[BP]   ;堆栈段中位于[BP]偏置处的字减1
				   ;DEC对内存单元进行操作, 用PTR说明目的数大小

4) NEG 取负指令 (Negate)

指令格式:NEG 目的
指令功能:目的 ← 0 - 目的
例:

NEG AX            ;将AX中的数取负(改变数的符号位)
NEG BYTE PTR[BX] ;对数据段中位于[BX]偏置处的字节取负

5) CMP 比较指令 (Compare)

指令格式:CMP 目的, 源
指令功能:目的 - 源
结果不会送到目的,仅反映在标志位上

例:

CMP AL, 80H		;AL与80H作比较
CMP BX, DATA1	;BX与数据段中偏移量为DATA1处的字比较

比较指令主要用在希望比较两个数的大小,而又不破坏原操作数的场合。

6) AAS 减法的ASCII调整指令 (ASCII Adjust for Subtraction)

指令格式:AAS
指令功能:在用 SUBSBB 指令,对两个非压缩 BCD,或以 ASCII 码表示的十进制数相减后,对 AL 中所得结果进行调整,如有借位,则 CF1

例 设 AL=BCD 3, CL=BCD 8,求两数之差。很显然,结果为 BCD 5,但要向高位借位。运算过程:
【微机原理与接口技术】学习笔记3 8086的寻址方式和指令系统_第20张图片

7) DAS 减法的十进制调整指令 (Decimal Adjust for Subtraction)

指令格式:DAS
指令功能:在用 SUBSBB 指令,对两个压缩 BCD相减(结果已存在 AL )后,进行调整。同样,它也要对 AL高半字节和低半字节分别进行调整

例 设 AL=BCD 56,CL=BCD 98,求两数之差。运算过程:
【微机原理与接口技术】学习笔记3 8086的寻址方式和指令系统_第21张图片


3. 乘法指令 (Multiply)

补码统一了有符号数和无符号数的加减法,但是乘除法却做不到。

1) MUL 无符号数乘法指令 (Multiply)

指令格式:MUL 源
指令功能:把源操作数累加器中的数,都当成无符号数,然后将两数相乘。其中有一个操作数一定是累加器

  • 如果源操作数是 1 个字节,则 AX ← AL * 源
  • 若源操作数是 1 个字, 则 (DX,AX) ← AX * 源
  • 源操作数可以是寄存器存储单元不能是立即数
  • 当源操作数是存储单元时,应在操作数前加 BYTEWORD ,说明是字节还是字

例:

MUL DL			;AX←AL*DL
MUL CX			;(DX,AX)←AX*CX
MUL BYTE[SI]	;AX←AL*(内存中某字节), BYTE说明字节乘法
MUL WORD[BX]	;(DX,AX)←AX*(内存中某字), WORD说明字乘法

MUL 指令执行后影响 CFOF 标志。如果结果的高半部分不为零,则 CFOF 均置 1 。否则,CFOF 均清 0 。通过测试这两个标志,可检测并去除结果中的无效前导零

例:设 AL=55H,BL=14H,计算它们的积。只要执行下面这条指令:

MUL	BL

结果:AX=06A4H。由于 AH=06H≠0 ,高位部分有效,所以置 CF=1OF=1

2) IMUL 整数乘法指令 (Integer Multiply)

指令格式:IMUL 源
指令功能:把源操作数和累加器中的数,都作为带符号数,进行相乘。

  • 存放结果的方式与 MUL 相同,最后给乘积赋予正确的符号
  • 指令执行后,如果乘积的高半部分不是全 0 或全 1 ,则置 CF=1,OF=1 。 若结果高半部分为全 0 或全 1 ,则使 CF=0,OF=0。这样来决定是否需要保存积的高半部分

例 设 AL=-28,BL=59,试计算它们的乘积。

IMUL BL	;AX=F98CH=-1652, CF=1, OF=1

3) AAM 乘法的ASCII调整指令 (ASCII Adjust for Multiply)

指令格式:AAM
指令功能:对存于 AL 的两个非压缩 BCD相乘的积进行调整,结果在 AX 中,高位放 AH ,低位在 AL 。两个 ASCII 码数相乘前,应先屏蔽掉每个数字的高半字节
调整过程: 把 AL 内容除以 10 ,商放在 AH 中,余数在 AL 中。即

  • AH ← AL/10所得的商
  • AL ← AL/10所得的余数

指令执行后,将影响 ZF、SF和PF

例 求两个非压缩十进制数 0906 之乘积。可用如下指令实现:

MOV	AL,09H	;置初值
MOV	BL,06H
MUL	BL		;AL←0906之乘积36H
AAM			;调整得AH=05H(十位), AL=04H(个位)

最后,可在 AX 中得到正确结果 AX=0504H ,即BCD数 54

如果 ALBL 中分别存放 96 的ASCII码,则求两数之积时要用以下指令实现:

AND	AL,0FH		;屏蔽高半字节
AND	BL,0FH
MUL	BL			;相乘
AAM				;调整

如要将结果转换成ASCII码,可再用指令 OR AX, 3030H 来实现,使 AX=3534H

8086/8088 指令系统中,不允许采用压缩十进制数做乘法,乘法调整指令仅此一条


4. 除法指令 (Division)

1) DIV 无符号数除法指令 (Division,unsigned)

指令格式:DIV 源
指令功能: 对两个无符号二进制数进行除法操作。

如果源操作数字节被除数必须事先放在 AX 中,并且有:( 16 16 16 位除以 8 8 8,结果可能是 16 16 16 位,AL放不下,会产生除法错)

  • AL ← AX/源(字节)的商
  • AH ← AX/源(字节)的余数

要是被除数只有 8 位,必须把它放在 AL,并将 AH0 ,然后相除。(8位除以8位

源操作数为字被除数必须放在 DXAX 中,并且有:( 32 32 32 位除以 16 16 16,结果可能是 32 32 32 位,AX放不下,会产生除法错)

  • AX ← (DX,AX)/源(字)的商
  • DX ← (DX,AX)/源(字)的余数

要是被除数只有 16 位,除数也是 16 位,则必须16 位被除数事先放入 AX,再将 DX0 (无符号扩展),然后相除。(16位除以16位

与被除数和除数一样,商和余数都是无符号数

2) IDIV 整数除法指令 (Integer Division)

指令格式:IDIV 源
指令功能:功能与 DIV 相同,但操作数都必须是带符号数商和余数也都是带符号数,而且规定余数的符号和被除数的符号相同

进行除法操作时,如果商超过了目标寄存器 ALAX 所能存放数的范围,计算机会自动产生除法错中断,相当于执行了除数为 0 的运算,所得的商和余数都不确定

例 两个无符号数 7A86H04H 相除的商,应为 1EA1H 。若用 DIV 指令进行计算,即

MOV	AX, 7A86H
MOV	BL, 04H
DIV	BL

这时,由于 BL 中的除数 04H字节,而被除数为字,商 1EA1H 大于 AL 中能存放的最大无符号数 FFH结果将产生除法错误中断

对于带符号数除法IDIV指令,字节操作时要求被除数16 位;字操作时要求被除数32 位。如果被除数不满足这个条件不能简单地将高位置 0 ,而应该先用下面的符号扩展指令 (Sign Extension)将被除数转换成除法指令所要求的格式,再执行除法指令


3) CBW 把字节转换为字指令 (Convert Byte to Word)

指令格式:CBW
指令功能:把 AL字节的符号位扩充到 AH 的所有位,这时 AH 被称为是 AL符号扩充

  • 如果 AL 中的 D7=0 ,就将这个 0 扩展到 AH 中去,使 AH=00H ,即
  • AL 中的 D7=1 ,则将这个 1 扩展到 AH 中去,使 AH=FFH ,即

CBW 指令执行后,不影响标志位

4) CWD 把字转换成双字指令 (Convert Word to Double Word)

指令格式:CWD
指令功能:把 AX字的符号位扩充到 DX 寄存器的所有位中去。

  • AX 中的 D15=0 ,则 DX←0000H ,即
    【微机原理与接口技术】学习笔记3 8086的寻址方式和指令系统_第22张图片
  • AX 中的 D15=1 ,则 DX←FFFFH,即
    【微机原理与接口技术】学习笔记3 8086的寻址方式和指令系统_第23张图片

注意,CBW和CWD是针对有符号数除法说的,无符号数除法直接扩充零即可。

例 编程求 -38/3 的商和余数。

MOV AL, 11011010B	;被除数=-38
MOV CH, 00000011B   ;除数+3
CBW		            ;将AL符号扩展到AH中, 使AX=1111 1111  1101 1010B
IDIV CH	            ;AX/CH 16位除以8;AL=1111 0100B = -12 ()
					;AH=1111 1110B = -2(余数)

5) AAD 除法的ASCII调整指令 (ASCII Adjust for Division)

指令格式:AAD
指令功能:在做除法前BCD转换成二进制数
前面介绍的调整指令,都是在用加法、减法和乘法指令后,紧跟着用一条 AAA、AAS或AAM 指令,对运算结果进行调整。而除法的 ASCII 调整指令不同,它是在除法之前进行的。

在把 AX 中的两位非压缩 BCD 数除以一个非压缩 BCD 数之前,AAD 指令,把 AX 中的被除数调整成二进制数,并存入 AL ,然后才能用 DIV 指令进行运算。调整的过程为:

  • AL←AH×10+AL
  • AH←00

本指令根据 AL 寄存器的结果影响 SF、ZF和PF

例 设 AX 中存有两个非压缩 BCD0307H ,即十进制数 37BL 中存有一个非压缩 BCD05H,若要完成 AX/BL 的运算,可用以下指令:

AAD
DIV BL

第1条指令先将 AX 中的两个 BCD 数转换成二进制数,03×10+7=37=25H,并将 25H→AL ,显然经调整后的被除数 25H 才真正代表 37 ,再用 DIV 指令做除法,可得正确的结果:

  • AL=7(商)
  • AH=2(余数)

3.3.3 逻辑运算和移位指令

逻辑运算和移位指令,对字节或字操作数进行按位操作,见表3.7。
【微机原理与接口技术】学习笔记3 8086的寻址方式和指令系统_第24张图片

1. 逻辑运算指令 (Logical Operations)

1) NOT 取反指令 (Logical Not)

指令格式:NOT 目的
指令功能:目的←目的取反
目的操作数可以是 8 位或 16 位寄存器或存储器,对存储器操作数要说明类型。

NOT 指令只有一个操作数,介绍几种用法。

NOT  AX		;AX←AX取反
NOT  BL		;BL←BL取反
NOT  BYTE  PTR[BX]	 ;对存储器字节单元内容取反后送回该单元 

以下为双操作数指令。源操作数可以是 816立即数、寄存器、存储器,目的操作数只能是寄存器或存储器,两个操作数不能同时为存储器

指令执行后,均将 CFOF 0 0 0ZFSFPF 反映操作结果AF 未定义,源操作数不变。

2) AND 逻辑与指令 (Logical AND)

指令格式:AND 目的, 源
指令功能:目的←目的∧源
主要用于使操作数的某些位保留(和“1”相与),而使某些位清除(和“0”相与)。

例 设 AX 中是数字 58ASCII 码,即 AX=3538H ,将它们转换成 BCD 码,结果仍放回AX 。指令如下:

AND	AX, 0F0FH 	;AX←0508H, 屏蔽高4, 截得低4

3) OR 逻辑或指令 (Logical OR)

指令格式:OR 目的, 源
指令功能:目的←目的∨源
主要用于使操作数的某些位保留(和“0”相或),而使某些位置1(和“1”相或)。
例 设 AX 中存有两个 BCD0508H,要将它们分别转换成 ASCII码 ,结果仍在 AX 中。可用如下指令实现:

OR AX, 3030H	;AX←3538H

4) XOR 异或操作指令 (Exclusive OR)

指令格式:XOR 目的, 源
指令功能:对两个操作数进行按位逻辑异或运算,结果送回目的操作数,即目的←目的 XOR 源
用于使操作数的某些位保留(和“0”相异或),而使某些位取反(和“1”相异或)。

例 若 AL 中存有某外设端口的状态信息,其中 D1 位控制扬声器发声,要求该位在 01 之间来回变化,原来是 1 变成 0 ,原来是 0 变成 1 ,其余各位保留不变。可用以下指令实现:

XOR AL, 00000010B

5) TEST 测试指令 (Test)

指令格式:TEST 目的, 源
指令功能:目的∧源,并修改标志位但不回送结果
它常用在要检测某些条件是否满足,但又不希望改变原有操作数的情况下。

例 设 AL 寄存器中存有报警标志。若 D7=1 ,表示温度报警,程序要转到温度报警处理程序T_ALARMD6=1,则转压力报警程序 P_ALARM 。为此,可用 TEST 指令来实现这种功能:

TEST AL, 80H	;查AL的D7=1?
JNZ	T_ALARM		;1(非零),则转温度报警程序
TEST AL, 40H	;D7=0,D6=1?
JNZ	P_ALARM		;1,转压力报警

其中,JNZ 为条件转移指令,表示结果非 0 (ZF=1)则转移。

2. 算术逻辑移位指令 (Shift Arithmetic and Shift Logical)

可对寄存器或存储器中的字或字节的各位进行算术移位或逻辑移位,移动的次数由指令中的计数值决定,如图3.17。
【微机原理与接口技术】学习笔记3 8086的寻址方式和指令系统_第25张图片

1) SAL 算术左移指令 (Shift Arithmetic Left)

指令格式:SAL 目的, 计数值

2) SHL 逻辑左移指令 (Shift Logic Left)

指令格式:SHL 目的, 计数值
指令功能:以上两条指令的功能完全相同。均将目的操作数的各位左移,每移一次,最低位 LSB 0 0 0 ,最高位 MSB 进标志位 CF 。移动一次,相当于将目的操作数乘以 2

计数值表示移位次数,可以是 1 。若大于 1 ,则用 CL 存放,需要事先将次数存入 CL 。移位次数最多为 31 (即 00011111B )。

MOV	   AH, 00000110B ;AH=06H
SAL	   AH, 1		 ;将AH内容左移一位后, AH=0CH
MOV	   CL, 03H		 ;CL←移位次数3
SHL	   DI, CL		 ;将DI内容左移3次
SAL	   BYTE  PTR[BX], 1	;将内存单元字节左移1

3) SHR 逻辑右移指令 (Shift Logic Right)

指令格式:SHR 目的, 计数值
指令功能:使目的操作数各位右移,每移一次,最低位进入 CF ,最高位补 0

右移次数由计数值决定,同 SAL/SHL 指令一样。若目的操作数为无符号数,每右移一次,使目的操作数除以2

例 用右移的方法做除法 133/8=16…5 ,即:

MOV	AL, 10000101B ;AL=133
MOV	CL, 03H		  ;CL=移位次数
SHR	AL, CL		  ;右移3次,AL=10H,余数5丢失

4) SAR 算术右移指令 (Shift Arithmetic Right)

指令格式:SAR 目的, 计数值
指令功能:每移位一次,最低位进入 CF ,但最高位(即符号位)保持不变,而不是补0。相当于对带符号数进行除2操作

例 用SAR指令计算 -128/8=-16 的程序段如下:

MOV	   AL, 10000000B	;AL=-128
MOV	   CL, 03H			;右移次数为3
SAR	   AL, CL			;算术右移3次后, AL=0FH=16

3. 循环移位指令 (Rotate)

算术逻辑移位指令,移出的操作数数位均丢失。循环移位指令则把数位从操作数的一端移到其另一端,从操作数中移走的位不会丢失

1) ROL 循环左移指令 (Rotate Left)

指令格式:ROL 目的, 计数值
【微机原理与接口技术】学习笔记3 8086的寻址方式和指令系统_第26张图片

2) ROR 循环右移指令 (Rotate Right)

指令格式:ROR 目的, 计数值
【微机原理与接口技术】学习笔记3 8086的寻址方式和指令系统_第27张图片
例:

ROL	 BX, CL	;将BX中的数, 不带进位位左移规定次数
ROR  WORD  PTR[SI], 1    ;将内存单元的字, 不带进位右移1

3) RCL 通过进位位循环左移 (Rotate through Carry Left)

指令格式:RCL 目的, 计数值
【微机原理与接口技术】学习笔记3 8086的寻址方式和指令系统_第28张图片

4) RCR 通过进位位循环右移 (Rotate through Carry Right)

指令格式:RCR 目的, 计数值
【微机原理与接口技术】学习笔记3 8086的寻址方式和指令系统_第29张图片

目的操作数可以是 8/16 位的寄存器操作数或内存操作数,计数值含义同上,即 1 或由 CL 指定。

ROLROR 为小循环移位指令,没有把 CF 包含在循环中;RCLRCR 为大循环指令,把 CF 作为整个循环的一部分参加循环移位。CF值由最后一次被移出的值决定

例 设 CF=1,AL=1011 0100B

  • 若执行指令 ROL AL, 1,则 AL=0110 1001BCF=1OF=1
  • 若执行指令 ROR AL, 1 ,则 AL=0101 1010BCF=0,OF=1
  • 若执行指令 RCR AL, 1,则 AL=1101 1010BCF=0,OF=0
  • 若执行指令 MOV CL, 3RCL AL, CL ,则 AL=1010 0110BCF=1OF 不确定。

总的来说,移位指令 shl, sal, shr, sar; rol, ror, rcl, rcr 指令的格式都是一致的,都是 指令 目的, 1 或 CL


3.3.4 字符串处理指令

字符串是指一系列存放在存储器中字或字节数据。

使用字符串操作指令时,可用指令中的源串目的串名(即操作数)来表明是字节还是字,也可在指令助记符后加 B 说明是字节,加 W 说明是字操作,每种指令都有3种格式
5条1字节字符串操作指令见表3.8。
【微机原理与接口技术】学习笔记3 8086的寻址方式和指令系统_第30张图片
字符串指令执行时,必须遵守以下的隐含约定

  • 源串位于数据段中,源串字符的始址(或末址)为 DS:SI
  • 目的串位于附加段中,目的串字符的始址(或末址)为 ES:DI
  • 每执行一次字符串指令,指针 SIDI自动修改,指向下一待操作单元。
  • DF 标志控制字符串处理的方向
    • DF=0 递增。执行一次字节串操作,SIDI+1字串操作,SIDI+2
    • DF=1 递减。执行一次字节串操作,SIDI-1字串操作,SIDI-2
    • STD 指令使 DF=1CLD 指令使 DF=0
  • CX=要处理的字符串长度(字节或字数)。

为加快串运算指令的执行速度,可在基本指令前加重复前缀,使数据串指令重复执行。每重复执行一次,SIDI根据方向标志自动修改CX 的值则自动减 1 。能与基本指令配合使用的重复前缀有:

  • REP 无条件重复 (Repeat)
  • REPE/REPZ 相等/结果为零则重复 (Repeat while Equal/Zero)
  • REPNE/REPNZ 不相等/结果非零则重复 (Repeat while Not Equal/Not Zero)

1. MOVS字符串传送指令 (Move String)

指令格式:MOVS 目的串, 源串
指令功能:把源串中的一个字节或字,传送到目的串中且自动修改指针 SIDI
利用 MOVS 指令,能很方便地将数据从内存的某一地址(源地址)传送到另一个地址(目的地址),还能自动修改源和目的地址;若使用重复前缀可用一条指令传送一批数据

例 要求把数据段中以 SRC_MESS 为偏移地址的一串字符 “HELLO!”,传送到附加段中以 NEW_LOC 开始的单元中。实现该操作的程序如下:
【微机原理与接口技术】学习笔记3 8086的寻址方式和指令系统_第31张图片
比较发现,使用有重复前缀 REPMOVSB 指令,程序更简洁

2. CMPS 字符串比较指令 (Compare String)

指令格式:CMPS 目的串, 源串
指令功能:将源串中数据减去目的串数据,但不改变两数据串的原始值,结果反映在标志位上。操作后源串和目的串指针会自动修改

常用此指令来比较两个串是否相同,并由其后的条件转移指令,根据 CMPS 执行后的标志位值,决定程序的转向。

CMPS 指令前可加重复前缀, 下面每两条指令功能相同:

  • REPE CMPSCX≠0 (未比完)且串相等时重复比较
  • REPZ CMPSZF=1(两串相等),则重复比较
  • REPNE CMPS ;若CX≠0(串没有结束)和串不相等重复比较
  • REPNZ CMPSZF=0 ,则重复比较

例 比较两个字符串,一个是在程序中设定的口令串 PASSWORD,另一个是从键盘输入的字符串 IN-WORD ,若输入串与口令串相同,程序开始执行。否则程序驱动扬声器发声,警告用户口令不符,拒绝往下执行。这可以用 CMPS 指令来实现,有关程序段如下:

DATA SEGMENT			 ;数据段
	PASSWORD DB '8086 CPUI'	 ;口令串
	IN_WORD  DB '8088 CPU'	 ;从键盘输入的串
	COUNT EQU  8 	 		 ;串长度
DATA ENDS

CODE SEGMENT	 ;代码段
	ASSUME DS:DATA, ES:DATA
	...
    LEA SI, PASSWORD	;源串指针
    LEA DI, IN_WORD		;目的串指针
    MOV CX, COUNT		;串长度
    CLD				    ;地址增
    REPZ CMPSB          ;CX≠0且串相等时重复比较
    JNE SOUND           ;若不相等,转发声程序
OK:	...	;比完且相等,往下执行
			...
SOUND: 	...	;使PC机扬声器发声
 			...	;并退出
CODE ENDS

3. SCAS 字符串扫描指令 (Scan String)

指令格式:SCAS 目的串
指令功能:从 AL (字节操作)或 AX (字操作)寄存器的内容,减去 ES:DI指针的目的串元素,结果反映在标志位上,但不改变源操作数。串操作后目的串指针 DI 会自动修改。

  • 利用 SCAS 指令,可在内存中搜索所需要的数据(关键字)。指令执行前,必须事先将它存在 AL (字节)或 AX (字)中。
  • SCAS 指令前也可加重复前缀。

例 在某字符串中搜寻字符 A 。若有,搜索次数送到 BX ;若无,将 BX0 。设字符串始址 STRING 的偏址为 0 ,字符串长度为 CX 。程序段如下:

MOV  DI, OFFSET STRING  ;DI=字符串偏移地址
MOV  CX, COUNT	 		;CX=字符串长度
MOV  AL, 'A'			;AL=关键字A的ASCII码
CLD						;清方向标志
REPNE  SCASB			;CX≠0(没查完);ZF=0(不相等)时重复
JZ  FIND				;若ZF=1,已搜到,转出
MOV  DI, 0		;若ZF=0,没搜到,DI←0
FIND:
MOV  BX, DI		;BX←搜索次数
HLT				;停机

4. LODS 数据串装入指令(Load String)

指令格式:LODS 源串
指令功能:把数据段中以 SI 作为指针的串元素,传送到 AL (字节操作)或 AX (字操作)中,同时修改 SI

为该指令加重复前缀没有意义。因为每重复传送一次数据,累加器中的内容就被改写,执行重复传送操作后,只能保留最后写入的那个数据

5. STOS 数据串存储指令 (Store String)

指令格式:STOS 目的串
指令功能:将累加器 ALAX 中的一个字节或字,传送到以 ES:DI 为目标指针的目的串中,同时修改 DI ,以指向串中的下一个单元。

STOS 指令与 REP 重复前缀连用,即执行指令 REP STOS ,能方便地用累加器中的一个常数,对一个数据串进行初始化。例如,初始化为全 0 的串。

例 数据段中有个数据块, 存有 8 位带符号数,始址BLOCK ,要求将正、负数分开,正数送到附加段中始址为 PLUS_DATA 的缓冲区,负数送到附加段中始址为 MINUS_DATA 的缓冲区。
数据块可看成一个数据串,用 SI 作源串指针,DIBX 作正、负数目的缓冲区指针,CX 控制循环次数。程序段如下:

START:
    MOV  SI, OFFSET   BLOCK  	;SI为源串指针
    MOV  DI, OFFSET   PLUS_DATA	
				;DI为正数目的区指针
    MOV  BX, OFFSET  MINUS_DATA 
				;BX为负数目的区指针
   	MOV  CX, COUNT	;CX放循环次数 
   	CLD
GOON:	
   LODS  BLOCK		;AL←取源串的一个字节
   TEST  AL, 80H	;是负数?
   JNZ   MINUS		;是,转MINUS
   STOSB			;非负数,将字节送正数区
   JMP   AGAIN		;处理下一个字节
MINUS:
   XCHG  BX, DI		;交换正负数指针
   STOSB			;负数送入负数区
   XCHG  BX, DI		;恢复正负数指针
AGAIN:		
   DEC   CX		;次数减1
   JNZ   GOON	;未处理完,继续传送
   HLT			;已完,停机

程序中,正负数的存储均使用 STOSB 指令,该指令必须以 SI 为源指针DI 为目的指针。但存储负数时,负数区的目的指针在 BX 中,因此要用 XCHG 指令将 BX 内容送进 DI ,让 DI 指向负数区,同时也把 DI 中的正数区目的指针保护起来。

执行 STOSB 指令后,再用 XCHG 指令将 BXDI 交换回来,以便下次转回 GOON 标号后,LODS 指令仍能正确执行。


3.3.5 控制转移指令

【微机原理与接口技术】学习笔记3 8086的寻址方式和指令系统_第32张图片

1. 无条件转移和过程调用指令 (Unconditional Transfer and Call)

1) JMP 无条件转移指令 (Jump)

指令格式:JMP 目的
指令功能: 无条件地转移到目的地址去执行。
这类指令又分成两种类型:

  • 段内转移,或近(NEAR)转移。转移指令的目的地址JMP 指令在同一代码段中,转移时仅改变 IP 的内容,段地址 CS 的值不变。
  • 段间转移,又称远(FAR)转移。转移指令的目的地址JMP 指令不在同一段中,转移时,CSIP 的值都要改变,程序要转移到另一个代码段去执行。

就转移地址提供的方式而言,又可分为两种方式:

  • 直接转移。在指令码中直接给出转移的目的地址,目的操作数用一个标号来表示。它又可分为段内直接转移和段间直接转移。
  • 间接转移。目的地址包含在某个 16寄存器存储单元中,CPU必须根据寄存器或存储器寻址方式间接地求出转移地址。同样,这种转移类型又可分为段内间接转移和段间间接转移。

所以无条件转移指令可分成段内直接转移 SHORT/NEAR PTR 、段内间接转移 WORD PTR 、段间直接转移 FAR PTR 和段间间接转移 DWORD PTR 四种不同类型和方式,如表所示。
【微机原理与接口技术】学习笔记3 8086的寻址方式和指令系统_第33张图片

(1) 段内直接转移指令

指令格式:

  • JMP SHORT 标号 立即短转移
  • JMP NEAR PTR 标号 (或JMP 标号) 立即近转移

段内相对转移指令,目的操作数均用标号表示。

  • 转向的有效地址= IP+8位/16位位移量(DISP)
  • 若转移范围在 -128~+127 字节内,称为短转移,指令中只需要用8位位移量,在标号前加说明符SHORT
  • 若位移量是 16 位,称为近转移,目的地址与当前IP的距离在 -32768~+32767 字节之间。可加说明符NEAR PTR ,也可省略这类指令用得最多

例 给出一个含有一条无条件转移指令的简单程序的列表文件,它是由汇编语言源程序经汇编程序翻译后产生的。即
【微机原理与接口技术】学习笔记3 8086的寻址方式和指令系统_第34张图片

(2) 段内间接转移指令

转向的 16 位地址存放在一个 16寄存器字存储器单元中。

寄存器寻址段内转移指令,转向的地址存放在寄存器中,执行操作:IP←寄存器内容
例:JMP BX,若指令执行前,BX=4500H ;指令执行时,IP←4500H ,程序转到代码段内偏移地址4500H 处执行。

存储器间接寻址段内转移指令,先计算出存储单元的物理地址,再从中取一个送到 IP 。即IP←字存储单元内容。
例:JMP WORD PTR 5[BX]WORD PTR 说明是字操作:

  • 设指令执行前 DS=2000H, BX=100H, (20105H)=4F0H
  • 则指令执行后 IP=(20000H+100H+5H) = (20105H)=4F0H ,转到段内 IP=4F0H 处执行。

(3) 段间直接(远)转移指令

指令中用远标号直接给出转向的 CS:IP ,程序从一个代码段转到另一个代码段。例:

JMP FAR PTR PROG_F

FAR PTR 说明 PROG_F 为远标号。指令执行的操作:

  • IP←PROG_F段内偏移量
  • CS←PROG_F 所在段的段地址
  • 设标号 PROG_F 的逻辑地址=3500H:080AH,则:指令执行后,IP=080AH,CS=3500H,程序转到 3500:080AH 处执行。
(4) 段间间接转移指令

操作数为存储器(这里不存在寄存器的使用),要转移的目标地址 CS:IP 存放在存储器中,需要加说明符 DWORD PTR,表示转向地址需要双字

例:JMP DWORD PTR [SI+0125H],设指令执行前,CS=1200H,IP=05H,DS=2500H,SI=1300H;内存单元 (26425H)=4500H(26427H)=32F0H,指令中的位移量 DISP=0125H。执行过程如图:
【微机原理与接口技术】学习笔记3 8086的寻址方式和指令系统_第35张图片


2) 过程调用和返回指令 (Call and Return)

把某些能完成特定功能常用的程序段,编写成独立模块,称为过程(Procedure)或子程序(Subroutine)。在主程序中用 CALL 语句调用这些过程,格式为:CALL 过程名

过程以 PROC 开头,ENDP 结束。过程中要安排一条返回指令 RET ,过程执行完后能正确返回主程序。若在过程运行中又调用另一过程,称为过程嵌套。

主程序和过程在同一代码段,称为近调用,不在同一段则称为远调用。过程调用的寻址方式与转移指令类似,但没有段内短调用。由于调用结束后需返回原程序继续运行,要执行保护和恢复返址操作,比转移JMP更复杂。

CALL 指令分两步执行:

  • 第一步:返址入栈,将 CALL 下面指令的地址推入堆栈:
    • 近调用执行的操作:SP←SP-2IP 入栈
    • 远调用执行的操作:SP←SP-2CS 入栈;SP←SP-2IP 入栈
  • 第二步:转到子程序入口执行相应的子程序。入口地址由 CALL 指令的目的操作数提供,寻址方法与 JMP指令类似。
  • 第三步,执行过程中的 RET 指令时,从栈中弹出返址,使程序返回主程序继续执行。也有两种情况:
    • 从近过程返回,从栈中弹出 1 1 1 个字→ IP ,并且使 SP←SP+2
    • 从远过程返回,先从栈中弹出 1 1 1 个字→ IP ,并且使 SP←SP+2 ;再弹出 1 1 1 个字→ CS ,并使SP←SP+2

下面举例说明 CALLRET 指令的 4 种寻址方式。

(1) 段内直接调用和返回

例:CALL PROG-N ;PROG-N是一个近标号。该指令含 3 3 3 个字节,编码格式为:
【微机原理与接口技术】学习笔记3 8086的寻址方式和指令系统_第36张图片
设调用前:CS:IP=2000H:1050H,SS:SP=5000H:0100HPROG-NCALL 指令之间的字节距离等于 1234H (即 DISP=1234H )。则执行CALL指令的过程:

  • SP←SP-2,即新的 SP=0100H-2=00FEH返回地址的 IP 入栈。由于存放 CALL 指令的内存首地址为CS:IP=2000:1050H,该指令占 3 字节,所以返回地址为 2000:1053H,即 IP=1053H 。于是 1053H 被推入堆栈。
  • 根据当前 IP 值和位移量 DISP 计算出新的 IP 值,作为子程序的入口地址,即 IP = IP+DISP = 1053H+1234H = 2287H
  • 程序转到本代码段中偏移地址为2287H处执行

指令 CALL PROG_N 的执行过程如图:
【微机原理与接口技术】学习笔记3 8086的寻址方式和指令系统_第37张图片

RET 指令的寻址方式与 CALL 一样,在本例中也是段内直接调用。执行过程如下:

  • IP←(SP和SP+1) 单元内容 即返址 IP=1053H 从栈中弹出
  • SP←SP+2,SP=00FEH+2=0100H,即恢复原 SP

结果,返回 CALL 下面的那条指令,即从 2000:1053 处继续执行程序,如上图。

(2) 段内间接调用和返回

例 下面是两条段内间接调用指令的例子,返址在寄存器或内存中

CALL BX
CALL WORD PTR[BX+SI]

它们执行的操作分三步,前两步与直接调用相同,第三步不同,具体为:

  • SP←SP-2
  • IP 入栈
  • IP←EA ,计算出目的地址的有效地址 EA ,送入 IP ,以此转移。

设:DS=1000H, BX=200H, SI=300H, (10500H)=3210H

CALL BX

转移地址在BX中,此调用指令执行后,IP←0200H,转到段内偏移地址为 0200H 处执行。

CALL WORD PTR[BX+SI]

子程序入口地址在内存字单元中,其值为 (16×DS+BX+SI) = (10000H+0200H+0300H) = (10500H) = 3210H , 即 EA=3210H 。此指令执行后,IP←3210H ,转到段内偏移地址为3210H 处执行。对应的RET指令执行的操作与段内直接过程的返回指令类似。

(3) 段间直接调用

CALL FAR PTR PROG_F ;PROG_F是一个远标号 。该指令含 5 个字节,编码格式为:
【微机原理与接口技术】学习笔记3 8086的寻址方式和指令系统_第38张图片

设调用前:CS:IP=1000:205AHSS:SP=2500:0050H ,标号 PROG-F 所在单元的地址指针CS:IP=3000:0500H

存放CALL指令的内存首址为 1000:205AH ,由于该指令长度为5个字节,所以返回地址应为 1000:205FH 。执行远调用CALL指令的过程如图3.22所示,具体为:

  • SP←SP-2SP=0050H-2=004EH
  • CS 入栈 即 CS=1000H 入栈
  • SP←SP-2SP←004CH
  • IP 入栈 即 IP=205FH 入栈
  • 转子程序入口,将 PROG-F 的段地址和偏移地址送 CS:IP。即 CS←3000H,IP←0500H

执行子程序 PROG-F 。过程 PROG-F 中的 RET 指令的寻址方式也是段间直接调用,返回时执行的操作为:

  • SP←SP+2SP←004C+2=004EH
  • IP←栈中内容,即 IP←205FH
  • SP←SP+2SP←004EH+2=0050H
  • CS←栈中内容,CS←1000H

所以程序转返回地址 CS:IP=1000:205FH 处执行。
【微机原理与接口技术】学习笔记3 8086的寻址方式和指令系统_第39张图片

(4) 段间间接调用

操作数必须是存储单元,从该单元开始存放的双字表示过程的入口地址,指令中用 DWORD PTR 说明是对存储单元进行双字操作

CALL DWORD PTR[BX]

  • 设调用前,DS=1000H,BX=200H,(10200H)=31F4H,(10202)=5200H
  • 执行时先将返址的 CS:IP 推入堆栈,再转向过程入口
  • 指令中操作数地址= DS×16+BX=10000H+200H=10200H 从中取得的双字就是过程入口地址,即:
    • IP←(10200H)IP=31F4H
    • CS←(10202H)CS=5200H

8086还有另一种带参数的返回指令,形式为:

RET  n

n 称为弹出值,它让CPU在弹出返回地址后,再从堆栈中弹出 n 个字节的数据,也就是让 SP 再加上 n 。n可以是0000~FFFFH范围内的任何一个偶数
例如,指令 RET 8 ,表示从堆栈中弹出地址后,再使 SP 的值加上 8


2. 条件转移指令 (Conditional Transfer)

上条指令执行后的状态标志,作为测试条件,来决定是否转移。当条件成立,程序转向指令中给出的目的地址去执行;否则,仍顺序执行。

条件转移均为段内短转移,转移指令与目的地址必须在同一代码段中。转移距离范围为 -128~+127 字节。8 位偏移量需用符号扩展法扩展16 位后才能与 IP 相加。

在指令中,目的地址均用标号表示,指令格式: 条件操作符 标号。条件转移指令共18条,归类成直接标志转移间接标志转移两大类。

1) 直接标志转移指令

助记符中直接给出标志状态测试条件,以 CF、ZF、SF、OFPF5个标志的10种状态为判断条件,形成10条指令,如表。有的指令有两种助记符,代表同样的指令,如JZ/JE。
【微机原理与接口技术】学习笔记3 8086的寻址方式和指令系统_第40张图片

例 求 ALBL 中的两数之和,若有进位,则 AH 置1,否则 AH 清0。程序如下:

	ADD	AL, BL		;两数相加
	JC	NEXT		;若有进位,转NEXT
	MOV	AH, 0		;无进位,AH清0
	JMP	EXIT		;往下执行
NEXT:	
	MOV	AH, 1		;有进位,AH置1
EXIT:;程序继续进行

2) 间接标志转移 ★★

不在指令助记符中直接给出标志状态位的测试条件,但仍以某一个或几个标志的状态组合为测试条件,若条件成立则转移,否则顺序往下执行。

间接标志转移指令共有8条,列于表中。每条指令都有两种不同的助记符。在无符号数比较测试指令中,指令助记符中的“A”是英文Above的缩写,表示“高于”之意,“B”是英文Below的缩写,表示“低于”之意。
【微机原理与接口技术】学习笔记3 8086的寻址方式和指令系统_第41张图片
例 设 AL=F0H,BL=35H ,执行指令

CMP  AL, BL	;AL-BL
JAE	 NEXT   ;AL大于等于BL,则转到NEXT

JAE/JNB 根据 CF 标志是否为0决定转移。若 CF=0 ,即无进位,则转移,这与直接标志转移指令中的 JNC 功能完全一样。同样,JB/JNAEJC 指令的功能相同。

带符号数进行比较时,不能仅根据 SFOF 标志来判定,而要将它们组合起来考虑。指令助记符中,“G”(Great than)表示“大于”,“L”(Less than)表示“小于”。

例 设某学生的英语成绩已存放在 AL 中,如低于 60 分,打印F(FAIL);高于或等于 85 分,打印G(GOOD);在 60~84 分之间,打印P(PASS)。程序为

		     CMP AL, 60		;60分比较
		     JB  FAIL		;<60,转FAIL
		     CMP AL, 85	 	;60,与85分比较
		     JAE GOOD		;85,转GOOD
		     MOV AL, 'P'	;其它,将AL←'P'
		     JMP PRINT		;转打印程序
FAIL:        MOV AL, 'F'	;AL←'F'
		     JMP PRINT		;转打印程序
GOOD:		 MOV AL, 'G'	;AL←'G'
PRINT: ... 			;打印存在AL中的字符

例:设某温度控制系统中,从温度传感器输入一个8位二进制摄氏温度值。当温度低于100℃时,打开加热器;温度升到100℃或以上时,关闭加热器。温度传感器端口号为 320H ,控制加热器的输出信号连到端口 321H最低有效位,当它置 1 加热器打开,清 0 则关闭。实现上述温度控制的程序:

GET-TEM:
	MOV	DX, 320H	;DX指向温度输入端口
	IN	AL, DX		;读取温度值
	CMP	AL, 100		;100 ℃比较
	JB	HEAT_ON		;<100 ℃,加热
	JMP	HEAT_OFF	;100 ℃,停止加热
HEAT-ON:	
	MOV	AL, 01H		;D0位置1,加热
	MOV	DX, 321H	;加热器口地址
	OUT	DX, AL		;打开加热器
	JMP	GET_TEMP	;继续检测温度
HEAT-OFF:
	MOV	AL, 00	;D0位置0,停止加热
	MOV	DX, 321H
	OUT	DX, AL	;关闭加热器	
     ...    	;进行其它处理

例 在首地址为 TABLE 的10个内存字节单元中, 存放了10个带符号数,统计其中正数、负数和零的个数,结果存入PLUS、NEGT和ZERO单元

TABLE  DB 01H, 80H, 0F5H, 32H, 86H
       DB 74H, 49H, 0AFH, 25H, 40H
		PLUS DB 0			;存正数个数
		NEGT DB 0			;存负数个数
		ZERO DB 0			;0的个数
			...					
	    MOV CX, 10			;数据总数
	    MOV BX, 0			;BX清0

AGAIN:
		CMP TABLE[BX], 0	;取一个数与0比
		JGE GRET_EQ		    ;0,转GRET_EQ
		INC	NEGT			;<0,负数个数加1
		JMP	NEXT			;往下执行
GRET-EQ:
		JG	P-INC			;>0,转P-INC
		INC	ZERO			;=0,零个数加1
		JMP	NEXT			;往下执行
P-INC:	
		INC	PLUS			;正数个数加1
NEXT:
		INC	BX			;数据地址指针加1
		DEC	CX			;数据计数器减1
		JNZ	AGAIN		;未完,继续统计

3. 循环控制指令 (Iteration Control)

是一组增强型条件转移指令,用来控制程序段的重复执行,重复次数由 CX 中的内容决定,转移目标都是短标号,偏移量都是负值,即只能向前转移。均不影响任何标志

1) LOOP循环指令 (Loop)

指令格式:LOOP 短标号
指令功能:重复执行一系列指令。重复次数放在 CX 中,执行一次指令,CX-1。如减1后 CX≠0 ,转到指令给定的标号处继续循环;CX=0 ,结束循环,转去执行 LOOP 指令后的那条指令。

一条 LOOP 指令相当于执行以下两条指令:

DEC CX
JNZ 标号

例 商店里有8种商品,价格为 83元,76元,65元,84元,71元,49元,62元和58元,要将每种商品提价7元,编程计算每种商品提价后的价格。先将商品原价按 BCD 码形式,依次存放在以 OLD 开始的8个存储单元中,新价格存放进以 NEW 开始的8个单元,然后用 LOOP 指令来实现8次循环。即

	OLD DB 83H, 76H, 65H, 84H
	    DB 71H, 49H, 62H, 58H
	NEW DB 8 DUP(?)
      ...	
	MOV	CX, 08H		;8种商品
	MOV	BX, 00H		;BX作指针,初值为0
NEXT:
	MOV	AL, OLD[BX]	;读入一个商品的原价
	ADD	AL, 7		;加上提价因子
	DAA				;调整为十进制数
	MOV	NEW[BX], AL	;存放结果
	INC	BX			;地址指针加1
	LOOP	NEXT	;未加满8次,继续循环
		...			;已加完8

循环操作也可以只含一条指令,即 LOOP 指令自身,这样的程序段常用来实现延时。例如:

		MOV	    CX, 10	    ;循环次数为10
DELAY:
		LOOP    DELAY	    ;本指令重复执行10

例 用循环和跳转指令,编写控制PC机扬声器发声的程序。在PC机中,61H 口的 D1D0 位接到扬声器接口电路上在 D0=0 的情况下,当 D1=1 时,扬声器被接通;当 D1=0 时,则断开。通过控制 D1 位的值,就能产生一个由1和0构成的二进制序列,使扬声器发声。61H 口中的其它位则用来控制PC机的内部开关状态、奇偶校验及键盘状态等。要将这些状态保存起来。

控制扬声器发声程序:

	IN  AL, 61H	 ;AL←从61H口读取数据
	AND AL, 0FCH ;保护D7~D2位,D0位清0
MORE:
	XOR AL, 02   ;触发D1位使之在01间变化
	OUT 61H, AL	 ;控制扬声器开关通断
	MOV CX,260	 ;CX=循环次数
DELAY:
    LOOP DELAY	 ;循环延时
	JMP  MORE	 ;再次触发

本例中,LOOP 指令重复执行 260 遍,起延时作用,使开关通断维持一定时间。否则开关动作太快,发出的声音频率太高,人耳听不出来。


2) LOOPE/LOOPZ 相等或结果为0时循环 (Loop If Equal/Zero)

指令格式:LOOPE 标号LOOPZ 标号
指令功能:LOOPE 是相等时循环,LOOPZ 是结果为0时循环。

它们能完成相同功能,具有不同助记符,用来控制重复执行一组指令。

指令执行前,先将重复次数送入 CX ,每执行一次 CX-1 ,若 -1CX≠0ZF=1 ,则转到指令指定的标号处重复执行;若 CX=0ZF=0 ,便退出循环,执行本指令后的那条指令。

例 设1个50字节组成的数组存在 ARRAY 开始的内存中,测试数组中的元素,若为 0 ,且不是最后 1 个,便继续进行下个元素的测试,直到找到第一个非零元素或查完了为止。

ARRAY	DB	××, ××, ...		;50个元素的数组
	MOV	BX, OFFSET ARRAY    ;BX指向数组开始单元
	DEC	BX					;指针-1
	MOV	CX, 50	            ;CX=元素个数
NEXT:
	INC	BX		            ;指向数组的下个元素
	CMP [BX], 00H			;数组元素与0比较
	LOOPE NEXT				;若元素为0和CX≠0,循环
               ...			;否则,结束查找

3) LOOPNE/LOOPNZ 不相等或结果不为0循环 (Loop If Not Equal/Not Zero)

指令格式:LOOPNE 标号LOOPNZ 标号
指令功能:LOOPNE 是不相等循环,而 LOOPNZ 是结果 ZF≠1 循环,它们也是一对功能相同但形式不一样的指令。
指令执行前,应将重复次数送入 CX ,每执行一次,CX 自动 -1 ,若 -1CX≠0ZF=0 ,则转移到标号所指定的地址重复执行;若 CX=0ZF=1 ,则退出循环,顺序执行下一条指令。

例 设一个由 17 个字符组成的字符串存放在以 STRING 开始的内存中,查找字符串中是否包含空格符。若没有找到空格符尚未查完,则继续查找,直到找到第一个空格符或查完了, 才退出循环。

STRING  DB    'Personal Computer' ;字符串
	...
    MOV BX, OFFSET STRING  ;BX指向字符串始址
    DEC BX				   ;BX-1
    MOV CX, 17			   ;CX=字符串长度
NEXT:	
    INC BX				   ;指向下一个字符
    CMP [BX], 20H		   ;字符串元素与空格比较
    LOOPNE NEXT			   ;若不是空格和CX≠0,循环
    ...	    			   ;找到空格或CX已为0

4) JCXZ 若CX为0跳转 (Jump If CX Zero)

指令格式:JCXZ 标号
指令功能:若 CX 寄存器为 0 ,则转移到指令中标号所指定的地址处,否则将往下顺序执行
它不对 CX 寄存器进行自动减 1 操作

这条指令用在循环程序开始处。为了使程序跳过循环,只要事先把 CX 寄存器清 0


4. 中断指令 (Interrupt)

1) 中断概念

计算机在执行正常程序过程中,由于某些事件发生,需要暂时中止当前程序的运行,转到中断服务程序去为临时发生的事件服务。中断服务程序执行完,又返回正常程序继续运行。此过程称为中断。

8086的中断有两种:

  • 第一种,外部中断或硬件中断,它们从8086的不可屏蔽中断引脚 NMI可屏蔽中断引脚 INTR 引入。
  • 第二种,内部中断或软中断,是为解决CPU在运行中发生意外情况或是为便于对程序调试而设置的。
  • 此外,也可在程序中安排一条中断指令 INT n ,利用它直接产生8086的内部中断

2) 中断指令

(1) INT n 软件中断指令 (Interrupt)

软件中断指令n 为中断类型号,范围 0~255 。可安排在程序的任何位置上。

(2) INTO 溢出中断指令 (Interrupt on Overflow)

带符号数进行算术运算后,若 OF=1 ,则可由 INTO 指令产生类型为 4 的中断; 若 OF=0 ,则 INTO 指令不产生中断。

为此,在带符号数进行加减法运算之后,必须安排一条 INTO 指令,一旦溢出就能及时向CPU提出中断请求,CPU可做出相应的处理。

(3) IRET (Interrupt Return)

中断返回指令IRET。被安排在中断服务程序的出口处,指令执行后,从堆栈中依次弹出程序断点和 FLAGS 的内容,使CPU继续执行原来被打断的程序。


3.3.6 处理器控制指令

1. 标志操作指令

8086提供一组标志操作指令,可直接对 CFDFIF 标志位进行设置或清除等操作,但不包含TF标志,如下表。
【微机原理与接口技术】学习笔记3 8086的寻址方式和指令系统_第42张图片

1) CLC,CMC和STC

利用 CLC 指令,使进位标志 CF0CMC 指令使 CF 取反,STC 指令则使 CF1

2) CLD和STD

方向标志 DF执行字符串操作指令时用来决定地址的修改方向CLD 指令使 DF0 (递增),而 STD 指令则使 DF1 (递减) 。

3) CLI和STI

中断允许标志 IF 决定CPU能否响应可屏蔽中断请求,指令 CLI 使 IF0禁止CPU响应这类中断。STI 使 IF1允许CPU响应


2. 外部同步指令

1) ESC 换码指令 (Escape)

指令格式:ESC 外部操作码, 源操作数
指令功能:换码指令实现8086对8087协处理器的控制。用于浮点数的运算。

2) WAIT 等待指令 (Wait)

通常跟在 ESC 指令之后。ESC 指令执行后,8086 CPU处于等待状态不断检测 TEST 引脚,若为高电平,则重复执行 WAIT 指令,处理器处于等待状态;如变为低电平,便退出等待状态,执行下条指令。

3) LOCK 封锁总线指令 (Lock Bus)

加在任何指令的前面,用于多处理器的环境。凡带有 LOCK 前缀的指令在执行过程中,将禁止其它处理器使用总线

3. 停机指令和空操作指令

1) HLT 停机指令 (Halt)

使CPU进入暂停状态,当下列情况之一发生时,则脱离暂停状态

  • RESET 线上加复位信号;
  • NMI 引脚上出现中断请求信号;
  • 在允许中断的情况下,在 INTR 引脚上出现中断请求信号
  • 程序中常用 HLT 指令来等待中断的出现

2) NOP 空操作或无操作指令 (No Operation)

单字节指令,执行时耗费 3 个时钟周期的时间,但不完成任何操作

你可能感兴趣的:(微机原理)