微机原理与接口技术(三)
第三章 指令系统
指令系统基本概念
一、指令与指令系统
指令:控制计算机完成某种操作的命令
指令系统:处理器所能识别的所有指令的集合
指令的兼容性:同一系列机的指令都是兼容的
一条指令应包含的信息:运算数据的来源、运算结果的去向、执行的操作
二、指令格式
见图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
三种类型操作数的比较
立即数:
- 由指令直接给出,是常数性质
- 无地址含义,只表示运算的数据,不能作为目标操作数
寄存器操作数
- 表示运算的数据存放在寄存器中
- 多数情况下,寄存器操作数指通用寄存器
- 在三类操作数中所需运行时间最短
存储器操作数
- 表示运算的数据存放在内存
- 指令中“[ ]”里是数据所在单元的偏移地址
- 在三类操作数中所需时间最长
指令的寻址方式
操作数可能的来源或运算结果可能的去处:由指令直接给出、寄存器、内存单元
寻找操作数所在地址的方法可以有三种大类型:
- 指令直接给出的方式
- 运算对象由指令直接给出
- 存放于寄存器中的寻址方式
- 参加运算的数据存放在CPU的某个通用寄存器中
- 存放于存储器中的寻址方式
- 隐含给出方式
- 指令直接给出的方式
立即寻址
由指令直接给出运算的数据(操作数是立即数)。为常数形式或字符形式。
立即数只表示运算的数据,无地址含义:
立即寻址仅适于源操作数。即源操作数是参加操作的数据本身
见图31
寄存器寻址
参加操作的操作数在CPU的通用寄存器中。
- 例:
- MOV AX,BX
- 例:
此种寻址方式中的寄存器主要是通用寄存器
不含控制寄存器,段寄存器限制使用
存储器寻址
指令操作的对象在内存中表现形式为 [ ]
指令中给出运算对象在内存某个逻辑段中的偏移地址 [ 偏移地址 ]
逻辑段的段基地址通过默认或重设方式给出
存储器操作数的字长本身不确定,其字长取决于指令中另一个寄存器操作数,或通过其他方式指定字长
一、直接寻址
指令中直接给出操作数的偏移地址
例:MOV AX,[1200H]
直接寻址方式下,操作数默认为在数据段,但允许段重设,即由指令给出所在逻辑段
例:MOV AX,ES:[1200H]
- (ES:)为段重设符
二、间接寻址(寄存器间接寻址)
操作数存放在内存中,数据在内存中的偏移地址为方括号中通用寄存器的内容。
仅有4个通用寄存器可用于存放数据的偏移地址
- 间址寄存器:BX,BP,SI,DI
间接寻址的一般格式:[ 间址寄存器 ]
寄存器间接寻址例:
见图32
由寄存器间接给出操作数的偏移地址
存放偏移地址的寄存器称为间址寄存器(BX,BP,SI,DI)
操作数的段地址(数据处于哪个段)取决于选择哪一个间址寄存器:
- BX,SI,DI→默认在数据段
- BP→默认在堆栈段
三、相对寻址(寄存器相对寻址)
操作数的偏移地址为寄存器的内容加上一个位移量。
如:
- MOV AX,[BX+DATA]
- DATA为人以8bit或16bit常数
- 段地址由所选间址寄存器决定
- MOV AX,[BX+DATA]
例:
- MOV AX,2000H
- MOV DS,AX
- MOV BX,1200H
- MOV AL,[BX]5
- [BX]5 相当于 [BX+5]
见图33
- 相对寻址主要用于一维数组的操作
- 常将位移量作为”表头“地址,间址寄存器的值作为表内相对地址
四、基址、变址寻址
操作数的偏移地址为
- 一个基址寄存器的内容+一个变址寄存器的内容
操作数的段地址由选择的基址寄存器决定
- 基址寄存器为BX,默认在数据段
- 基址寄存器为BP,默认在堆栈段
基址变址寻址方式与相对寻址方式一样,主要用于一维数组操作
例:
见图34
[SI+BX] 也可表示为 [SI] [BX]
五、基址、变址、相对寻址
操作数的偏移地址为:
- 基址寄存器内容+变址寄存器内容+位移量
操作数的段地址由选择的基址寄存器决定
基址变址相对寻址方式主要用于二维表格操作
例:
见图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
- 数据段中的分布
见图37
②堆栈操作指令
堆栈操作的原则
- 先进后出
- 以字为单位
堆栈操作指令:
- 压栈指令
- 格式:PUSH OPRD ;16位寄存器或存储器两单元
- 出栈指令
- 格式:POP OPRD
- 压栈指令
压栈指令 PUSH
- SP-2→SP
- 操作数高字节→SP+1
- 操作数低字节→SP
见图38
- 出栈指令 POP
- SP→操作数低字节
- SP+1→操作数高字节
- SP←SP+2
见图39
- 堆栈操作指令说明
- 指令的操作数必须是16位
- 操作数可以是寄存器或存储器两单元,但不能是立即数
- 不能从栈顶弹出一个字给CS
- PUSH和POP指令在程序中一般成对出现
- PUSH指令的操作方向是从高地址,而POP指令的操作正好相反
见图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个或多个端口
- I/O端口:
见图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位偏移地址写入到目标寄存器
- 变量:内存单元的符号地址。属于存储器操作数。
- 将变量的16位偏移地址写入到目标寄存器
- 当程序中用符号表示内存偏移地址时,须使用该指令。
- 格式:
- LEA REG,MEM (MEM必须是存储操作数)
- 指令要求:
- 源操作数必须是一个存储器操作数,目标操作数通常是间址寄存器
见图42
- LEA指令在程序中的应用
- 将数据段中首地址为MEM1的50个字节的数据传送到同一逻辑段首地址为MEM2的区域存放。编写相应的程序段。
见图43
1 | LEA SI,MEM1 |
见图44
②LDS、LES指令
LDS和LES均用于将一个32位的远地址指针写入到目标寄存器
LDS(Load pointer using DS)的一般格式:
- LDS 通用寄存器,存储器操作数
LES(Load pointer using ES)的一般格式:
- LES 通用寄存器,存储器操作数
- 存储器操作数将源操作数的偏移地址送目标寄存器,将源操作数的段地址送ES
- LES 通用寄存器,存储器操作数
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
- 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
②ADC指令
指令格式、对操作数的要求、对标志位的影响与ADD指令完全一样
指令的操作:
- OPRD1+OPRD2CF→OPRD1
ADC指令多用于多字节数相加,使用前要先将CF清零
③INC指令
- 格式:INC OPRD (OPRD不能是段寄存器不能是立即数)
- 操作:OPRD+1→OPRD
- INC指令的执行不影响CF,但会影响其余五个状态标志位
- 常用于在程序中修改地址指针
加法指令例:
- 求内存数据段中M1为首和M2为首的两个20字节数之和,并将结果写入M2为首的区域中。
见图47
见图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 | MOV BL,2 |
④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 | LEA BX,MAX |
见图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
有符号数乘法指令
格式: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
1 | MOV DX,3F8H |
2、”或“运算指令
格式:OR OPRD1,OPRD2
操作:两操作数相”或“,结果送目标地址
”或“指令的应用
- 实现两操作数相”或“的运算
- OR AX,[DI]
- 使某些位不变,某些位置”1“
- OR CL,0FH
- 在不改变操作数的情况下使OF=CF=0
- OR AX,AX
- 实现两操作数相”或“的运算
”或“指令例
- 将一个二进制9变为字符‘9’
1 | MOV AL,9 |
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 | 方法1: |
1 | 方法2: |
1 | 方法3: |
移位操作指令
控制二进制位向左或向右移动的指令
- 非循环移位指令
- 循环移位指令
移位操作指令说明
- 指令格式在形式上为双操作数,本质上为单操作数
- 指令的目标操作数为被移动对象,源操作数为移动次数
- 当目标为存储器操作数时,需要说明其字长
- 移动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
算数右移
指令(有符号数的右移):
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 | LEA SI,M1 |
四、串操作指令
串操作指令说明
- 针对数据块或字符串的操作
- 可实现存储器到存储器的数据传送
- 待操作的数据串称为源串,目标地址称为目标串
- 串操作指令的操作对象是多个字节数(一串字符或数据),因此,指令的执行需要确定:
- 串所造的区域
- 串的首地址(原串、目标串起始地址)
- 串长度(大小)
- 串的操作方向
串操作指令的要求
- 串所在区域及首地址:
- 源串一般存放在数据段,偏移地址由SI(源串)指定。允许段重设。
- 目标串必须在符加段,偏移地址由DI(目标串)指定。
- 串长度:
- 串长度值由CX指定
- 串的操作方向:
- 由DF标志位决定。指令根据DF状态自动修改地址指针
- DF=0→增地址方向
- DF=1→减地址方向
- 由DF标志位决定。指令根据DF状态自动修改地址指针
- 通过增加重复前缀,可以实现对CX值的自动修改
- 串所在区域及首地址:
重复前缀
无条件重复
- REP
- 当CX≠0时,REP后的指令将继续重复执行
- 常用于传送类指令前→未传完则继续传送
- REP
条件重复
- 相等(为零)重复:REPE(REPZ)
- CX≠0 ∩ ZF=1,则前缀后的指令将继续重复执行
- 不相等(不为零)重复:REPE(REPZ)
- CX≠0 ∩ ZF=0,则前缀后的指令将继续重复执行
条件重复前缀常用于运算类指令前,当:
- 操作位结束 AND 结果=0 或者
- 操作位结束 AND 结果≠0
使其后的指令继续重复执行
- 相等(为零)重复:REPE(REPZ)
串操作指令流程
见图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
10LEA SI,MEM1
LEA DI,MEM2
MOV CX,200
NEXT:MOV AL,[SI]
MOV [DI],AL
INC SI
INC DI
DEX CX
JNZ NEXT
HLT1
2
3
4
5
6LEA 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
10LEA 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
15MOV 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
②无条件段间转移
转移的目标地址不在当前代码段内
目标地址为32位,包括段地址和偏移地址
目标地址→指令中直接给出目标地址→段间直接转移
目标地址→由指令中的32位存储器操作数指出目标地址→段间间接转移
段间直接转移
- 转移的目标地址由指令直接给出
- 格式:JMP FAR Label (FAR Label为远地址标号)
段间间接转移
段间间接寻址
- 转移的目标地址由指令中的32操作数给出
- 32位目标地址须存放于内存中
例:
- JMP DWORD PTR[BX]
见图55
无条件转移指令例:
见图56
见图57
见图58
(2)条件转移指令
在满足一定条件下,程序转移到目标地址继续执行
条件转移指令均为段内短转移,即转移范围为:-128—+127
基于1个标志位状态实现转移的指令:
- JC/JNC
- 判断CF的状态。常用于两个无符号数大小比较
- JZ/JNZ
- 判断ZF的状态。常用于循环体的结束判断
- JO/JNO
- 判断OF的状态。常用于有符号数溢出的判断
- JP/JPE、JNP/JPO
- 判断PF的状态。用于判断运算结果低8位中的个数是否为偶数
- JS/JNS
- 判断SF的状态。常用于判断数的性质
- JC/JNC
基于2个或3个标志位状态实现转移的指令:
- JA/JAE/JB/JBE
- 判断CF或CF+ZF的状态。常用于无符号数大小的比较
- JG/JGE/JL.JLE
- 判断SF+OF或SF+OF+ZF的状态。常用于有符号数大小的比较
- JA/JAE/JB/JBE
基于CX内容转移的指令
- JCXZ
- 可根据指令执行后CX的结果实现转移
- JCXZ
转移指令例:
统计内存数据段中以TABLE为首地址的100个8位带符号数中正数、负数和零元数的个数
基本思路:
- 可先将存放统计值的单元(或寄存器)清零
- 读取一个数,通过标志位的状态判断数的性质
- 最高位为1,则为负数
- 最高位为0,则为正数或零
流程图
见图59
- 程序代码
1 | START:XOR AL,AL |
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
18START: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
(2)段间调用
子过程与圆调用程序不在同一代码段→调用前需保护断点的段基地址和偏移地址
先将断点的CS压栈,再压入IP。
例:
见图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
- 中断指令例:
见图63
见图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种寻址方式
指令系统
- 数据传送类,算术运算类、逻辑运算和位移、串操作、程序控制、处理器控制
希望理解
- 指令的格式
- 不同类型指令对操作数的要求
- 不同类型指令的执行对标志位产生的影响
- 指令的执行原理
- 串操作指令,程序控制指令
关注点:
- 指令格式
- 单操做数指令,位移指令,串操作指令
- 操作数字长的一致性
- 一般情况下,条件转移指令应跟在对相应标志位影响的指令后
- ‘输入输出指令格式
- 程序控制类指令对堆栈区的影响
- 处理器控制指令的使用
- 指令格式