第二章:8086/8088的指令系统(一)

8086指令系统

  1. 从功能上包括6大类:
    1. 数据传送
    2. 算术运算
    3. 逻辑运算和移位
    4. 串操作
    5. 程序控制
    6. 处理器控制
  2. 学习指令的时候要注意一下几点:
    1. 指令码的含义
    2. 指令对操作数的要求
    3. 指令的对标志位的影响
    4. 指令的功能

数据传送指令

  1. 分为下面四小类
    1. 通用数据传送
    2. 输入输出
    3. 地址传送
    4. 标志位操作
  2. 注意: 除了标志传送指令外其他指令的执行对标志位不产生影响。

通用数据传送指令

  1. 分为如下几小类
    1. 一般数据传送指令
    2. 堆栈操作指令
    3. 交换指令
    4. 查表转换指令
    5. 字位扩展指令
  2. 一般数据传送指令MOV
    1. 格式:MOV dest ,src
    2. 操作: 将操作数src复制传送到操作数dest,即src->dest
    3. 注意点:
      1. 两操作数字长必须相同;
      2. 两操作数不允许同时为存储器操作数;
      3. 两操作数不允许同时为段寄存器;
      4. 在源操作数是立即数时,目标操作数不能是段寄存器;
      5. IP和CS不作为目标操作数,FLAGS一般也不作为操作数在指令中出现。
    4. 注意了:前说过段寄存器的初始化不能由程序员控制,但是初始化之后可以
    5. 举例:(略)
  3. 堆栈操作指令
    1. 堆栈是内存中一段特定的存储区域,常用来存放中断断点,调用子程序的调用现场,程序运行中需要临时保存的数据等内容。对堆栈区间的访问遵循“先进后出”的原则
    2. 8086、8088微机中堆栈的段基址是由堆栈寄存器SS确定的,而堆栈区间的具体大小是由用户在程序中指定的,在微机中用堆栈指针SP表示,SP始终指向堆栈顶部(栈顶)。
    3. 堆栈操作的原则:
      1. 先进后出
      2. (2个字节)为单位,也就是说堆栈操作的操作数一定为16位。
    4. 堆栈操作指令( OPRD:可以为16位的寄存器,或者内存的2个单元。)
      1. 压栈指令
        1. 格式: PUSH OPRD
        2. 功能: 将指定的寄存器或存储单元的内容存入到栈顶
        3. 执行过程:
          1. SP-1 ->SP,然后操作数的高位字节送至SP所指向的单元
          2. SP-1-> SP,然后操作数的低位字节送至SP所指向的单元
      2. 压栈指令
        1. 格式: pop OPRD
        2. 功能: 将栈顶的数据复制到指定的寄存器或内存单元中
        3. 执行过程:
          1. SP所指向单元的数据送至操作数的低位字节,SP+1 -> SP
          2. SP所指向单元的数据送至操作数的高位字节,SP+1 -> SP
      3. 举例:

         1. 压栈
             PUSH AX
             若此时(AX) = 1234H, (SS) = 2000H, (SP) = 0100H,则指令的执行流程如下:
             第一步: SP-1 -> SP,即(SP) = 00FFH, (200FFH) = 12H;
             第二步: SP-1 -> SP,即(SP) = 00FEH, (200FEH) = 34H;
                        
         2. 出栈
             POP [BX]
             若此时(BX)= 0010H,(SS) = 2000H,(DS) = 3000H,(SP) = 00FEH,则指令执行过程如下:
             第一步:(SP)->(30010h),SP+1->SP,即(SP) = 00FFH;
             第二步:(SP)->(30011h),SP+1->SP,即(SP) = 0100H;
        
      4. 栈操作指令说明:
        1. 指令的操作数必须是16位
        2. 操作数可以是寄存器或存储器2个单元,但不能是立即数
        3. 不能从栈顶弹出一个字给CS;
        4. PUSH和POP指令在程序中一般成对出现;
        5. PUSH指令的操作方向是从高地址向低地址,而POP指令的操作正好相反。
  4. 交换指令
    1. 指令格式: XCHG dest, src
    2. 功能: 将目的操作数dest与源操作数src的内容相互交换。
    3. 注意:
      1. 两个操作数必须有一个是寄存器操作数
      2. 不允许使用段寄存器。
      3. 2个操作数位数必须相同。
  5. 查表指令:
    1. 指令格式:XLAT 或 XLAT 表首地址
    2. 功能:((BX) + (AL) -> (AL)),把内存数据段中的一个字节的数据复制进AL,该数据的偏移地址是(BX)+(AL)
    3. 可以把内存数据段中以BX为偏移地址的一段连续的存储空间看成是一张表,而AL是表中具体数据项距表头的唯一量(索引值)。只要知道了这个位移量,就能利用XLAT指令方便地找到表中的数据。
    4. 说明: 用BX的内容代表表格首地址,AL内容为表内偏移量,BX+AL得到要查找元素的偏移地址
    5. 操作:将BX+AL所指向单元的内容送AL
  6. 字位扩展指令
    1. 作用:将8位扩展为16位,或者将16位扩展为32位
    2. 前提:
      1. 全部针对的是有符号数的扩展
      2. 将符号数的符号位扩展到高位
      3. 指令位零操作数指令,采用隐含寻址,隐含操作数为AX及AX,DX
      4. 无符号数的扩展规则为在高位补0
    3. 字到字节的扩展指令
      1. 格式:CBW
      2. 操作: 将AL内容扩展到AX
      3. 规则: 若最高位=1,则执行后AH=FFH;若最高位=0,则执行后AH = 00H;
    4. 将字扩展到双字的扩展指令
      1. 格式: CWD
      2. 操作: 将AX内容扩展到DX AX
      3. 规则: 若最高位=1,则执行后DX=FFFFH;若最高位=0,则执行后DX = 0000H;

