微机原理与接口技术(三)

第三章 指令系统

指令系统基本概念

一、指令与指令系统

  • 指令:控制计算机完成某种操作的命令

  • 指令系统:处理器所能识别的所有指令的集合

  • 指令的兼容性:同一系列机的指令都是兼容的

  • 一条指令应包含的信息:运算数据的来源、运算结果的去向、执行的操作

二、指令格式

见图29

29

  • 零操作数指令:操作码
  • 单操作数指令:操作码 操作数
  • 双操作数指令:操作码 操作数,操作数
  • 多操作数指令:三操作数及以上

三、指令中的操作数

  • 操作数:
    • 立即数:表征参加操作的数据本身
    • 寄存器:表征数据存放的地址
    • 存储器:表征数据存放的地址

立即数操作数

  • 立即数本身是参加操作的数据,可以是8位或16位,只能作为源操作数。

  • 例:

    • MOV AX,1234H
    • MOV BL,22H
  • 立即数无法作为目标操作数

  • 立即数可以是无符号或带符号数,数值符合其取值范围

寄存器操作数

  • 参加运算的数存放在指令给出的寄存器中,可以是16位或8位。
  • 例:
    • MOV AX,BX
    • MOV DL,CH

存储器操作数

  • 参加运算的数存放在存储器的某一个或两个单元中

  • 表现形式:操作数在内存中的偏移地址需 [ ] 扩起

  • 例:

    • MOV AL,[1200H]
    • MOV AX,[1200H]
    • AL=22H
    • AX=1122H

见图30

30

三种类型操作数的比较

  • 立即数:

    • 由指令直接给出,是常数性质
    • 无地址含义,只表示运算的数据,不能作为目标操作数
  • 寄存器操作数

    • 表示运算的数据存放在寄存器中
    • 多数情况下,寄存器操作数指通用寄存器
    • 在三类操作数中所需运行时间最短
  • 存储器操作数

    • 表示运算的数据存放在内存
    • 指令中“[ ]”里是数据所在单元的偏移地址
    • 在三类操作数中所需时间最长

指令的寻址方式

  • 操作数可能的来源或运算结果可能的去处:由指令直接给出、寄存器、内存单元

  • 寻找操作数所在地址的方法可以有三种大类型:

    • 指令直接给出的方式
      • 运算对象由指令直接给出
    • 存放于寄存器中的寻址方式
      • 参加运算的数据存放在CPU的某个通用寄存器中
    • 存放于存储器中的寻址方式
    • 隐含给出方式

立即寻址

  • 由指令直接给出运算的数据(操作数是立即数)。为常数形式或字符形式。

  • 立即数只表示运算的数据,无地址含义:

  • 立即寻址仅适于源操作数。即源操作数是参加操作的数据本身

见图31

31

寄存器寻址

  • 参加操作的操作数在CPU的通用寄存器中。

    • 例:
      • MOV AX,BX
  • 此种寻址方式中的寄存器主要是通用寄存器

  • 不含控制寄存器,段寄存器限制使用

存储器寻址

  • 指令操作的对象在内存中表现形式为 [ ]

  • 指令中给出运算对象在内存某个逻辑段中的偏移地址 [ 偏移地址 ]

  • 逻辑段的段基地址通过默认或重设方式给出

  • 存储器操作数的字长本身不确定,其字长取决于指令中另一个寄存器操作数,或通过其他方式指定字长

一、直接寻址

  • 指令中直接给出操作数的偏移地址

  • 例:MOV AX,[1200H]

  • 直接寻址方式下,操作数默认为在数据段,但允许段重设,即由指令给出所在逻辑段

  • 例:MOV AX,ES:[1200H]

    • (ES:)为段重设符

二、间接寻址(寄存器间接寻址)

  • 操作数存放在内存中,数据在内存中的偏移地址为方括号中通用寄存器的内容。

  • 仅有4个通用寄存器可用于存放数据的偏移地址

    • 间址寄存器:BX,BP,SI,DI
  • 间接寻址的一般格式:[ 间址寄存器 ]

  • 寄存器间接寻址例:

见图32

32

  • 由寄存器间接给出操作数的偏移地址

  • 存放偏移地址的寄存器称为间址寄存器(BX,BP,SI,DI)

  • 操作数的段地址(数据处于哪个段)取决于选择哪一个间址寄存器:

    • BX,SI,DI→默认在数据段
    • BP→默认在堆栈段

三、相对寻址(寄存器相对寻址)

  • 操作数的偏移地址为寄存器的内容加上一个位移量。

  • 如:

    • MOV AX,[BX+DATA]
      • DATA为人以8bit或16bit常数
      • 段地址由所选间址寄存器决定
  • 例:

    • MOV AX,2000H
    • MOV DS,AX
    • MOV BX,1200H
    • MOV AL,[BX]5
      • [BX]5 相当于 [BX+5]

见图33

33

  • 相对寻址主要用于一维数组的操作
  • 常将位移量作为”表头“地址,间址寄存器的值作为表内相对地址

四、基址、变址寻址

  • 操作数的偏移地址为

    • 一个基址寄存器的内容+一个变址寄存器的内容
  • 操作数的段地址由选择的基址寄存器决定

    • 基址寄存器为BX,默认在数据段
    • 基址寄存器为BP,默认在堆栈段
  • 基址变址寻址方式与相对寻址方式一样,主要用于一维数组操作

  • 例:

见图34

34

[SI+BX] 也可表示为 [SI] [BX]

