指令系统 是指 CPU 能完成的所有 指令的集合, 它是在 CPU 设计时就确定了的 所以, 对不同的 CPU, 其指令系统中所包含的具体指令将是各不相同的 但 8088/8086 CPU 的指令系统是完全一样的
8088/8086 CPU 的指令系统可分成下面 9 类 : (1) 数据传送指令 ; (2) 算术运算指令 ; (3) 逻辑运算指令 ; (4) 移位指令 ;
(5) 标志处理指令和 CPU 控制指令 ; (6) 转移和循环控制指令 ; (7) 调用和返回指令 ; (8) 字符串操作指令 ; (9) 输入 输出指令 ;
本节主要学习前 6 类指令, 后面几类指令将结合程序设计和 I/O 电路设计介绍
一. 数据传送类指令数据传送类指令除 SAHF 和 POPF 指令外, 其余的所有数据传送类指令均不影响 6 个状态标志
1. 通用传送指令 (MOV) 在第三章讲寻址方式时, 已经给大家介绍了要寻找的操作数有 4 处来源, 如图 4.2.1 所示 图中的箭头指出两个之间可以进行数据传送的方向
立即数 存储器 段寄存器 DS ES SS CS 寄存器 AX BX CX DX SI DI SP BP
例如 寄存器 AX BX CX DX SI DI SP BP 之间可以相互进行 数据的传送 ;
各寄存器 ( 除段寄存器 CS 外 ) 与存储器之间也可以相互传送, 但段寄存器之间不能传送数据 ;
立即数可以传送给存储器 或寄存器, 但不能传送给段 寄存器 ;
两个存储器单元之间不能 直接传送数据
MOV 指令的格式 : MOV DST, SRC 功能 : 将源操作数 SRC 的一个字节或一个字传送到目的操作数 DST 所指单元 即 : DST (SRC)
其中 : 源操作数可以是通用寄存器 段寄存器 立即数和内存单元, 目的操作数可以是通用寄存器 段寄存器和内存单元 内存单元可通过第三章所指出的各种寻址方式寻址 当目的操作数为段寄存器时, 源操作数不能为立即数, 当源操作数不是立即数时, 两个操作数中必须有一个是寄存器
例如, 下面指令书写是正确的 MOV AX,BX ; 将 BX 中的一个字传送到 AX 中 MOV AL,DL ; 将 DL 中的一个字节传送到 AL 中 MOV AX,02 ; 将立即数 02 传送到 ;AX 中 MOV SI,[BX] ;(SI) ((BX))
MOV AL,4[DI] ; 将 (DI)+4 作为偏移地址, ; 将该单元内容送入 AL MOV AX,[BX+2] ; 将寄存器 BX 中的内容加 ;2 后的值作为偏移地址, ; 将该单元中的一个字节 ; 送入 AL 中, 下一单元中 ; 的一个字节送 AH 中
MOV [BX][DI],DX ;((BX)+(DI)) (DL) ;((BX)+(DI)+1) (DH)
当程序中采用伪指令定义了 一组变量后, 那么, 传送指令也 可以有下面的形式 :
设在数据段 (DS 段 ) 有下面的变量定义 : DATA1 DW 1234H, 5678H DATA2 DB 20H, 30H, 40H DATA3 DW 10 DUP(?) 则传送指令可以有 : DATA1 34H MOV AX, DATA1 12H ; AX (DATA1) 78H 56H 指令执行后,(AX)=1234H AL AH
设在数据段 (DS 段 ) 有下面的变量定义 : DATA1 DW 1234H, 5678H DATA2 DB 20H, 30H, 40H DATA3 DW 10 DUP(?) 则传送指令可以有 : MOV BX,1122H MOV DATA3,BX ; (DATA3) (BX) 指令执行后,(DATA3)=1122H
设在数据段 (DS 段 ) 有下面的变量定义 : DATA1 DW 1234H, 5678H DATA2 DB 20H, 30H, 40H DATA3 DW 10 DUP(?) 则传送指令可以有 : MOV DI,2 MOV AL,DATA2[DI] ;AL (DS:OFFSET DATA2+(DI)) 指令执行后,(AL)=40H
设在数据段 (DS 段 ) 有下面的变量定义 : DATA1 DW 1234H, 5678H DATA2 DB 20H, 30H, 40H DATA3 DW 10 DUP(?) 则传送指令可以有 : MOV SI,2 MOV DX,0AABBH MOV DATA3[SI],DX ;(DS:OFFSET DATA3+(SI)) (DX) DATA3 +1 +2 0BBH 0AAH 指令执行后,(DS:OFFSET DATA3+(SI))=0AABBH DL DH
设在数据段 (DS 段 ) 有下面的变量定义 : DATA1 DW 1234H, 5678H DATA2 DB 20H, 30H, 40H DATA3 DW 10 DUP(?) 则传送指令可以有 : MOV BP, 2 MOV AL, DATA2[BP] ;AL (DS : OFFSET DATA2+(BP)) 指令执行后,(AL)=40H
设在数据段 (DS 段 ) 有下面的变量定义 : DATA1 DW 1234H, 5678H DATA2 DB 20H, 30H, 40H DATA3 DW 10 DUP(?) 则传送指令可以有 : MOV CX, LENGTH DATA3 ;CX LENGTH DATA3 指令执行后,(CX)=10 (0AH)
设在数据段 (DS 段 ) 有下面的变量定义 : DATA1 DW 1234H, 5678H DATA2 DB 20H, 30H, 40H DATA3 DW 10 DUP(?) 则传送指令可以有 : MOV BX, SIZE DATA3 ;(BX) SIZE DATA3 指令执行后,(BX)=20 (14H)
设在数据段 (DS 段 ) 有下面的变量定义 : DATA1 DW 1234H, 5678H DATA2 DB 20H, 30H, 40H DATA3 DW 10 DUP(?) 则传送指令可以有 : MOV SI, OFFSET DATA2 ;(SI) OFFSET DATA2 指令执行后,(SI)=0004H
根据图 4.2.1, 我们可以总结出 8086/8088 所有指令在书写时要遵循的语法共性规则, 有以下几点 : 立即数只能作 SRC 类型要一致 类型要明确 ( 不明确时, 要用 PTR 说明 )
CS 不能做 DST 当 DS ES SS 作 DST 时,SRC 不能为立即数 两存储器单元之间不能直接传送数据 两段寄存器之间不能直接传送数据
例如, 下面指令书写是错误的 (DATA1 为字变量 ) MOV 10H,AL ㄨ DST 不能为立即数寻址 MOV AL,CX ㄨ 类型不一致 MOV [BX][SI],78H ㄨ 类型不明确
MOV DATA1,AH ㄨ 类型不一致 MOV [DI]+02H,DATA1 ㄨ两单元之间不 MOV CS,AX ㄨ 能直接传送数据 CS 不能做 DST MOV DS,0100H ㄨ 当 DS 作 DST 时,SRC 不能为立即数
2. 取有效地址指令 (LEA) 格式 :LEA REG, SRC 功能 : 指令的功能是将源操作数 SRC 的有效地址 ( 偏移地址 ) 送入寄器 REG 这是一条特殊指令, 它传送的不是操作数本身, 而是操作数的有效地址 注 :DST REG 为通用 REG, 一般用 BX BP SI DI
例 1. 若 (BX)=0050H, (DS:0050H)=7788H, 如下图所示 DS:0050H 88H 77H
则 CPU 执行 LEA SI, [BX] 指令后, 是将 DS:(BX) 单元的有效地址 SI. (SI)=0050H DS:0050H 88H 77H
DS:0050H 88H 77H 而 CPU 执行 MOV SI, [BX] 指令后, 是将 (DS:(BX)) SI. (SI)=7788H
例 2. 若在数据段 (DS 段 )0010H 偏移地址开始定义了如下变量 : ORG 0010H DAT1 DW 7766H DAT2 DW 9988H 汇编后, 存储器分配示意图如下 :
DS:0010H 66H 77H 88H 99H DAT1 DAT2 那么,CPU 执行 LEA BX, DAT2 指令完成的功能是 : BX 将 DAT2 变量所具有的 EA (BX)=0012H
上述指令完成的功能等效于 : MOV BX, OFFSET DAT2 而 CPU 执行 MOV BX, DAT2 指令完成的功能是 : BX (DAT2) (BX)=9988H
3. 取地址指针指令 (LDS,LES) 格式 :LDS REG, SRC LES REG, SRC
功能 : 指令的功能是将源操作数 SRC 的有效地址所对应的双字长的内存单元中的高 16 位内容送入 DS( 或 ES), 低 16 位内容送入指令中所指出的 REG 这里的 REG 不允许为段寄存器, 源操作数的寻址方式不允许是立即数和寄存器方式
例 1. 我们可以有下面的变量定义和指令 : TABLE DB 10H,20H,30H,40H,50H POINT1 DD 02001000H POINT2 DD TABLE LDS DI, POINT1 LES SI, POINT2
POINT1 POINT2 00H 10H 00H 02H OFFSET TABLE SEG TABLE
指令 LDS DI, POINT1 执行后, (DI)=1000H, (DS)=0200H; 指令 LES SI, POINT2 执行后, (SI)= OFFSET TABLE, (ES)= SEG TABLE 需要指出的是, 汇编后双字变量 POINT2 中的 32 位内容将是变量 TABLE 的 32 位地址, 其高 16 位是 TABLE 的段地址, 低 16 位是 TABLE 的偏移地址, 这正是双字变量的一种重要用途
上面两条指令的源操作数的寻址方式为直接寻址方式, 也可采用其它寻址方式, 但不同寻址方式所指的内存单元都应是双字类型
例 2. 数 M 所在单元的地址指针在 POINT 双字 单元存放着, 试将数 M AL 中 POINT 20H 01H 00H 15H BX DS LDS BX,POINT MOV AL,[BX] 1500H:0120H M DS:BX
4. 标志传送指令 (LAHF,SAHF) 其中 : LAHF ;AH (FLAG 的低 8 位 ) SAHF ;(AH) (FLAG 的低 8 位 )
5. 数据交换指令 (XCHG) 格式 :XCHG DST, SRC 功能 : 该指令是完成寄存器与寄存器或寄存器与存储单元之间内容交换的 该指令要求两个操作数之一必须是寄存器, 允许两个操作数都是寄存器, 但不允许是段寄存器 注 : 段 REG 和立即数不能参加交换
例 1. 下面指令是合法的 XCHG AX,BX ;(AX) (BX) XCHG CX,[DI] ;(CX) (DS:(DI)) XCHG BX,DATA1 ;(BX) (DATA1)
例 2. 下面指令书写格式是错误的 XCHG AX,1234H ㄨ立即数不能参加交换 XCHG BX,ES ㄨES 段寄存不能参加交换 XCHG AL,CX ㄨ类型不一致 XCHG DAT1,DAT2 ㄨ两存储器单元不能直接交换
例 3. 若 (CX)=9A8BH, 试将 CX 的高 8 位与低 8 位互相交换 XCHG CH, CL 指令执行后,(CX)=8B9AH
6. 字节交换指令 (XLAT) 格式 :XLAT 功能 : 该指令的寻址方式是隐含的, 其有效地址 EA=(BX)+(AL) 指令的功能是将 EA 为偏移地址所对应的内存单元中的一个字节的内容送入 AL 即 :AL (DS:(BX)+(AL))
例. 求某数 (0 9 之间 ) 的平方 在 DS 段定义以下变量 : DAT1 DB 04H ; 被求平方的数 TABLE DB 0,1,4,9,16,25,36 DB 49,64,81
DS:(BX) DS:(BX)+(AL) 04H 00H 01H 04H 09H 10H 19H 24H 31H 40H 51H DAT1 TABLE AL
在 CS 段编写源程序如下 : MOV AX, SEG TABLE MOV DS,AX MOV BX, OFFSET TABLE MOV AL, DAT1 ;(AL)=04H XLAT ;(AL)=10H
7. 堆栈操作指令 1 堆栈 堆栈是以后进先出 (LIFO) 的原则存取信息的一种存储机构 在微型计算机中, 堆栈通常是存储器的一部分 为了保证堆栈区的存储器能按后进先出的规则存取信息, 该存储区的存取地址由一个专门的地址寄存器来管理, 这个地址寄存器称为堆栈指示器或称堆栈指针 SP
在 8088/8086 系统中, 堆栈段 的段地址由 SS 提供, 堆栈操作单 元的偏移地址由 SP 提供
当信息存入堆栈时, 堆栈指针 SP 将自动减量并将信息存入堆栈指针所指出的存储单元, 当需要从堆栈中取出信息时, 也将从堆栈指针 SP 所指出的存储单元中读取信息, 并自动将堆栈指针 SP 增量
所以, 堆栈指针 SP 始终指向堆栈中最后存入信息的那个单元, 我们称该单元为堆栈顶 在信息的存与取的过程中, 栈顶是不断移动的, 也称它为堆栈区的动端, 而堆栈区的另一端则是固定不变的, 这端我们又称其为栈底
操作 8088/8086 系统中堆栈必须按字 8088/8086 系统中, 初始化后 SP 指向堆栈底 +1 单元的偏移地址
例如 : 若堆栈段定义空间大小为 256 字节, 则初始化后,(SP)=0100H SS:0000H 256B 的堆栈区 SS:00FFH (SP)=0100H 栈底
2 堆栈操作指令 只能按字操作, 不能为立即数寻址 入栈指令 (PUSH) 格式 :PUSH SRC 功能 :(1)SP (SP)-2 (2)(SS:(SP)) (SRC)
例 :PUSH AX AX AH AL SP=0100H 256B PUSH AX 指令执行前 栈顶 SP=00FEH (AL) (AH) PUSH AX 指令执行后 256B
PUSHF ;(1) SP (SP)-2 ;(2) ((SP)) (FLAG)
出栈指令 (POP) 格式 :POP DST 功能 :(1)DST (SS:(SP)) (2)SP (SP)+2
例如 : POP BX ;(1) BX (SS:(SP)) ;(2) SP (SP)+2 POPF ;(1) FLAG (SS:(SP)) ;(2) SP (SP)+2
在程序设计时,PUSH POP 必须配对使用, 以保证 SP 指针不被破坏 这样才能保证在程序执行期间, 堆栈不会发生溢出
例 1: 若 (SS)=2000H,(SP)=0100H (AX)=1122H,(BX)=3344H,(CX)=5566H 则 CPU 执行以下指令 : PUSH AX PUSH BX PUSH CX ; 此时, 栈顶单元的 SP=
例 1: 若 (SS)=2000H,(SP)=0100H (AX)=1122H,(BX)=3344H,(CX)=5566H 则 CPU 执行以下指令后, POP AX ;(AX)= POP CX ;(CX)= POP BX ;(BX)= ; 此时,(SP)=
例 2: 若 CPU 执行 PUSH AX PUSH BX PUSH CX 指令组后, 试将压入堆栈的 (AX) DX ( 用 MOV 指令实现 )
BP SS:SP +1 +2 +3 +4 CL CH BL BH AL AH MOV BP, SP MOV DX, [BP]+04H
例 3: 下列指令书写格式语法是错的 PUSH AL 〤堆栈只能按字操作 PUSH 5678H 〤不能为立即数寻址 POP CS 〤 CS 不能作 DST
二. 算术运算类指令算术类指令除了要遵循前面讲的语法规则外, 还要注意 : 只要 ALU 涉及到运算, 就不能使用段 REG; 只要 ALU 涉及到运算, 其运算结果就影响 6 个状态标志
1. 加法指令 8086/8088 共有 3 条加法指令 1 不带 CF 的加法指令 (ADD) 格式 :ADD DST, SRC 功能 :(1)DST (DST)+(SRC) (SRC) 不变 (2) 根据结果设置 6 个状态标志
2 带 CF 的加法指令 (ADC) 格式 :ADC DST, SRC 功能 : (1)DST (DST)+(SRC)+CF (2) 根据结果设置 6 个状态标志
3 增 1 指令 (INC) 格式 :INC DST 功能 : (1)DST (DST)+1, 其中 DST 不能为立即数寻址 (2) 根据结果设置除 CF 以外的 5 个状态标志, 对 CF 无影响
例 1: 若 (AX)=7A8BH,(BX)=9C6DH, 则 CPU 执行 ADD AX, BX 指令后, (AX)= AF=,PF=, ZF= SF=,CF=, OF=
(AX)=0111 1010 1000 1011B + (BX)=1001 1100 0110 1101B ````` ` ``` [1]0001 0110 1111 1000B 结果 CF
例 2: 若 (AL)=0FFH,CF=0, 则 CPU 执行 INC AL 指令后, (AL)= AF=,PF=, ZF= SF=,CF=, OF=
(AL)=1 1 1 1 1 1 1 1 B + ` CF 1 B [1]0 0 0 0 0 0 0 0 B 结果
1. 减法指令 8086/8088 共有 5 条减法指令 1 不带 CF 的减法指令 (SUB) 格式 :SUB DST, SRC 功能 :(1)DST (DST)-(SRC) (2) 根据差设置 6 个状态标志
2 带 CF 的减法指令 (SBB) 格式 :SBB DST, SRC 功能 : (1)DST (DST)-(SRC)-CF (2) 根据差设置 6 个状态标志
3 减 1 指令 (DEC) 格式 :DEC DST 功能 : (1)DST (DST)-1, (2) 根据差设置除 CF 以外的 6 个状态标志, 对 CF 无影响
4 取负指令 (NEG) 格式 :NEG DST 功能 : DST 0-(DST), NEG 指令完成的是特殊的减法操作, 它的被减数一定为零, 因此它是一条单操作数指令
实际它是将目的操作数的值取负 若操作数的原值为一正数, 那么, 执行该指令后, 其值变为该数的负数的补码 ; 而若操作数的原值为一负数 ( 补码表示 ), 那么, 执行该指令后, 其值变为该数所对应的正数 该指令将正常影响各标志位, 并且 CF 表示最高位产生的借位 指令中的目的操作数可以采用除立即数以外的各种寻址方式
例如 : 若 (AL)=03H, 则 CPU 执行 NEG AL 指令后, (AL)=0FDH -3 的补码 ` ` ` ` 0 0 0 0 0 0 0 0 B - 0 0 0 0 0 0 1 1 B [1]1 1 1 1 1 1 0 1 B 结果为 -3 的补码
AF=1 PF=0 ZF=0 SF=1 CF=1 OF=0
若 (AL)=0FDH, 则 CPU 执行 NEG AL 指令后, (AL)=03H - +3 的补码 ` ` ` ` 0 0 0 0 0 0 0 0 B 1 1 1 1 1 1 0 1 B [1]0 0 0 0 0 0 1 1 B 结果为 +3 的原码 ( 补码 ) 应用场合 : 常常用于求某数的绝对值的场合