地址传送指令

  1. 顾名思义就是取地址的指针
  2. 这类指令一共有3条:
    1. 去偏移地址指令LEA->取近地址指针
    2. *LDS指令->取远地址指针
    3. *LES指令->取远地址指针
  3. LEA指令
    1. 格式:LEA REG, MEM
    2. 功能: 把源操作数MEM的地址偏移量送至目的操作数REG
    3. 注意:
      1. 源操作数必须是一个内存操作数,目标操作数通常是间址寄存器。
    4. 举例:

       假设源操作数为内存中的数据段
       MOV BX, [1200H]
       析: 将内存数据段中偏移地址为1200H的2个单元的存储内容复制到BX寄存器中
       LEA BX, [1200H]
       析: 将内存数据段中[1200H]数据的偏移地址(即1200H)复制到BX寄存器中,(BX) = 1200H
      
  4. LDS/LES指令
    1. LDS:从源操作数src指示的存储单元开始,连续取出4个字节的数据,这4个字节的数据组成一个完整的内存逻辑地址,即段基址(16位):偏移地址(16位),其中较低地址单元的两个字节的数据作为偏移地址送至目的寄存器dest,而较高地址单元的两个字节的数据作为段基址送至附加段寄存器ES;
    2. LES:从源操作数src指示的存储单元开始,连续取出4个字节的数据,这4个字节的数据组成一个完整的内存逻辑地址,即段基址(16位):偏移地址(16位),其中较低地址单元的两个字节的数据作为偏移地址送至目的寄存器dest,而较高地址单元的两个字节的数据作为段基址送至数据段寄存器DS;
    3. 注意:
      1. 源操作数src必须是一个内存操作数
      2. 目的操作数dest必须是一个16位的通用寄存器。

标志传送指令

  1. LAHF
    1. 将FLAGS(标志寄存器)的低8位装入AH
  2. SAHF
    1. 将AH内容写入到FALGS的低8位。
  3. 标志压栈指令
    1. 指令格式: PUSHF
    2. 功能: 将标志寄存器FR的内容存入到栈顶
  4. 标志出栈指令
    1. 指令格式:POPF
    2. 功能: 将SP所指向的栈顶子单元的内容送至标志寄存器FR.