五、基址、变址、相对寻址

  • 操作数的偏移地址为:

    • 基址寄存器内容+变址寄存器内容+位移量
  • 操作数的段地址由选择的基址寄存器决定

  • 基址变址相对寻址方式主要用于二维表格操作

  • 例:

见图35

35

[BP] [DI] 也可表示为 [BP+DI+5]

⭐隐含寻址

  • 指令中隐含了一个或两个操作数的地址,即操作数在默认的地址中。

  • 例:

    • MUL BL
  • 指令执行:

    • AL×BL→AX

小结:

  • 寻址方式表示指令运算对象的来源和运算结果的去向
  • 注意点:
    • 立即寻址仅针对源操作数
    • 寄存器寻址表示指令运算的数据在寄存器中(常为通用寄存器)
    • 存储器寻址表示指令运算的对象在内存中
      • 数据在内存中的偏移地址在 [ ] 中,段地址可以默认或重设
    • 存储器寻址和寄存器寻址均可用于源或目标操作数

寻址方式练习

  • 设DS=6000H,ES=2000H,SS=1500H,SI=00A0H,BX=0800H,BP=1200H,字符常数VAR为0050H。说明以下各条指令源操作数的寻址方式及存储器操作数的物理地址。
    • MOV AX,BX→寄存器寻址
    • MOV DL,80H→立即寻址
    • MOV AX,VAR[BX] [SI]→基址变址相对寻址 物理地址:608F0H
    • MOV AL,‘B’→立即寻址
    • MOV DI,ES:[BX]→寄存器间接寻址,物理地址:20800H
    • MOV DX,[BP]→寄存器间接寻址,物理地址:16200H
    • MOV BX,20H[BX]→寄存器相对寻址,物理地址:60820H

8086指令系统

  • 从功能上包括六大类:数据传送、算数运算、逻辑运算和位移、串操作、程序控制、处理器控制

一、数据传送指令

  • 通用数据传送指令
  • 输入输出指令
  • 地址传送指令
  • 标志传送指令

⭐除标志传送指令外,其他指令的执行对标志位不产生影响

1、通用数据传送指令

  • 一般数据传输指令
  • 堆栈操作指令
  • 交换指令
  • 查表转换指令
  • 字位扩展指令

⭐该类所有指令的执行均不影响标志位

①一般数据传输指令

  • 一般数据传输指令 MOV

  • 格式:MOV dest,src

  • 操作:src→dest

  • 例:MOV AL,BL

  • 注意点:

    • 两操作数字长必须相同
    • 两操作数不允许同时为存储器操作数
    • 两操作数不允许同时为段寄存器
    • 在源操作数是立即数时,目标操作数不能是段寄存器
    • IP和CS不作为目标操作数,FLAGS一般也不作为操作数在指令中出现
  • 例:

    • 判断下列指令的正确性:
      • MOV AL,BX→错误,两操作数字长不相等
      • MOV AX,[SI]05H→正确,源操作数为相对寻址
      • MOV [BX] [BP],BX→错误,目标操作数寻址方式错误
      • MOV DS,1000H→错误,不能用立即寻址方式为段寄存器
      • MOV DX,09H→正确
      • MOV [1200],[SI]
  • 一般数据传送指令应用例

    • 将(*)的ASCII码2AH送入内存数据段1000H开始的100个单元中。

    • 程序段:

      ​ MOV DI,1000H

      ​ MOV CX,64H

      ​ MOV AL,2AH

      AGAIN:MOV [DI],AL

      ​ INC DI ;DI+1

      ​ DEC CX ;CX-1

      ​ JNZ AGAIN ;CX≠0则继续

      ​ HLT

  • 上段程序在代码段中的存放形式

见图36

36

  • 数据段中的分布

见图37

37

②堆栈操作指令

  • 堆栈操作的原则

    • 先进后出
    • 以字为单位
  • 堆栈操作指令:

    • 压栈指令
      • 格式:PUSH OPRD ;16位寄存器或存储器两单元
    • 出栈指令
      • 格式:POP OPRD
  • 压栈指令 PUSH

    • SP-2→SP
    • 操作数高字节→SP+1
    • 操作数低字节→SP

见图38

38

  • 出栈指令 POP
    • SP→操作数低字节
    • SP+1→操作数高字节
    • SP←SP+2

见图39

39

  • 堆栈操作指令说明
    • 指令的操作数必须是16位
    • 操作数可以是寄存器或存储器两单元,但不能是立即数
    • 不能从栈顶弹出一个字给CS
    • PUSH和POP指令在程序中一般成对出现
    • PUSH指令的操作方向是从高地址,而POP指令的操作正好相反

见图40

40

③交换指令

  • 格式:XCHG REG,MEM/REG

  • 注:

    • 两操作数必须有一个是寄存器操作数
    • 不允许使用段寄存器
  • 例:

    • XCHG AX,BX
    • XCHG [2000],CL

④查表指令

  • 格式:XLAT

  • 说明:用BX的内容代表表格首地址,AL内容为表内位移量,BX+AL得到要查找元素的偏移地址

  • 操作:将BX+AL所指单元的内容送AL

⑤字位扩展指令

  • 将符号数的符号位扩展到高位

  • 指令位零操作数指令,采用隐含寻址,隐含的操作数为AX及AX,DX

  • 无符号数的扩展规则为在高位补0

  • 字节到字的扩展指令:

    • 格式:CBW
    • 操作:将AL内容扩展到AX
    • 规则:
      • 若最高位=1,则执行后AH=FFH
      • 若最高位=0,则执行后AH=00H
  • 字到双字的扩展指令

    • 格式:CWD
    • 操作:将AX内容扩展到DX AX
    • 规则:
      • 若最高位=1,则执行后DX=FFFFH
      • 若最高位=0,则执行后DX=0000H