输入输出指令

  1. 关于I/O端口
    1. I/O端口
      1. I/O接口中用于存储数据、可以直接被CPU访问的寄存器
      2. 我们知道CPU与外部设备之间的交互是需要输入输出接口的。
      3. 什么是端口: 就是输入输出接口中用来存放数据可以被CPU直接访问的一些寄存器
      4. 因为CPU内部也有寄存器,为了在名字上不要出现冲突,所以接口中的寄存器给取了另外一个名字–端口
      5. 通俗的说就是寄存器不一定CPU内部才有,I/O接口中也有,但是I/O接口中的寄存器不叫寄存器,叫端口。
  2. 输入输出指令是专门针对I/O端口进行的操作。
  3. 无论是输入还是输出,都必须通过累加器AX或AL才能与I/O端口上的数据进行通讯
  4. 输入指令:
    1. 直接输入指令
      1. 格式: IN AL, PORT 或 IN AX,PORT
      2. 其中PORT为I/O端口地址,范围为00H->FFH,此时可不是立即数了
      3. 功能: (PORT)-> (AL),将地址为PORT的I/O端口中的一个字节的数据复制到寄存器AL中; 或者(PORT+1)-> (AH),(PORT)-> (AL),即将地址为PORT+1,PORT的I/O端口中的两个字节的数据复制到寄存器AX中
    2. 间接输入指令
      1. 格式:IN AL, DX 或 IN AX,DX
      2. 其中,DX寄存器中的内容就是I/O端口的地址,范围是0000H~FFFFH
      3. 功能:(DX)-> (AL),将以DX中的内容为地址的I/O端口中的一个字节的数据复制到寄存器AL中; 或者(DX+1)-> (AH),(DX)-> (AL),即以DX+1,PORT中的内容为地址的I/O端口中的两个字节的数据复制到寄存器AX中
  5. 输出指令:
    1. 直接输出指令:
      1. 格式:OUT PORT, AL 或 OUT PORT, AX
      2. 其中PORT为I/O端口地址,范围为00H->FFH,此时可不是立即数了
      3. 功能: (AL)-> (PORT),将寄存器AL中的内容复制到地址为PORT的I/O端口中;或(AH)->(PORT+1),(AL)->(PORT),即寄存器AX中的内容复制到地址为PORT+1,PORT的I/O端口中
    2. 间接输出指令:
      1. 格式:OUT DX, AL 或 OUT DX, AX
      2. 其中DX寄存器中的内容为I/O端口地址,范围为0000H->FFFFH
      3. 功能: (AL)-> (DX),将寄存器AL中的内容复制到以DX中的内容为地址的I/O端口中;或(AH)->(DX+1),(AL)->(PORT),即寄存器AX中的内容复制到以DX+1,DX中的内容为地址的I/O端口中

算术运算指令

  1. 常见的算术运算指令如下:
    1. 加法运算指令
    2. 减法运算指令
    3. 乘法运算指令
    4. 除法运算指令
  2. 算术运算指令的执行大多对状态标志位会产生影响

加法指令

注意: 加法指令对操作数的要求与MOV指令相同

  1. 普通加法指令ADD
    1. 通常用在两个字节、两个字相加的情况下。
    2. 格式:
      1. ADD dest, src
    3. 操作: 源操作数和目标操作数按位相加结果送到目标地址:(dest)<-(dest)+(src)
    4. ADD指令的执行对全部6个状态标志位都产生影响。
  2. 带进位的加法指令ADC
    1. 用于多个字节的数据相加,会产生进位
    2. 指令格式、对操作数的要求、对标志位的影响与ADD指令完全一样。
    3. 区别: (dest)<-(dest)+(src) +CF ,就是目标与源操作数求和之后还要加上CF的状态
    4. 注意:ADC多用于多字节数相加,使用前要先将CF清零。
  3. 自加1指令INC
    1. 对标志位的影响不同,不会影响CF,只会影响其余5个标志位,而上面2种对每个标志位都会产生影响。
    2. 格式:INC dest
    3. 操作数不能是段寄存器、不能是立即数
    4. 操作:(dest)<-(dest)+1;
    5. 常用于在程序中修改地址指针

减法指令

注意: 减法指令对操作数的要求与对应的加法指令相同

  1. 普通减法指令SUB
    1. 格式: SUB dest,src
    2. 操作: (dest)<- (dest) - (src)
    3. 对标志位的影响与ADD相同,使用场合业余ADD相同。
  2. 考虑借位的减法指令SBB
    1. 指令格式、对操作数的要求、对标志位的影响与SUB指令完全一样。
    2. SBB指令多用于两个多字节数的相减运算
  3. 自减1指令DEC
    1. 格式: DEC dest
    2. 操作: (dest)<- (dest)-1
    3. 指令对操作数的要求以及对标志位的影响与INC相同
    4. 指令常用于在程序中修改计数值
  4. 比较指令CMP
    1. 格式: CMP dest,src
    2. 操作: (dest)- (src),用目标操作数-源操作数,只影响标志位,然后结果舍弃,不影响目标操作数dest
    3. 用途: 用于比较2个数的大小,可作为条件转移指令转移的条件
    4. 指令对操作数的要求以及对标志位的影响与SUB相同
  5. 求补指令NEG(取负指令)
    1. 格式:NEG dest
    2. 操作数要求: 8/16位寄存器或存储器操作数
    3. 操作:(dest)<- 0 - (dest)
    4. 对一个负数取补码就相当于用零减去此数
    5. 执行NEG指令后,一般情况下都会使CF为1,除非给定的操作数为零才会使CF为0.
    6. 当指令的操作数的值为80H(-128)或8000H(-32768),则执行NEG指令后,结果不变,但OF置1,其他情况下OF均置0.
    7. 用0减去操作数,可以得到负数的绝对值。