2、输入输出指令

  • 关于I/O端口
    • I/O端口:
      • I/O接口中用于存储数据、可以直接被CPU访问的寄存器
    • 计算机输入输出系统中可以包含若干接口控制电路(芯片),每个接口中都包含了1个或多个端口

见图41

41

  • 专门面向I/O端口操作的指令

  • 端口地址在指令中的表示方式——寻址方式

  • 指令功能:

    • 从端口地址读入数据到累加器/将累加器的值输出到端口中
  • 指令格式:

    • 输入指令:IN acc,PORT(端口地址)
    • 输出指令:OUT PORT,acc(AL/AX)
  • 指令寻址方式

    • 根据端口地址码的长度,指令具有两种不同的端口地址表现形式
    • 直接寻址
      • 端口地址为8位时,指令中直接给出8位端口地址
      • 寻址256个端口
    • 间接寻址
      • 端口地址为16位时,指令中的端口地址必须由DX指定
      • 可寻址64K个端口
  • I/O指令例

    • IN AX,80H→从80H端口读入16bit数据到AX
    • MOV DX,2400H
    • IN AL,DX→从2400H端口读入8bit数据到AL
    • OUT 35H,AX→将AX的值写入到35H端口中
    • OUT AX,35H→错误,格式错误

3、地址传送指令

  • 取偏移地址指令LEA→取近地址指针

  • *LDS指令→取远地址指针

  • *LES指令→取远地址指针

①LEA指令

  • 操作:
    • 将变量的16位偏移地址写入到目标寄存器
      • 变量:内存单元的符号地址。属于存储器操作数。
  • 当程序中用符号表示内存偏移地址时,须使用该指令。
  • 格式:
    • LEA REG,MEM (MEM必须是存储操作数)
  • 指令要求:
    • 源操作数必须是一个存储器操作数,目标操作数通常是间址寄存器

见图42

42

  • LEA指令在程序中的应用
    • 将数据段中首地址为MEM1的50个字节的数据传送到同一逻辑段首地址为MEM2的区域存放。编写相应的程序段。

见图43

43

1
2
3
4
5
6
7
8
9
10
     LEA SI,MEM1
LEA DI,MEM2
MOV CL,50
NEXT:MOVE AL,[SI]
MOVE [DI],AL
INC SI
INC DI
DEC CL
JNZ NEXT
HLT

见图44

44

②LDS、LES指令

  • LDS和LES均用于将一个32位的远地址指针写入到目标寄存器

  • LDS(Load pointer using DS)的一般格式:

    • LDS 通用寄存器,存储器操作数
  • LES(Load pointer using ES)的一般格式:

    • LES 通用寄存器,存储器操作数
      • 存储器操作数将源操作数的偏移地址送目标寄存器,将源操作数的段地址送ES

4、标志传送指令

  • LAHF (Load AH from Flags) //隐含操作数AH
  • SAHF (Store AH into Flags) //隐含操作数AH
  • PUSHF (Push flages onto stack) //隐含操作数FLAGS
  • POPF (Pop flags off stack) //隐含操作数FLAGS

LAHF,SAHF

  • 指令格式:

    • LAHF
  • 操作:将FLAGS的低8位装入AH

见图45

45

  • SAHF执行与LAHF相反的操作

二、算数运算类指令

  • 加法运算指令
  • 减法运算指令
  • 乘法指令
  • 除法指令

算数运算指令的执行大多对状态标志位会产生影响

1、加法运算指令
  • 普通加法指令ADD
  • 带进位位的加法指令ADC
  • 加1指令INC

①ADD指令

  • 格式:

    • ADD OPRD1,OPRD2
  • 操作:

    • OPRD1+OPRD2→OPRD1
  • ADD指令的执行对全部6个状态标志位都产生影响

  • ADD指令例:

    • MOV AL,78H
    • ADD AL,99H
    • 指令执行后6个状态标志位的状态

见图46

46

②ADC指令

  • 指令格式、对操作数的要求、对标志位的影响与ADD指令完全一样

  • 指令的操作:

    • OPRD1+OPRD2CF→OPRD1
  • ADC指令多用于多字节数相加,使用前要先将CF清零

③INC指令

  • 格式:INC OPRD (OPRD不能是段寄存器不能是立即数)
  • 操作:OPRD+1→OPRD
  • INC指令的执行不影响CF,但会影响其余五个状态标志位
  • 常用于在程序中修改地址指针

加法指令例:

  • 求内存数据段中M1为首和M2为首的两个20字节数之和,并将结果写入M2为首的区域中。

见图47

47

见图48

48

2、减法运算指令
  • 普通减法指令SUB
  • 考虑借位的减法指令SBB
  • 减1指令DEC
  • 比较指令CMP
  • 求补指令NEG

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

①SUB指令

  • 格式:SUB OPRD1,OPRD2
  • 操作:OPRD1-OPRD2→OPRD1
  • 对标志位的影响与ADD指令同

②SBB指令

  • 指令格式、对操作数的要求、对标志位的影响与SUB指令完全一样

  • 指令的操作:OPRD1-OPRD2-CF→OPRD1

  • SBB指令多用于两个多字节数的相减运算

③DEC指令

  • 格式:DEC OPRD

  • 操作:OPRD-1→OPRD

  • 指令对操作数的要求及对标志位的影响与INC相同

  • 指令常用于在程序中修改计数值

  • 应用程序例(功能:延时(定时)):

1
2
3
4
5
6
7
      MOV BL,2
NEXT1:MOVE CX,0FFFFH
NEXT2:DEX CX
JNZ NEXT2 ;ZF=0转NEXT2
DEC BL
JNZ NEXT1 ;ZF=0转NEXT1
HLT ;暂停执行

④NEG指令

  • 格式:NEG OPRD (OPRD为8/16位寄存器或存储器操作数)

  • 操作:0-OPRD→OPRD

  • 对一个负数取补码就相当于用零减去此数

  • 说明:

    • 执行NEG指令后,一般情况下都会使CF为1,除非给定的操作数为零才会使CF为0;
    • 当指定的操作数的值为80H(-128)或为8000H(-32768),则执行NEG指令后结果不变,但0F置1,其他情况下OF均置0。
    • 用0减去操作数,可以得到负数的绝对值

⑤CMP指令

  • 格式:CMP OPRD1,OPRD2

  • 操作:OPRD1-OPRD2

  • 指令执行的结果不影响目标操作数,仅影响标志位

  • 用途:用于比较两个数的大小,可作为条件转移指令转移的条件

  • 指令对操作数的要求及对标志位的影响与SUB指令相同

  • 两个无符号数的比较:

    • CMP AX,BX

      • 若AX≥BX→CF=0

      • 若AX<BX→CF=1

      • 若AX=BX→CF=0,ZF=1

  • 两个带符号数的比较

    • CMP AX,BX
    • 两个数的大小由OF和SF共同决定
      • OF和SF状态相同 AX≥BX
      • OF和SF状态不同 AX<BX
  • CMP指令例:

1
2
3
4
5
6
7
8
9
10
11
12
	 LEA BX,MAX
LEA SI,BUF
MOV CL,20
MOV AL,[SI]
NEXT:INC SI
CMP AL,[SI]
JNC GOON ;CF=0转移
XCHG [SI],AL
GOON:DEC CL
JNZ NEXT
MOV [BX],AL
HLT

见图49

49

3、乘除运算指令
  • 说明:
    • 有分别针对无符号数和有符号数运算指令
      • 有不同的指令助记符
    • 乘、除运算指令均采用隐含寻址方式
    • 乘除运算指令对操作数的要求与加减不同

①乘法指令

无符号的乘法指令MUL

带符号的乘法指令IMUL

注意点:乘法指令采用隐含寻址,隐含了存放被乘数的累加器AL或AX,以及存放结果的AX或AX,DX;

  • 无符号数乘法指令

    • 格式:MUL OPRD (OPRD不能说立即数)

    • 操作:

      • OPRD为字节数→AL×OPRD→AX
      • OPRD为16位数→AX×OPRD→DXAX

    无符号数乘法指令例:

    • MUL BYTE PTR[BX]

    见图50

    50

  • 有符号数乘法指令

    • 格式:IMUL OPRD

    • 指令格式及对操作数的要求与MUL指令相同。

    • 指令执行原理:

      ①将两个操作数取补码(对负数按位取反加1,正数不变)

      ②做乘法运算;

      ③将乘积取补码。

②除法指令

  • 无符号除法指令

    • 格式:DIV OPRD
  • 有符号除法指令

    • 格式:IDIV OPRD

除法指令的操作:

  • 若OPRD是字节数

    • 执行:AX/OPRD
    • 结果:
      • AL=商 AH=余数
  • 若OPRD是双字节数

    • 执行:DXAX/OPRD
    • 结果:
      • AX=商 DX=余数
  • 指令要求被除数是除数的双倍字长

算数运算指令小结

  • 算数运算类指令的执行会影响状态标志位。其中
    • INC和DEC指令的执行不会影响CF
  • 该类指令中,全部双操作数指令对操作数的要求与MOV指令完全相同;所有单操做数指令都要求操作数:
    • 不能是立即数
    • 如果是存储器操作数,需要声明操作数的字长(用PTR运算符)
  • 乘法运算中:乘积是乘数的双倍字长
  • 除法指令要求被除数是除数的双倍字长

三、逻辑运算指令和移位操作指令

逻辑运算指令
  • 逻辑运算

    • 基本逻辑运算:
      • 与、或、非
      • 异或
    • 逻辑运算指令→实现逻辑操作的指令
      • 与、或、非、异或
  • 逻辑运算指令

    • 对操作数的要求:
      • 大多与MOV指令相同
      • “非”运算指令要求操作数不能是立即数
    • 对标志位的影响
      • 除“非”运算指令,其余指令的执行都会影响除AF外的5个状态标志
      • 无论执行结果如何,都会使标志位OF=CF=0
      • “非”运算指令的执行不影响标志位

1、“与”运算指令

  • 格式:AND OPRD1,OPRD2

  • 操作:两操作数相“与”,结果送目标地址

  • “与“运算指令的应用:

    • 实现两操作数按位相与的运算
      • AND BL,[SI]
    • 使目标操作数的某些位不变,某些位清零
      • AND AL,0FH
    • 在操作数不变的情况下使CF和OF清零
      • AND AX,AX
  • ”与“指令应用例

    • 从地址为3F8H端口中读入一个字节数,如果该数bit1位为1,则可从38FH端口将DATA为首地址的1个字输出,否则就不能进行数据传送。
    • 要求:
      • 编写相应的程序段

见图51

51

1
2
3
4
5
6
7
	 MOV DX,3F8H