乘除运算指令

  1. 说明:
    1. 有分别针对有符号数和无符号数运算指令
      1. 有不同的指令助记符
    2. 乘、除运算指令均采用隐含寻址方式
    3. 请注意该类指令对操作数的要求
  2. 乘法指令:
    1. 无符号的乘法指令MUL
    2. 带符号的乘法指令IMUL
    3. 注意点:
      1. 乘法指令采用隐含寻址,隐含了存放被乘数的累加器AL或AX,以及存放结果的AX或AX,DX;
      2. 两个8位二进制数相乘他的结果无论是大还是小,一律都是16位字长; 同理,两个16位数相乘,结果都是32位字长。
      3. 那么2个字节(8位)数相乘结果可以放在一个16位寄存器中,在乘法计算中默认放在AX寄存器中;2个字(16位)数相乘结果为32位,那么久没有一个32位的寄存器了,因此必须借助另外一个寄存器DX,用它来存放运算结果的高16位。
    4. 无符号数的乘法指令:
      1. 格式:MUL dest
      2. 功能:
        1. 若dest是字节操作数,则(AL)* (dest)->(AX),若此时(AH)!= 0,则CF = OF = 1,表示相乘后操作数长度扩展,否则,CF = OF = 0;
        2. 若dest是字操作数,则(AX)* (dest)->(DX)(AX),若此时(DX)!= 0,则CF = OF = 1,表示相乘后操作数长度扩展,否则,CF = OF = 0;
      3. 注意:dest 不能是立即数
    5. 有符号数的乘法指令:
      1. 格式:IMUL dest
      2. 指令功能:
        1. 指令的操作数类型,存放方式的规定与MUL指令相同。无论是字节数据或字数据相乘,首先将两个数的绝对值相乘,再根据乘数的符号确定积的符号,最后所得的积是补码形式的带符号数。 若乘积的高位(AH) 或(DX)不是低位(AL)或(AX)的符号扩展,则CF= OF = 1.表示乘积的高位含有有效数据,否则 CF=OF=0;
  3. 除法指令:
    1. 无符号数的除法指令:
      1. 格式: DIV dest
      2. 功能:
        1. 若dest是字节操作数,则(AX)/ (dest)->(AL),(AX)mod(dest)->(AH),即商在AL,余数在AH;
        2. 若dest是字操作数,则(DX)(AX)/ (dest)->(AX),(DX)(AX)mod(dest)->(DX),即商在AX,余数在DX;
        3. 除法运算不影响标志位
    2. 有符号数的除法指令
      1. 格式: IDIV dest
      2. 指令功能:
        1. 指令的操作数类型,存放方式的规定与DIV指令相同。无论dest是字节数据或字数据,首先将两个数的绝对值相除,再根据被除数和除数的符号确定商和余数的符号,最后所得的商和余数是补码形式的带符号数。 8086、8088规定余数的符号与被除数的符号相同。
  4. 算术运算指令小结
    1. 指令执行影响状态标志位
    2. 乘法指令执行结果为相乘数的双倍字长;除法指令要求被除数是除数的双倍字长。

逻辑运算指令

  1. 简介:
    1. 8086、8088的逻辑运算指令包括”与“、”或“、”非“、”异或“这4种,均是对操作数的对应位按位进行逻辑运算,同时对状态标志位有不同的影响。
  2. 对操作数的要求
    1. 大多数与MOV指令相同
    2. “非”运算指令要求操作数不能是立即数
  3. 对标志位的影响
    1. 除”非“运算指令,其余指令的执行都会影响除AF外的5个标志
    2. 无论执行结果如何,都会是标志位OF=CF= 0;
    3. ”非”运算指令的执行不影响标志位。

“与”指令

  1. 格式: AND dest,src
  2. 功能:将两个操作数按位相与结果送回目标操作数,即(dest)& (src)-> (dest).
  3. 特点:任何二进制位与1相与保持不变,与0相与结果为0.
  4. 应用场合:
    1. 实现两个操作数按位相与的运算.举例:AND BL,[SI]
    2. 使目标操作数的某些位不变,某些位清零. 举例:AND AL,0FH
    3. 在操作数不变的情况下是CF和OF清零。举例:AND AX,AX