WATT:IN AL,DX
AND AL,02H
JZ WATT ;ZF=1转移
MOV DX,38FH
MOV AX,DATA
OUT DX,AX

2、”或“运算指令

  • 格式:OR OPRD1,OPRD2

  • 操作:两操作数相”或“,结果送目标地址

  • ”或“指令的应用

    • 实现两操作数相”或“的运算
      • OR AX,[DI]
    • 使某些位不变,某些位置”1“
      • OR CL,0FH
    • 在不改变操作数的情况下使OF=CF=0
      • OR AX,AX
  • ”或“指令例

    • 将一个二进制9变为字符‘9’
1
2
MOV AL,9
OR AL,30H

3、”非“运算指令

  • 格式:NOT OPRD
  • 操作:操作数按位取反再送回原地址
  • 注:指令的执行对标志位无影响
  • 例:NOT BYTE PTR[BX]

4、”异或“运算指令

  • 格式:XOR OPRD1,OPRD2
  • 操作:两操作数相”异或“,结果送目标地址
  • 例:
    • XOR BL,80H
    • XOR AX,AX

5、”测试“指令

  • 格式:TEST OPRD1,OPRD2

  • 操作:执行”与“运算,但运算的结果不送回目标地址

  • 应用:常用于测试某些位的状态

  • 例:

    • 从地址为3F8H的端口中读入一个字节数,当该数的bit1,bit3,bit5位同时为1时,可从38FH端口将DATA为首地址的一个字输出,否则就不能进行数据传送
    • 编写相应的程序段
1
2
3
4
5
6
7
8
9
10
11
12
13
方法1:
LEA SI,DATE
MOV DX,3F8H
WATT:IN AL,DX
TEST AL,02H
JZ WATT ;ZF=1转移
TEST AL,08H
JZ WATT
TEST AL,20H
JZ WATT
MOV DX,38FH
MOV AX,[SI]
OUT DX,AX
1
2
3
4
5
6
7
8
9
10
方法2:
LEA SI,DATE
MOV DX,3F8H
WATT:IN AL,DX
AND AL,2AH
CMP AL,2AH
JNZ WATT
MOV DX,38FH
MOV AX,[SI]
OUT DX,AX
1
2
3
4
5
6
7
8
9
10
方法3:
LEA SI,DATE
MOV DX,3F8H
WATT:IN AL,DX
AND AL,2AH
XOR AL,2AH
JNZ WATT
MOV DX,38FH
MOV AX,[SI]
OUT DX,AX
移位操作指令
  • 控制二进制位向左或向右移动的指令

    • 非循环移位指令
    • 循环移位指令
  • 移位操作指令说明

    • 指令格式在形式上为双操作数,本质上为单操作数
    • 指令的目标操作数为被移动对象,源操作数为移动次数
      • 当目标为存储器操作数时,需要说明其字长
    • 移动1位时由指令直接给出;移动两位及以上时,移位次数必须由CL指定
    • 指令源操作数只能是1或CL

1、非循环移位指令

  • 逻辑左移

    • 指令(无符号数):

      SHL OPRD,1

      SHL OPRD,CL

  • 算数左移

    • 指令(有符号数):

      SAL OPRD,1

      SAL OPRD,CL

  • 逻辑右移

    • 指令(无符号数的右移):

      SHR OPRD,1

      SHR OPRD,CL

    • 例:

      MOV AL,68H

      MOV CL,2

      SHR AL,CL

      见图52

      52

  • 算数右移

    • 指令(有符号数的右移):

      SAR OPRD,1

      SAR OPRD,CL

    • 右移八位后会都变成符号位

  • 应用

    • 左移可实现乘法运算
    • 右移可实现除法运算

2、循环移位指令

  • 不带进位位的循环移位

    • 左移ROL
    • 右移ROR
  • 带进位位的循环移位

    • 左移RCL
    • 右移RCR
  • 应用

    • 用于对某些位状态的测试
    • 高位部分和低位部分的交换
    • 与非循环移位指令一起组成32位或更长字长数的移位

例题:

  • 在内存数据段M1为首地址的4个单元中存放了4个压缩BCD码

  • 要求:将这4个压缩BCD码分别转换为ASCII码,并将转换结果存放在同一逻辑段、M2为首的单元中。

  • 题目分析:

    • 压缩BCD码是用4位二进制码表示1位十进制数(1字节表示2位压缩BCD)
    • 转换ASCII码时需要分别转换高4位(十位数)和低4位(个位数)
    • 0~9的ASCII码的高4位均为0011(03H)
    • 转换低4位时应先使高4位清零,转换高4位时须先将高4位移动到低4位的位置。
  • 程序例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
     LEA SI,M1
LEA DI,M2
MOV CH,4
Next:MOV AL,[SI]
MOV BL,AL
AND AL,0FH
OR AL,30H
MOV [DI],AL
INC DI
MOV AL,BL
MOV CL,4
SHR AL,CL
OR AL,30H
MOV [DI],AL
INC DI
INC SI
DEX CH
JNZ Next
HLT