“或”指令

  1. 格式: OR dest,src
  2. 功能:将两个操作数按位相或结果送回目标操作数,即(dest)   (src)-> (dest).
  3. 特点:任何二进制位与0相或保持不变,与1相或结果为1.
  4. 应用场合:
    1. 实现两个操作数按位相或的运算.举例:OR AX,[DI]
    2. 使某些位不变,某些位置1. 举例:OR CL,0FH
    3. 在操作数不变的情况下是CF和OF清零。举例:OR AX,AX

“非”指令

  1. 格式: NOT dest
  2. 功能:将目的操作数dest按位取反,送回目的操作数,(dest^)-> (dest).

“异或”指令

  1. 格式: XOR dest,src
  2. 功能:将两个操作数按位相异或结果送回目标操作数
  3. 特点:任何二进制位与0相异或保持不变,与1相异或结果取反.
  4. 应用场合:
    1. 实现两个操作数按位相异或的运算.举例:XOR BL,80H
    2. 在操作数不变的情况下是CF和OF清零。举例:XOR AX,AX

“测试”指令

  1. 格式: TEST dest,src
  2. 功能:将两个操作数按位与,结果丢弃,目的只影响各个状态标志位。即(dest)&(src);
  3. 应用场合:
    1. 常用于测试某些位的状态

移位指令

  1. 控制二进制位向左或向右移的指令
  2. 主要分为以下2类:
    1. 非循环移位指令
    2. 循环移位指令
  3. 移位指令的说明
    1. 指令格式在形式上为双操作数,本质上为单操作数
    2. 指令的目标操作数为被移动的对象,源操作数为移动的次数
    3. 当目标操作数为存储器操作数时,需要说明其字长
    4. 移动1位时由指令直接给出;移动2位以及以上位次数必须由CL指定
    5. 即指令的源操作数只能是1或者CL

非循环移位指令

  1. 包含以下2类
    1. 逻辑移位
      1. 把进行移位的操作数当做是无符号数,总是用0填补已空出的位。
    2. 算术移位
      1. 对带符号数进行移位,在移位过程中必须保持操作数的符号不变。
  2. 逻辑左移指令:
    1. 格式:SHL dest,1 或者 SHL dest,CL
    2. 功能:将目的操作数dest左移1位或左移CL中预置的位数,最高位移入CF中,其他依次左移,低位补0.
  3. 逻辑右移指令:
    1. 格式:SHR dest,1 或者 SHR dest,CL
    2. 功能:将目的操作数dest右移1位或右移CL中预置的位数,最低位移入CF中,其他依次右移,高位补0.
  4. 算术左移指令:
    1. 格式:SAL dest,1 或者 SAL dest,CL
    2. 功能:同逻辑左移一样
  5. 算术右移指令:
    1. 格式:SAR dest,1 或者 SAR dest,CL
    2. 功能:将目的操作数dest右移1位或右移CL中预置的位数,最低位移入CF中,其他依次右移,最高位用原数值的最高位补足。
  6. 非循环移位指令的应用场合
    1. 左移可以实现乘法运算
    2. 右移可以实现除法运算

循环移位指令

  1. 不带进位的循环左移指令
    1. 格式:ROL dest,1 或者 ROL dest,CL
    2. 功能: 将目的操作数dest循环左移1位或者CL中预置的位数,最高位移入CF的同时,也移入最低位,其他位依次左移,原CF中的内容消失。
  2. 不带进位的循环右移指令
    1. 格式:ROR dest,1 或者 ROR dest,CL
    2. 功能: 将目的操作数dest循环右移1位或者CL中预置的位数,最低位移入CF的同时,也移入最高位,其他位依次右移,原CF中的内容消失。
  3. 带进位的循环左移指令
    1. 格式:RCL dest,1 或者 RCL dest,CL
    2. 功能: 将目的操作数dest连同进位标志位CF一起循环左移1位或者CL中预置的位数,将CF的值移入最低位,其他位依次左移,原数值dest的最高位移入CF中。
  4. 带进位的循环右移指令
    1. 格式:RCR dest,1 或者 RCR dest,CL
    2. 功能: 将目的操作数dest连同进位标志位CF一起循环右移1位或者CL中预置的位数,将CF的值移入最高位,其他位依次右移,原数值dest的最低位移入CF中。
  5. 应用场景:
    1. 用于对某些位状态的测试
    2. 高位部分和低位部分的交换
    3. 与非循环移位指令一起组成32位或更长字长数据的移位
Table of Contents