四、串操作指令

  • 串操作指令说明

    • 针对数据块或字符串的操作
    • 可实现存储器到存储器的数据传送
    • 待操作的数据串称为源串,目标地址称为目标串
    • 串操作指令的操作对象是多个字节数(一串字符或数据),因此,指令的执行需要确定:
      • 串所造的区域
      • 串的首地址(原串、目标串起始地址)
      • 串长度(大小)
      • 串的操作方向
  • 串操作指令的要求

    • 串所在区域及首地址:
      • 源串一般存放在数据段,偏移地址由SI(源串)指定。允许段重设。
      • 目标串必须在符加段,偏移地址由DI(目标串)指定。
    • 串长度:
      • 串长度值由CX指定
    • 串的操作方向:
      • 由DF标志位决定。指令根据DF状态自动修改地址指针
        • DF=0→增地址方向
        • DF=1→减地址方向
    • 通过增加重复前缀,可以实现对CX值的自动修改
  • 重复前缀

    • 无条件重复

      • REP
        • 当CX≠0时,REP后的指令将继续重复执行
        • 常用于传送类指令前→未传完则继续传送
    • 条件重复

      • 相等(为零)重复:REPE(REPZ)
        • CX≠0 ∩ ZF=1,则前缀后的指令将继续重复执行
      • 不相等(不为零)重复:REPE(REPZ)
        • CX≠0 ∩ ZF=0,则前缀后的指令将继续重复执行

      条件重复前缀常用于运算类指令前,当:

      • 操作位结束 AND 结果=0 或者
      • 操作位结束 AND 结果≠0

      使其后的指令继续重复执行

  • 串操作指令流程

    见图53

    53

    • 若按增地址方向操作,串操作结束时:
      • 串传送指令:指针将指向串尾+1
      • 串比较类指令:指针将指向结束位+1
    • 若按减地址方向操作,串操作结束时:
      • 串传送指令:指针将指向串尾-1
      • 串比较类指令:指针将指向结束位-1
串操作指令
  • 串传送MOVS
  • 串比较CMPS
  • 串扫描SCAS
  • 串装入LODS
  • 串送存STOS

1.串传送指令

  • 功能:

    • 将源数据串传送到目标地址
  • 格式:

    ① MOVS OPRD1,OPRD2 (此格式仅用于源操作数需段重设的情况下)

    ② MOVSB (用来字节传送)

    ③ MOVSW (用来字传送)

  • 串传送指令常与无条件重复前缀连用

  • 串传送指令例:

    • 分别用MOV指令和MOVS指令编写将200个字节数据从内存数据段MEM1为首地址的区域送到同一逻辑段MEM2为首地址的区域中的程序。
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
         LEA SI,MEM1
    LEA DI,MEM2
    MOV CX,200
    NEXT:MOV AL,[SI]
    MOV [DI],AL
    INC SI
    INC DI
    DEX CX
    JNZ NEXT
    HLT
    1
    2
    3
    4
    5
    6
    LEA SI,MEM1
    LEA DI,MEM2
    MOV CX,200
    CLD
    REP MOVSB
    HLT

2.串比较指令

  • 功能:

    • 用于实现两个数据传的比较
  • 操作:

    • 目标串-源串,结果不屑回目标地址
    • 常与条件重复前缀连用
  • 格式:

    ① CMPS OPRD1,OPRD2

    ② CMPSB

    ③ CMPSW

  • 前缀的操作对标志位不影响

  • 传比较指令例:

    • 测试上例串传送中200个字节数据是否传送正确

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
           LEA SI,MEM1
      LEA DI,MEM2
      MOV CX,200
      CLD
      REPE CMPSB ;结束串比较指令的条件1.CX=0;2.CX不等于0,但ZF=0
      JZ STOP ;两数据串相同
      DEC SI ;指向存放不相等数据的地址
      MOV AL,[SI] ;获取不相等数据及
      MOV BX,SI ;存放该数据的地址
      SYOP:HLT

3.串扫描指令

  • 常用于在指定存储区域中寻找某个关键字

  • 格式:

    • SCAS OPRD (OPRD为目标操作数)
    • SCASB
    • SCASW
  • 执行与CMPS指令相似的操作,区别是:

  • 这里的源操作数是AX或AL

  • 传扫描指令应用例:

    • 在ES段中从2000H单元开始存放了10个字符,寻找其中有无字符“A”。若有则记下搜索次数,将搜索次数写入到DATA1单元,并将存放“A”的地址写入DATA2单元。
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
         MOV DI,2000H
    MOV BX,DI
    MOV CX,0AH
    MOV AL,'A'
    CLD
    REPNZ SCASB
    JZ FOUND
    MOV DI,0
    JMP DONE
    FOUND:DEC DI
    MOV MATA2,DI
    INC DI
    SUB DI,BX
    DONE:MOV DATA1,DI
    HLT

4.串装入指令

  • 格式:

    • LODS OPRD (OPRD为源操作数)
    • LODSB
    • LODSW
  • 操作:

    • 对字节:AL←[DS:SI]
    • 对字:AX←[DS:SI]
  • 用于将内存某个区域的数据串依次装入累加器,以便显示或输出到接口。

  • LODS指令一般不加重复前缀

5.串存储指令

  • 格式:
    • STOS OPRD (OPRD为目标操作数)
    • STOSB
    • STOSW
  • 操作:
    • 对字节:AL→[ES:DI]
    • 对字:AX→[ES:DI]
  • 串存储指令的应用
    • 常用于内存某个区域置同样的值
    • 此时:
      • 将带送存的数据放入AL(字节数)或AX(字数据)
      • 确定操作方向(增地址/减地址)和区域大小(串长度值)
      • 使用串存储指令+无条件重复前缀,实现数据传送

串操作指令应用注意事项

  • 需要定义附加段
    • 目标操作数必须在附加段
  • 需要设置数据的操作方向
    • 确定DF的状态
  • 源串和目标串指针分别为SI和DI
  • 串长度值必须由CX给出
  • 注意重复前缀的使用方法
    • 传送类指令前加无条件重复前缀
    • 串比较类指令前加条件重复前缀,但前缀不影响ZF状态

五、程序控制指令

  • 程序控制类指令的本质是:

    • 控制程序的执行方向
  • 决定程序执行方向的因素:

    • CS,IP
    • 同时修改CS和IP,回使程序走向另一个代码段执行
  • 程序控制类指令以“隐含”的方式修改CS和IP,以现实控制程序走向的目的(Intel指令集不允许由指令直接修改CS和IP)

  • 通过修改IP或CS和IP,实现程序的三种基本控制结构

    • 顺序,选择(分支),循环
  • 重点为如何实现对CS和IP的修改

程序控制类指令
  • 转移指令
  • 循环指令
  • 过程指令
  • 中断指令

1.转移指令

  • 通过修改指令的偏移地址或段地址及偏移地址实现程序的转移

  • 无条件转移指令→无条件转移到目标地址

    条件转移指令→当具备一定条件时(通常值状态标志位)转移到目标地址

(1)无条件转移指令

  • 格式:JMP OPRD

  • 可以实现在当前代码段内或段间转移

  • OPRD→目标地址→与JMP在同一代码段

    OPRD→目标地址→与JMP不在同一代码段

①无条件段内转移

  • 转移的目标地址在当前代码段内,段地址不改变。

  • 即:目标地址是16位偏移地址

  • 目标地址→指令中直接给出目标地址→段内直接转移

    目标地址→由指令中的寄存器或存储器操作数指出目标地址→段内间接转移

段内直接转移

  • 转移的目标地址由指令直接给出
  • 格式:JMP Label (Label为近地址标号)
  • 下一条要执行指令的偏移地址=当前IP+位移量

段内间接转移

  • 转移的目标地址存放在某个16位寄存器或存储器的某两个单元中

  • 例:

    • MOV BX,1200H
    • JMP BX

    执行完上述指令后:

    • IP=1200H
  • 例2:

见图54

54

②无条件段间转移

  • 转移的目标地址不在当前代码段内

  • 目标地址为32位,包括段地址和偏移地址

  • 目标地址→指令中直接给出目标地址→段间直接转移

    目标地址→由指令中的32位存储器操作数指出目标地址→段间间接转移

段间直接转移

  • 转移的目标地址由指令直接给出
  • 格式:JMP FAR Label (FAR Label为远地址标号)

段间间接转移

  • 段间间接寻址

    • 转移的目标地址由指令中的32操作数给出
    • 32位目标地址须存放于内存中
  • 例:

    • JMP DWORD PTR[BX]

    见图55

    55

无条件转移指令例:

见图56

56

见图57

57

见图58

58

(2)条件转移指令

  • 在满足一定条件下,程序转移到目标地址继续执行

  • 条件转移指令均为段内短转移,即转移范围为:-128—+127

  • 基于1个标志位状态实现转移的指令:

    • JC/JNC
      • 判断CF的状态。常用于两个无符号数大小比较
    • JZ/JNZ
      • 判断ZF的状态。常用于循环体的结束判断
    • JO/JNO
      • 判断OF的状态。常用于有符号数溢出的判断
    • JP/JPE、JNP/JPO
      • 判断PF的状态。用于判断运算结果低8位中的个数是否为偶数
    • JS/JNS
      • 判断SF的状态。常用于判断数的性质
  • 基于2个或3个标志位状态实现转移的指令:

    • JA/JAE/JB/JBE
      • 判断CF或CF+ZF的状态。常用于无符号数大小的比较
    • JG/JGE/JL.JLE
      • 判断SF+OF或SF+OF+ZF的状态。常用于有符号数大小的比较
  • 基于CX内容转移的指令

    • JCXZ
      • 可根据指令执行后CX的结果实现转移

转移指令例:

  • 统计内存数据段中以TABLE为首地址的100个8位带符号数中正数、负数和零元数的个数

  • 基本思路:

    • 可先将存放统计值的单元(或寄存器)清零
    • 读取一个数,通过标志位的状态判断数的性质
      • 最高位为1,则为负数
      • 最高位为0,则为正数或零
  • 流程图

见图59

59

  • 程序代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
START:XOR AL,AL
MOV PLUS,AL
MOV MINUS,AL
MOV ZERO,AL
LEA SI,TABLE
MOV CX,100
CLD
CHECK:LODSB
OR AL,AL
JS X1
JZ X2
INC PLUS
JMP NEXT
X1: INC MINUS
JMP NEXT
X2: INC ZERO
NEXT: DEC CX
JNZ CHECK
HLT

2.循环指令

  • 循环范围:

    • 以当前IP为中心的-128~+127范围内循环
  • 循环次数由CX寄存器指定

  • 循环指令:

    LOOP→无条件循环指令

    LOOPZ→条件循环指令

    LOOPNZ→条件循环指令

(1)无条件循环指令

  • 格式:LOOP LABEL

  • 循环条件:CX≠0

  • 操作:

    • 完全相当于:

      • DEC CX

        JNZ 符号地址

(2)条件循环指令

  • 功能:先使CX-1,再根据CX中的值及ZF值来决定是否继续循环

  • 格式:

    • LOOPZ Label →继续循环的条件:CX≠0,且ZF=1
    • LOOPNZ Label→继续循环的条件:CX≠0,且ZF=0
  • 例:

    • 在以DATA为首地址的内存数据段中,存放有200个16位有符号数,试找出其中最大和最小的符号数,并分别放在MAX和MIN为首的内存单元中。

    • 题目分析:

      • 先取数据块中第1个数,将其同时暂存于MAX和MIN中
      • 循环读取其它数并分别与MAX和MIN中的数进行比较
        • 若大于则取代元MAX中的数;若小于MIN内容,则将新数放于MIN中。直到结束
      • 注:有符号数比较应采用JG和JL等用于符号数的条件转移指令
    • 程序代码

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      START:LEA SI,DATA
      MOV CX,200
      CLD
      LODSW
      MOV MAX,AX
      MOV MIN,AX
      DECC CX
      NEXT: LODSW
      CMP AX,MAX
      JG LARGE
      CMP AX,MIN
      JL SMALL
      JMP GOON
      LARGE:MOV MAX,AX
      JMP GOON
      SMALL:MOV MIN,AX
      GOON: LOOP NEXT
      HLT

3.过程指令

  • 过程调用指令

    • 用于调用一个子过程
  • 与转移指令的比较

    • 子过程执行结束后要返回原调用处
      • 必须保护返回地址
  • 调用指令的执行过程

    ①保护断点

    • 将调用指令的下一条指令的地址(断点)压入堆栈

    ②获取子过程的入口地址

    • 子过程第1条指令的地址

    ③执行子过程

    • 功能实现,参数的保存及恢复

    ④恢复断点,返回原程序

    • 将断点偏移地址由堆栈弹出

    断点保护和恢复由系统自动完成,但会影响堆栈的栈顶指针

过程调用指令

  • 段内调用
    • 段内直接调用
      • 直接调用:指令中直接给出走过场的入口地址
    • 段内间接调用
      • 间接调用:由内存获得子过程的入口地址
  • 段间调用
    • 段间直接掉用
      • 直接调用:指令中直接给出走过场的入口地址
    • 段间间接调用
      • 间接调用:由内存获得子过程的入口地址

(1)段内调用

  • 被调用程序与调用程序在同一代码段

    • 调用前只需保护断点的偏移地址
  • 例:

    见图60

    60

(2)段间调用

  • 子过程与圆调用程序不在同一代码段→调用前需保护断点的段基地址和偏移地址

  • 先将断点的CS压栈,再压入IP。

  • 例:

    见图61

    61

返回指令

  • 功能:从堆栈中弹出断点地址,返回源程序
  • 格式:RET
  • 子程序的最后一条指令必须是RET

4.中断指令

  • 中断的概念
    • 某种异常或随机事件(中断源)使处理器暂时停止正在运行的程序,转去执行一段特殊处理程序,并在处理结束后返回原程序被中断处继续执行的过程。
  • 中断指令:
    • 引起CPU产生异常中断的指令
  • 中断与过程调用:
    • 相似点:
      • 从一个正在执行的过程转向另一个过程(处理程序),并在执行完后返回原程序继续执行
    • 区别:
      • 中断是随机事件或异常事件引起,调用是事先已在程序中安排好
      • 调用指令在指令中直接给出子程序入口地址,中断指令只给出中断向量码,入口地址则在向量码指向的内存单元中。
      • 调用可以是近过程调用或远过程调用,中断处理程序均为远过程
      • 响应中断请求不仅要保护断点地址,还要保护FLAGS内容

(1)中断指令

  • 格式:INT n (n为中断类型码,n=0~255)

  • 说明:

    • n*4

      存放中断服务子程序入口地址的单元的偏移地址

      该单元在数据段,段地址=DS

  • 中断指令的执行过程(硬件系统完成)

    ①将FLAGS压入堆栈

    ②将INT指令的下一条指令的CS、IP压栈

    ③由n×4得到存放中断向量的地址

    ④将中断向量(中断服务程序入口地址)送CS和IP寄存器

    ⑤转入中断服务程序

  • 中断指令的执行过程

见图62

62

  • 中断指令例:

见图63

63

见图64

64

(2)中断返回指令

  • 格式:IRET
  • 中断服务程序的最后一条指令,负责:
    • 恢复断点
    • 恢复标志寄存器内容

六、处理器控制指令

  • 这类指令用来对CPU进行控制,如修改标志寄存器,使CPU暂停,使CPU与外部设备同步等

  • 对标志位的操作

    与外部设备的同步

  • 处理器控制指令的控制对象是CPU

  • 操作指令均为零操作数格式指令

标志位操作指令
  • 置标志位状态
    • CLC CF←0 ;清进位标志位
    • STC CF←1 ;进位标志位置位
    • CMC CF← 非CF ;进位标志位取反
    • CLD DF←0 ;清方向标志位,串操作从低地址到高地址
    • STD DF←1 ;方向标志位置位,串操作从高地址到低地址
    • CLI IF←0 ;清中断标志位,即关中断
    • STI IF←1 ;中断标志位置位,即开中断

指令系统小结

  • 基本概念

    • 指令的操作数
  • 8种寻址方式

  • 指令系统

    • 数据传送类,算术运算类、逻辑运算和位移、串操作、程序控制、处理器控制
  • 希望理解

    • 指令的格式
    • 不同类型指令对操作数的要求
    • 不同类型指令的执行对标志位产生的影响
    • 指令的执行原理
      • 串操作指令,程序控制指令
  • 关注点:

    • 指令格式
      • 单操做数指令,位移指令,串操作指令
    • 操作数字长的一致性
    • 一般情况下,条件转移指令应跟在对相应标志位影响的指令后
    • ‘输入输出指令格式
    • 程序控制类指令对堆栈区的影响
    • 处理器控制指令的使用