微机原理基础
计算机基础
微型计算机组成
硬件结构
微处理器、微型计算机、微型计算机系统
微处理器
- 功能:运算和控制中心,提供运算,判断能力
- ALU,CU,Register
- CPU位数:4,8,16,32,64
- 指的是数据总线宽度,CPU一次能处理的数据位数
运算器
- 算数逻辑单元,以加法器为基础,加减乘除
控制器
- 指令寄存器,指令译码器,操作控制电路
- 操作:取指令,指令译码,发出控制信号
寄存器
-
分类:
-
专用名称:AX,DX,BX
-
通用寄存器:暂时存放一些需要重复使用的操作数和中间结果
-
专用寄存器:堆栈指针SP,程序计数器PC,标志寄存器F
-
存储器
-
功能:存放程序,数据
-
内存:只读存储器ROM,随机存储RAM
-
RAM,断电数据就丢失了
ROM,断电不丢失信息
-
外存:光盘啥的
-
内存容量地址
-
1MB=1024KB 1KB=1024B 每个存储单元都被编排不同号码
-
内存的操作
- 读:CPU将内存单元内容取到CPU内部,并不改变被读单元的内容
- 写:CPU将内部信息传送到内存单元保存起来,被写单元内容改变
- 内存读写的步骤
- cpu把要读的内存单元的AB上
- 写操作,CPU紧接着把要写入的数据放到DB上
- CPU发出写命令
- 数据被写入指定单元或从指定单元独处DB
- 若是读操作,CPU紧接着从DB上取回数据
总线
- 连接多个功能部件的一组公共信号线
- 地址总线AB:地址线的根数决定了CPU的寻址范围
- 数据总线DB:数据总线决定CPU一次最多可以传送的数据宽度
- 控制总线CB:用来传送各种控制信号
微型计算机软件系统
程序操控硬件
位和字节
字长
- 字长是微处理器一次可以直接处理二进制数码位数,取决于微处理器内部通用寄存器位数和数据总线宽度
内存容量
- 内存单元个数,以字节为单位
- 内存空间:又称存储空间,
- 寻址范围:指的是微机寻址能力,和cpu总线宽度有关
微型计算机指标
主频
- 主频也叫时钟频率,表示微处理器运行速度
- 主频=外部总线频率x倍频系数
- 超频:提高外频或倍频系数,可以使微处理器在更高的时钟频率
MIPS
- 由于执行不同类型的指令所需要时间长度不同,MIPS通常是根据不同指令出现的频度上不同系数求的平均值
计算机中数和运算
数制
用一组和一套统一规则表示数目
基数
数制中所含数字符号个数
常见数制
二进制八进制十进制十六进制
表示
权重
任何一个数值,都是各位数字本身和它权之积的总和
进制之间的转换
1.短除法
2.按权展开法
二进制-->八进制 | 八进制-->二进制
从最低位二进制数3位一组 | 小数点为界1位八进制数对应3位二进制数
八进制-->十进制
按权展开
十六进制-->十进制
按权展开
二进制-->十六进制
从小数点起二进制数4位一组,变为十六进制
十六进制-->二进制
小数点为界十六进制数对应4位二进制数
编码体系
计算机中符号数表示
-
二进制数的符号由最高位表示
-
0表示+
-
1表示-
-
机器数:数在机器中编码表示
-
真值:机器数对应的十进制数值
-
模数:一个计量器的容量
-
对模数理解:
一个有n位计数器,每一位有R种状态,每种状态代表1个数,从0开始计数 计数器所能计的数值个数就是模数 计数器模数=计数器最大值+1 计数器模数(R的n次方)取决于基数R和位数n 例子:2位十进制计数器模数是多少 基数-->10 位数-->2 模数-->100=99+1 模数决定计数器表示数值最大数量
$$
$$
机器数的三种编码方法
原码反码补码
例子
求复数的补码的方法:
先写出复数对应的正数的二进制表示
连同符号位一起按位取反,然后再加上1
真值转换为补码
补码转换为真值
正数补码的真值X=[X]
负数补码和与正数的补码之间存在
- 当x是负数时候,对补码求补,是x的补码
- 对负数求补的结果是负数对应的正数的补码,也就是负数的绝对值
- 负数补码求真值的方法,将负数补码按位取反末尾加1,就得到负数补码对应的真值的绝对值
溢出的判断方法
-
同号相减或异号相加--不会溢出
-
同号相加或异号相减--可能溢出
-
同号相加,结果符号与加数符号相反---溢出
-
异号相减,结果符号与减数符号相同---溢出
8086微处理器
微处理器功能
- 进行逻辑运算
- 译码,寄存
- 存储器,IO接口通信
- 数据暂存
- 控制信号
- 响应请求
微处理器组成
- 运算器
- 控制器
- 寄存器阵列
- 内部总线,总线缓冲器
运算器
算数逻辑单元
与或非
寄存器组
暂存
内部总线
数据传送通道
控制器
- 指令控制
- 时序控制
- 操作控制
组成
程序计数器,存放下一跳要执行指令在存储器中的地址
指令寄存器,存放存储器中取出待执行的指令
指令译码器,翻译指令
时序控制部件,产生时序信号
微操作控制部件,微操作
8086,8088微处理器
8088数据总线是8位,8086是16位
总线接口,执行部件,BIU,EU组成
总线
控制cpu存储器,IO信息传送,形成0位物理地址
四个寄存器
CS,DS,SS,ES
段地址和地址偏移量
CS:代码段寄存器
DS:数据段
ES:扩展段
SS:堆栈段
指令寄存器IP
IP:偏移地址,与段寄存器CS相加,形成20位物理地址
20位地址加法器
指令队列
指令队列6字节,总线接口部件BIU内存存取指令
执行部件EU
通用数据寄存器
AX,BX,CX,DX,AL,BL,CL,DL
SP:堆栈指针
内容与堆栈寄存器SS,内容相加,物理地址
BP:基址指针
偏移地址一部分
SI:源地址
串操作时来操作放数据段DS指定单元的偏移地址
状态标志 6位
控制标志3位
BIU和EU动作管理
- 8086指令队列有两个空字节,BIU自动取指令到指令队列
- 执行部件EU准备执行一条指令,从BIU指令队列取指令,然后执行
- 指令访问存储器IO接口执行单元BIU发出请求,由BIU通过总线获取存储数据
- 指令队列已满,BIU与EU又无总线请求,总线接口部件进入空闲状态
- 执行转移指令,调用指令,返回指令,BIU自动清除指令队列然后从新地址取指令
指令流水线结构
两个单元既独立又协调
存储器组织
存储容量
20条地址总线,寻址空间1MB
存储器分段
存储器一个段64KB
物理地址 00000H--FFFFFH
物理地址 = 段地址X16+偏移地址
偏移地址
偏移地址是某存储单元相对于其所在起始位置偏移字节数,简称偏移量
存储器分段组织带来的存储器管理新特点
数据量在64kb范围内
特殊的内存区域
内存区域是固定的
中断矢量区:00000H—003FFH共1K字节,用以存放256种中断类型的中断矢量,每个中断矢量占用4个字节,共256×4=1024=1K
显示缓冲区:B0000H—B0F9FH约4000(25×80×2)字节,是单色显示器 的显示缓冲区,存放文本方式下,所显示字符的ASCII码及属性码;B8000H—BBF3FH约16K字节,是彩色显示器的显示缓冲区,存放图形方式下,屏幕显示象素的代码。
启动区:FFFF0H—FFFFFH共16个单元,用以存放一条无条件转移指令的代码,转移到系统的初始化部分。
8086芯片引脚图
两种模式功能相同的32个引脚
- MN/MX:最大最小模式控制
最小模式接5v
最大模式接地
- VCC 40脚 +5v电源引出脚
GND,接地引出脚
- AD15-AD0地址数据线分时复用AD15~AD0为地址信号;
T2、T3、TW、T4状态:数据信号 - A19/S6—A16/S3(35-38脚)
- BHE/S7 T1状态: 为BHE 信号,BHE 低电平时AD15—AD8有效,高电平时使用AD7-AD0低八位数据线。
T2、T3、TW、T4状态:为S7信号,在8086中无意义。
标志寄存器 清零
指令指针 000H
CS:FFFFH
DS.ES.SS 000H
指令队列:空
其它寄存器:0000H
最小模式
8086在最小模式下的典型配置:
1、MN/MX接+5V;
2、一片8284,作为时钟发生器;
3、三片8282或74LS373,作地址锁存器;
4、二片8286/8287,作数据收发器;
最大模式
多处理系统,所有的总线控制信号均为8288产生,系统中总线控制逻辑电路介绍
引线接地,处于最大组态
1、 QS1、QS2(25、24):队列状态信号。
协处理器8087:硬件实现高精度整数浮点段运算
输入输出协处理器8089:相当于DMA通道处理器
增加协处理器,不在占用8086时间
3、RQ/GT1、 RQ /GT0(双向,引脚30、 31)
请求允许信号可供CPU以外的两个处理器发总线请求
RQ/GT0优先级比RQ/GT1更高。
LOCK(输出三态,29)
总线锁定信号由指令前缀产生,最大模式是多处理器系统,共用一条外部总线,需要增加总线控制器,完成处理器分时控制
最大模式与最小模式差别
最小模式:
MN/MX接+5V,只有 8086一个CPU,
控制信号由CPU产生
最大模式
MN/MX接地,除8086一个主CPU外,还有一个以上协处理器,需要总线控制器来变换和组合控制信号。
80888086数据线与地址线状态线是分时复用的
cpu内存,IO端口之间在时间上匹配主要靠READY信号
RD信号与MIO配合使用,指明内存或者IO端口读信息哦
高4位地址线与状态线分时复用,在TT1状态,输出地址信息其余状态,输出状态信息
80868088时序概念
时钟周期:CPU的基本时间单位。微处理器在运行过程中是按照统一的时钟一步一步的执行每一个操作,每个时钟脉冲的持续时间成为一个时钟周期(T)。
总线周期:4个T状态 ,CPU通过总线进行一次读或写的过程成为一个总线周期。
机器周期只执行一条指令需要的时间,一个机器周期你包含若干个总线周期
8086操作时序
总线读操作
最小方式下总线读操作
T1状态
A19—A0上是地址信息,出现ALE信号后,将地址锁存到地址锁存器(8282)
T2状态
地址信息消失,A19-A16从地址信息变为状态信息S6-S3。
数据允许信号DEN在T2状态有效。RD信号有效,RD=0
T3状态
AD0~AD15上出现数据
TW状态
若存储器式外设的工作速度较慢,不能满足基本时序要求,使用一个产生READY的电路,以使在T3状态之后,插入一个等待周期TW
T4状态
CPU采样数据,结束一个总线周期
总线写操作
最小模式下总线操作
T1状态:A19—A0上是地址信息,出现ALE信号后, 将地址锁存到地址锁存器(8282)。
T2状态:地址信息消失,A19-A16从地址信息变为状态信息S6-S3。
T3状态:AD0~AD15上出现数据。
WR信号有效。WR=0。
TW状态:若存储器式外设的工作速度较慢,不能满足基本时序要求,使用一个产生READY的电路,以使在T3状态之后,插入一个等待周期TW。
T4状态:CPU认为数据已写入存储器或IO端口,结束一个总线周期。
最大模式下总线读操作
读信号RD(低电平有效)
总线控制器由S2,S1S0产生
存储器读信号IORC(低电平)
最大模式下总线读操作时序
T1状态: A19—A0上是地址信息,总线控制器输出ALE信号后,将地址锁存到地址锁存器(8282)。
T2状态:地址信息消失,CPU输出状态信息
S2-S0。总线控制器输出DEN,
MRDC或IORC。
T3状态:AD0~AD15上出现数据。
S2、S1、S0为高电平,总线进入无
源状态。
T4状态:CPU采样数据,结束一个总线周期。
中断响应操作
总线保持与响应操作
系统复位与启动
总线
总线是一组信号线的组合,是计算机各系统部件之间传输地址,数据和控制信息的公共通路
公用型
总线上任何一个部件发出信息都可以被连接总线上其他所有设备接收,但在某一时刻一个设备进行信息传送
数据总线
地址总线
控制总线
8086指令系统
指令:控制计算机完成指定操作命令
指令系统:处理器所能执行的指令合集叫指令·系统
指令分为六类
数据传送类
算术运算类
逻辑运算和位移
串操作
控制转移
处理器控制
指令的构成
指令由两部分构成:操作码字段,操作数字段
操作码:用来说明指令要完成的操作
操作数字段:该指令操作对象,可直接给出操作数,或操作数存放的寄存器编号,或操作数存放的存储单元地址或有关地址信息
立即数
立即数智能用作源操作数,而不能用作目的操作数
寄存器操作数
操作数放在8086的8个通用寄存器4个段寄存器,源操作数,也可以是,目的操作数
存储器操作数
存储单元物理地址=段基地址+偏移地址
如果指令中没有指明所涉及的段寄存器,cpu就采用默认的段寄存器1来确定所操作数的所在段
8086的寻址方式
寻址方式:寻找操作数的方法
寻找操作数的地址(源操作数)
寻找执行下一条指令地址
立即寻址
操作数直接指令给出
mov ax,1c8fh
mov vyte ptr[2A00H],8FH
直接寻址
指令中直接给出操作数16位偏移地址
默认的段寄存器DS,也可以显式的指定其他段寄存器
偏移地址也可以用符号地址表示
mov ax,[2A00H]
mov dx,es:[2A00H]
寄存器寻址
操作数放在某个寄存器中源操作数与目的操作数字长要相同
寄存器寻址与段地址无关
mov ax,bx
mov [3F00H],AX
mov cl,al
寄存器间接寻址
操作数的偏移地址(有效地址EA)放在寄存器中
寄存器相对寻址
EA=间址寄存器内容加上一个9/16位位移量
寄存器相对寻址常用于存取表格或一维数组元素,把表格起始地址为位移量,元素下标值放在间
mov ax,[bx+8]
mov cx,table[si]
mov ax,[bp+10000h],默认段寄存器是SS
基址-变址寻址
若操作数偏移地址
由基址寄存器(bx,bp):基址寻址方式
由变址寄存器(si,di)变址寻址方式
由一个基址寄存器内容和一个变址寄存器的内容相加而形成的操作数的偏移地址,叫基址变址寻址
MOV AX, [BX] [SI]
MOV AX, [BX+SI]
MOV AX, DS: [BP] [DI]
使用相抵基址变址寻址可以很方便的访问二维数组
隐含寻址
指令操作数是隐含的,在指令中未显式的指明
AL + BL=AX
指令隐含了被乘数AL及乘积AX
总结
指令执行的时间
一条指令执行时间
取指令
取操作数
执行指令
传送结果
单位用时钟周期数表示
尽量用寄存器作为操作数
如果可能,用移位代替乘除法
尽量使用简单的寻址方式
执行指令时间,由时钟周期长短执行指令所需要的时钟周期数决定
访问内存操作执行一条指令时间为基本执行水花四溅加上计算有效地址所需要的时间
指令系统可以分为
- 数据传送
- 实现数据地址立即传送到寄存器存储器单元
- 通用数据传送指令
-
- 传送指令MOV
- mov dest,src
- 双操作指令不能传送到段寄存器中
- 目的操作数不允许使用CS段寄存器
- dest与src必须类型匹配,即同时是字节或字类型,
- 存储器-存储区
- mov ax,mem1
- mov memm2,ax
- 段寄存器-段寄存器
- mov ax,ds
- mov es,ax
- 段寄存器-立即数
- mov ax,data
- mov ds,ax
- 堆栈操作PUSH,POP
- 指令格式:进栈 push src
- (SP) (SP)-2,((SP)+1,(SP)) (SRC)
- 出栈 pop dst
- (DST) ((SP)+1,(SP)),(SP) (SP)+2
- 堆栈:存储器一段区域后进先出存储区域,堆栈是字单位进行弹出操作,段地址知识msp寄存器指针,sp内容始终向栈顶所在存储单元
- 保存断点地址,暂时存放操作数,参数传递功能
- 交换指令XCHG
- 查表转换XLAT
- 字位扩展
- 传送指令MOV
- 目标地址传送指令
- 标志传送指令
- 输入输出传送
- 算数运算
- 逻辑
- 串操作
- 考及格内置转移
- 处理器
push和pop:堆栈操作指令
指令
进栈 push src
出栈 pop dst
堆栈
存储器的一段区域,按“后进先出(LIFO)”方式工作的存储区域。堆栈以字为单位进行压入弹出操作。 8086/8088系统中,堆栈位于堆栈段,其段地址由SS指示,SP寄存器作为指针,SP内容始终指向栈顶所在存储单元。
作用:保存断点地址;暂时存放操作数;参数传递等功能(见下页图)
堆栈特点
先进后出
栈顶栈底指向同一个内存单元
ss:sp 在任何时候都指向当前的栈顶
ss指示堆栈段的段基址,堆栈指针sp始终指向堆栈的顶部,sp初值规定所用的堆栈区的大小,堆栈最高地址栈底
压栈指令
PUSH src ; src为16位操作数
例:PUSH AX ;将AX内容压栈
执行操作:(SP)-1←高字节AH
(SP)-2←低字节AL
(SP)←(SP)- 2
指令格式
压栈指令的格式为:
PUSH reg
PUSH mem/reg
PUSH seg/reg
例如:
PUSH AX
PUSH [BX]
PUSH DS
弹出
POP dest
例:POP BX ;将栈顶内容弹至BX
执行操作:(BX)←(SP)
(SP)←(SP)+2
堆栈指令
- 堆栈操作总是按字进行
- 不能从栈顶弹出一个字给cs
- 堆栈指针是ss:sp,sp永远指向找你打个
- sp自动进行增减量
XCHG交换指令
格式
XCHG oprd1 , oprd2 ;交换oprd1与oprd2的内容
XCHG reg/mem,reg/mem
功能:交换量操作数内容
两操作数中必须有一个在寄存器中,操作数不能为段寄存器和立即数,源和目的操作数类型要一致
XLAT 查表
根据表项序号查出表对应的代码,执行时先将表首地址送到BX
MOV BX,2000H ;(BX)←表首地址
MOV AL,0BH ;(AL)←序号
XALT ; 查表转换
执行后得到:(AL)= 42H = ’ B’
CBW和CWD字节自转换
格式 CBW 把AL符号位复制到AH
CWD把AX符号位复制到 DX
用于有符号数的除法
AL=A7H,执行CBW,AX内容FFA7H
目标地址传送指令
将操作数所在存储器地址送入目标寄存器
指令
有效地址送寄存器: LEA reg16 , mem ;
把源操作数的有效地址送目标寄存器。
指针送寄存器和DS:LDS reg16 ,mem32 ;
把源操作数指定的4个相继字节送到由指令指定的寄存器及DS寄存器中。该指令常指定SI寄存器。
指针送寄存器和ES:LES reg16 ,mem32 ;
把源操作数指定的4个相继字节送到由指令指定的寄存器及ES寄存器中。该指令常指定DI寄存器 。
LEA 指令与MOV指令的区别
LEA SI,BUFF指令是将标号BUFF的偏移地址送入寄存器
MOV SI,BUFF指令是将标号所指的存储单元内容送入SI
注意以下两条指令
LEA BX,BUFFER 将符号地址 BUFFER 的存储单元偏移地址
MOV BX,BUFFER 后者将BUFFER存储单元内容取到BX中
下面两条指令等效
LEA BX,BUFFER
MOV BX, OFFSET BUFFER
其中OFFSET BUFFER表示存储器单元BUFFER的偏移地址。二者都可用于取存储器单元的偏移地址,但LEA指令可以取动态的地址,OFFSET只能取静态的地址。
LDS或LES指令将源操作数指定4个连续字节单元内容分别送入指令指定的寄存器以及DS或ES中
标志传送指令
LAHF
SAHF
PUSHF
POPF
说明:LAHF/SAHF指令是寄存器AH与标志寄存器PSW的低字节 之间完成的字节型数据传送。
PUSHF/POPF指令是标志寄存器PSW与堆栈间进行的字型数据传送。
指令SAHF/POPF将影响标志位。
读指令
LAHF:把标志寄存器低8位5个标志位传送到AH指定位
SAHF:与LAHF功能正好相反,只要将5个箭头反向以下
把标志寄存器推入栈顶指令PUSHF
执行的操作:(SP)-1←标志寄存器高8位
(SP)-2←标志寄存器低8位
(SP)←(SP)-2
4)从栈顶弹出标志寄存器指令POPF
执行的操作:标志寄存器低8位←(SP)
标志寄存器高8位←(SP)+1
(SP)←(SP)+2
PUSHF和POPF指令用于保护和恢复标志寄存器内容。
例:
PUSH AX
PUSH CX
PUSHF ;保护标志寄存器内容
;这段程序要用到AX,CX以及标志位
POPF ;恢复标志寄存器内容
POP CX
POP AX
数据传送指令中,除SAHF和POPF这两条指令外,其余所有指令均不影响标志位。
输入输出I/O指令
只限于累加器AL或AX传送
功能:累加器--I/O端口
输入指令IN
IN acc PORT 直接寻址,,直接寻址
IN acc DX ,DX端口范围达64K,寄存器间接寻址
输出指令OUT
OUT port acc
OUT DX,acc
例:OUT 68H,AX ;(69H,68H)←(AX)
OUT DX,AL ;((DX))←(AL)
在使用间接寻址,IN/OUT,要事先用传送指令把IO端口号设置到DX寄存器
MOV DX,220H
IN AL,DX ;将220H端口内容读入AL
算数运算
无符号和有符号,对加减法,无符号
参加的操作数必须都是无符号或都是有符号数
需要使用不同标志位来检查无符号和有符号数运算结果是否溢出
四则运算是计算机经常进行的一种操作。算术运算指令实现二进制(和十进制)数据的四则运算。
请注意算术运算指令对标志的影响
掌握:ADD/ADC/INC SUB/SBB/DEC/NEG/CMP
熟悉:MUL/IMUL DIV/IDIV
理解:CBW/CWD DAA/DAS AAA/AAS/AAM/AAD
两个8位相加有4种情况
1.无符号数和有符号均不溢出
2.无符号数溢出
3.有符号数溢出
4.无符号数和有符号数均溢出
CF标志可用来表示无符号数溢出,0F标志可用来表示有符号数溢出
加法
(1) 不带进位的加法指令ADD
格式: ADD acc, data
ADD mem/reg, data
ADD mem/reg1, mem/reg2
例:ADD AL,30H
ADD AX,[BX+20H]
ADD CX,SI
ADD [DI],200H
ADD指令对标志位(指状态标志)都有影响。
带进位加法指令ADC
ADC指令在形式上和功能上都有与ADD类似,知识相加还要包括进位标志CF
ADC AL,68H ;AL←(AL)+68H+(CF)
ADC AX,CX ;AX←(AX)+(CX)+(CF)
ADC BX,[DI] ;BX←(BX)+[DI+1][DI] +(CF)
例:有两个4字节的无符号数相加:
2C56F8AC+309E47BE=?
设被加数、加数分别存放在BUFFER1及BUFFER2开始的两个存储区内,结果放回BUFFER1存储区,如下页图所示。
因CPU只能进行8位或16位的加法运算,为此可将加法分4次进行。
多字节加法示意图
程序段如下:
MOV CX,4 ;置循环次数
MOV SI,0 ;置SI初值为零
CLC ;清进位标志CF
LL: MOV AL,BUFFER2[SI] ;寄存器相对寻址
ADC BUFFER1[SI],AL ;带进位加
INC SI ;(SI)+1
DEC CX ;(CX)-1
JNZ LL ;若(CX)0,则转LL
思考:若最高位有进位,如何改?
ADD/ADC条件标志位(CF/OF/ZF/SF)影响
SF
SF
1 结果为负
0 否则
ZF
1 结果为0
0 否则
CF 1和最高的有效位有向高位进位
0 否则
OF
1 两个操作数符号相同,而结果符号与之相反
0否则
CF表示无符号数相加溢出
OF表示带符号数相加的溢出
加1指令INC(单操作数指令)
格式:INC reg/mem
功能:类似于C语言中的++操作:对指定的操作数加1
例: INC AL
INC SI
INC BYTE PTR[BX+4]
注:本指令不影响CF标志。
减法指令
不考虑借位的减法指令
格式: SUB dest, src
操作: dest←(dest)-(src)
源和目的操作数不能同时为存储器操作数
立即数不能作为目的操作数
例:
SUB AL,60H
SUB [BX+20H],DX
SUB AX,CX
例:x、y、z均为32位数,分别存放在地址为X, X+2;Y,Y+2;Z,Z+2的存储单元中,用指令序列实现wx+y+24-z,结果放在W, W+2单元中。
MOV AX, X
MOV DX, X+2
ADD AX, Y
ADC DX, Y+2 ; x+y
ADD AX, 24
ADC DX, 0 ; x+y+24
SUB AX, Z
SBB DX, Z+2 ; x+y+24-z
MOV W, AX
MOV W+2, DX ; 结果存入W, W+2单元
考虑借位减法指令SBB
SBB指令主要用于多字节的减法。
格式: SBB dest, src
操作: dest←(dest)-(src)-(CF)
例: SBB AX,CX
SBB WORD PTR[SI],2080H
SBB [SI],DX
SUB/SBB对标志位OF/CF/ZF/SF影响
CF =1 表示无符号减法溢出
0F=1 表示带符号数减法溢出
减1指令DEC
作用类似于C语言中的”--”操作符。
格式:DEC opr
操作:opr←(opr)-1
例:
DEC CL
DEC BYTE PTR[DI+2]
DEC SI
DEC 02H ?
求补指令NEC
格式: NEG opr
操作: opr← 0-(opr)
对一个负数操作数取补码相当于用0减去此操作数,故利用NEG指令可得到负数的绝对值。
例:若(AL)=0FCH,则执行 NEG AL 后,
(AL)=04H,CF=1
本例中,0FCH为-4的补码,执行求补指令后,即得到4(-4的绝对值)。
NEG 对CF/OF影响
CF:操作数为0,求补结果使CF=0,否则CF=1
OF:字节运算对-128求补或字运算对-32768求补时OF=1 否则OF=0
例:内存数据段存放了100个带符号数,首地址为AREA1,要求将各数取绝对值后存入以AREA2为首地址的内存区。
LEA SI,AREA1
LEA DI,AREA2
MOV CX,100
K1: MOV AL,[SI]
OR AL,AL
JNS NEXT ; 结果不为负则转移
NEG ;求补码
NEXT: MOV [DI],AL
INC SI
INC DI
LOOP K1
比较指令CMP
格式: CMP dest, src
操作: (dest)-(src)
CMP是执行两个操作数相减,但结果不送目标操作数,结果使反在标志位上
例:
CMP AL,0AH
CMP CX,SI
CMP DI,[BX+03]
根据标志位来判断比较结果
根据ZF判断两个数是否相等,若ZF=1则两数相等
若两个数不相等,则分两种情况
比较的是两个无符号数
若CF=0,dst>src
CF =1dst<src
比较的是两个有符号数
OF+SF =0 dst>src
OF+=SF=1 dst<src
比较指令在使用时候一般在后面紧跟一条条件转移指令,判断比较结果专项
例:比较AL、BL、CL中带符号数的大小,将最小数放在AL中。
程序: CMP AL,BL ;AL和BL比较
JNG BBB ;若AL≤BL,则转
XCHG AL,BL ;若AL>BL,则交换
BBB: CMP AL,CL ;AL和CL比较
JNG CCC ;若AL≤CL,则转
XCHG AL,CL ;若AL>CL,则交换
CCC: HLT
例:在内存数据段从DATA开始的存储了两个8位无符号数,试比较它们的大小,并将大数存入MAX单元。
MOV BX,OFFSET DATA
MOV AL,[BX]
INC BX
CMP AL,[BX]
JNC DONE
MOV AL,[BX]
DONE:MOV MAX,AL
乘法指令
无符号数乘法指令·MUL
格式: MUL src
操作:字节操作数 (AX) (AL) × (src)
字操作数 (DX, AX) (AX) × (src)
例: MUL BL ;(AL)×(BL),乘积在AX中
MUL CX ;(AX)×(CX),乘积在DX,AX中
MUL BYTE PTR[BX]
有符号数乘法 IMUL
格式与MUL指令类似,只是要求两操作数均为有符号数。
例:
IMUL BL ;(AX)←(AL)×(BL)
IMUL WORD PTR[SI] ;(DX,AX)←(AX)×([SI+1][SI])
MUL/IMULL
AL(AX)是隐含的乘数级寄存器
AX(DX,AX)是隐含的乘积寄存器
源操作数不能是立即数
除CF和OF 外,对其他标志位无定义
乘法对CF/OF影响
例:设(AL)=FEH,(CL)=11H,求AL与CL的乘积。
(AL)=FEH为无符号数的254D,有符号数的- 2D,
(CL)=11H无符号数的17D,有符号数的+17D,
*执行MUL CL
(AX)=10DEH(4318D),因AH中的结果不为零,故CF=OF=1。
*执行IMUL CL
(AX)=FFDEH(-34D),因AH中的内容为AL中的符号位扩展,故CF=OF=0。
*对FEH求补为02H,02H×11H=22H再求补为FFDEH(-34D)
除法指令
除法 16/8位 -- 8位商
32/16 –16
无符号数DIV
格式
格式: DIV src
操作:字节操作 (AL) (AX) / (SRC) 的商
(AH) (AX) / (SRC) 的余数
字操作 (AX) (DX, AX) / (SRC) 的商
(DX) (DX, AX) / (SRC) 的余数
例: DIV CL
DIV WORD PTR[BX]
注:若除数为零或AL中商大于FFH(或AX中商大于FFFFH),则CPU产生一个类型0的内部中断。
有符号数除法指令IDIV
操作与DIV相似,商和余数都是有符号数,且余数符号总是与被除数相同
AX是隐藏的被除数寄存器
AL是隐含的余数寄存器
src不能是立即数
对所有条件均无定义
除法运算要求辈出数字长时的两倍,若不满足则需要对被除数进行扩展,否则产生错误
对于无符号数除法扩展,只需要将AH或DX清零即可
对有符号,则是符号位扩展
例: 写出34H÷25H的程序段。
MOV AL,34H
MOV BL,25H
CBW ; AL的符号扩展到AH
IDIV BL ; 0034H÷25H,结果为
; (AH)=0FH余数, (AL)=01H商
逻辑运算指令
运算规则:按位操作,无进借位
对标志位影响(NOT指令外)
CF OF SF ZF PF AF
0 0 * * * 无定义
逻辑’与‘ AND
对两个操作数进行按位逻辑“与”操作。
格式:AND dest, src
用途:保留操作数的某几位,清零其他位。
保持操作数不变,但影响标志位,同时使CF=OF=0
例1:保留AL中低4位,高4位清0。
AND AL, 0FH
例2:AL中有字符’a’~’z’, 将其转换成大写。
AND AL, 01011111B
例3:测试AL的bit7,bit5,bit2是否都是1,则转YES。
AND AL, 10100100B
CMP AL, 10100100B
JZ YES ; if match, go to YES
… … ; if not match
… …
YES: … … ; goes here if all ‘1’
逻辑OR
对两个操作数进行按位逻辑或操作
对两个操作数进行按位逻辑”或”操作。
格式:OR dest, src
用途:对操作数的某几位置1操作;对两操作数进行组合。(“逻辑加” )
例1:把AL中的非压缩BCD码变成相应十进制数的ASCII码。
OR AL, 30H
例2:把AH和AL中的非压缩BCD码组合成压缩的BCD码, 放到AL中。
MOV CL, 4
SHL AH, CL
OR AL, AH
例3:把AL的第5位置为1
OR AL, 00100000B
逻辑非取反NOT
对操作数进行按位逻辑”非”操作。 单目运算
格式:NOT mem/reg
例:NOT CX
NOT BYTE PTR[DI]
逻辑异或XOR
对两个操作数按位进行”异或”操作。
格式:XOR dest, src
用途:对reg清零(自身异或)
把reg/mem的某几位变反(与’1’异或)
例1:把AX寄存器清零。
例2:把DH的bit4,3变反
① MOV AX,0
XOR DH,18H
② XOR AX,AX
③ AND AX,0
④ SUB AX,AX
测试指令 TEST
操作与AND指令类似,但不将与结果送回,只影响标志位
TEST指令常用于位测试,与条件转移指令一起用
例:测试AL的内容是否为负数。
TEST AL,80H ;检查AL中D7=1?
JNZ MINUS ;是1(负数),转MINUS
… … ;否则(正数)不转移
MINUS: … …
… …
例3:测试某端口地址为PORT的外设端口输入的数据,若输入数据的第bit5,bit3,bit1位中的任一位不等零,则转移到NEXT。
TEST AL, 00101010B
JNZ NEXT
… …
NEXT: … … ;
例:在TABLE开始的内存区中,存放了100个字节的十六进制数,求累加和,并将累加和的低位存SUM单元,高位存SUM+1单元。
LEA BX,TABLE
MOV CL,100
XOR AX,AX
K1: ADD AL, [BX]
JNC GO
INC AH
GO: INC BX
DEC CL
JNZ K1
MOV SUM,AX
算数指令
算数左移 SAL
算数右移 SAR
逻辑左移 SHL
逻辑右移 SHR
算数一维--把操作数看做有符号数
逻辑一维-把操作数看做无符号数
移位位数放在CL寄存器中,如果只移1位,也可以直接在指令中
MOV CL,4
SHR AL,CL
影响 CF,SF,ZF,OF
结果未溢出 左移1位 = 操作数*2 右移1位=操作数/2
例:把AL中的数x乘10
因为10=8+2=23+21,所以可用移位实现乘10操作。程序如下:
SHL AL,1 ; 2x
MOV AH,AL
SHL AL,1 ; 4x
SHL AL,1 ; 8x
ADD AL,AH ; 8x+2x = 10x
用移位操作代替乘除法提高速度
例:前例中计算 x×10。
(1)采用乘法指令:
MOV BL,10
MUL BL
共需70~77个T周期。
(2)采用移位和加法指令:
SAL AL,1 ; 2T
MOV AH,AL ; 2T
SAL AL,1 ; 2T
SAL AL,1 ; 2T
ADD AL,AH ; 3T
只需11个T周期,仅相当于乘法的1/7。
例:将一个16位无符号数除以512。该数存放在TAB为首地址的存储单元中。
因为TAB÷512=(TAB÷2)÷256,因此可用逻辑右移指令完成。
MOV AX,[TAB]
SHR AX,1 (AX)=TAB÷2
XCHG AL,AH;相当右移8位
CBW
例:假设(DI)=0064H,(CL)=05H,则执行指令SAR DI,CL后,(DI)=0003H,(CF)=0,(SF)=0,(ZF)=0,(PF)
=1(有符号数)
例:MOV AX,0FF81H ;(AX)=-127
SAR AX,1 ; (AX)=-64
用IDIV指令
MOV AX,0FF81H;(AX)=-127
MOV CL,2
IDIV CL ;(AL)=-63,(AH)=-1 余数
循环移位指令
不含进位标志位CF循环左移指令 ROL
不含进位标志位CF循环右移指令 ROR
含进位标志位 CF 循环左移指令 RCL
含进位标志位 CF 循环右移指令 RCR
格式同非循环移位指令
移位位数放在CL寄存器,如果只移位1位,也可以直接写在指令中
循环移位指令只影响标志位CF和OF中
例1:将AL的高4位与低4位互换。
MOV CL,4
ROL AL,CL
例2:将1A00H内存单元中的双字循环左移1位。
CMP [1A00H],8000H
CMC ( 进位标志取反) ;用来将低16位的最高位放入CF中
RCL WORD PTR[1A02H],1
RCL WORD PTR[1A00H],1
例:设在1000H开始存有四个压缩的BCD码12、34、56、78。要求把它们转换为ASCII码存放在3000H开始的单元中。
假定DS、ES都已设置为数据段的段基址。
程序见下页。
MOV SI,1000H ;SI←BCD首址
MOV DI,3000H ;DI←ASCII首址
MOV BX,4 ;置计数器初值
CLD ;DF=0
BBB: MOV AL,[SI] ;AL←BCD码,第一次取12H
AND AL,0FH ;屏蔽高4位→02H
OR AL,30H ;转换为ASCII码→32H
STOSB ;保存结果
等同于: MOV ES:[SI], AL
LODSB ;串装入指令,DS:SI
等同于:MOV AL, [SI]
INC SI
MOV CL,4
SHR AL,CL ;逻辑右移4位
OR AL,30H ;得到高4位ASCII码
STOSB ;保存结果
DEC BX ;(BX)←(BX)-1
JNZ BBB ; (BX)≠0,则继续循环
串操作指令
串:顺序放在内存中一组相同类型数据
串操作:对传中元素进行相同操作
串操作寻址方式
源操作数指针 -- DS:SI
目的操作是指针 ES:DI
每次操作后
串操作指令自动修改SI和DI,
主要退出操作后,指针指向最后操作数元素进行下一个元素
可完成存储单元传送比较
有的串操作指令前面可以添加重复前缀,当使用重复前缀,操作重复次数有CX决定
- 重复前缀
- 可以加上重复前缀REP,当使用REP前缀时
- 该指令重复执行,重复执行次数由CX决定,带有REP前缀串操作指令每执行一次,CX自动-1
- 重复前缀包括
- rep
- REPE/REPZ CX!=0 ZF=1重复执行
- REPNE/REPNZ
执行串指令前,应先进行
源串首地址末地址 -SI
目的传授地址 DI
串长度CX
建立方向标志 CLDD使DF=0,,STD使DF=1
- ⒈串传送指令MOVSB / MOVSW
- ⒉串比较指令CMPSB / CMPSW
- ⒊串扫描SCASB / SCASW
- ⒋串装入指令LODSB / LODSW
- ⒌串存储指令STOSB / STOSW
串传送指令MOVSB/MOVSW
指令执行的操作为:
MOVSB: ((ES):(DI))←((DS):(SI))
SI±1, DI±1
MOVSW: ((ES):(DI+1)(DI))←((DS):(SI+1)(SI))
SI±2, DI±2
指令也可写成:MOVS dest,src
但要求:
①src用DS:SI寻址,dest用ES:DI寻址
②传送是字节还是字,由操作数的类型决定
用串传送指令实现200个字节的数据传送:
LEA SI,MEM1
LEA DI,MEM2
MOV CX,200
CLD
REP MOVSB
HLT
串比较指令CMPSB//SMPPSW
指令执行的操作为:
CMPSB: ((DS):(SI))-((ES):(DI))
SI±1, DI±1
CMPSW: ((DS):(SI+1)(SI))-((ES):(DI+1)(DI))
SI±2, DI±2
指令也可写成:CMPS dest, src
比较的结果只反映在标志位上,串本身无变化。
本指令可用来检查两个串是否相等。
例:比较两个字符串是否相同,并找出第一个不相等字符串的地址,将该地址送BX,不相等字符送AL。设两个字符串的长度均为200,M1为源串首地址,M2为目标串首地址。
LEA SI,M1 ;
LEA DI,M2 ;
MOV CX,200;
CLD
REPE CMPSB ;若相等则重复比较
JZ STOP ;判ZF=1否
DEC SI ;否则指向不相等单元
MOV BX,SI ;不相等单元地址
MOV AL,[SI] ;不相等单元内容
STOP: HLT ;
串扫描SCASM/SCASW
执行的操作:
对字节:(AL)-((ES):(DI))
DI±1
对字: (AX)-((ES):(DI+1)(DI))
DI±2
搜索指令执行的仍是比较(减法)操作,结果只影响标志位。
要搜索的关键字放在AL(字节)或AX(字)中。
本指令用于在串中查找指定的信息。
SCAS指令加上重复前缀后,可对串进行连续扫描比较:
若前缀为REPZ,则表示比较结果相等(ZF=1)且串未结束(CX≠0),则继续比较。
若前缀为REPNZ,则表示比较结果不相等(ZF=0)且串未结束(CX≠0)就继续比较。
例:在ES段的偏移1000H开始处存有10个ASCII码。搜索’E’,若找到则记下搜索次数及存放地址,并在屏幕上显示’Y’;若未找到则显示’N’。(见右图)
在屏幕上显示一个字符的
指令段如下:
MOV DL,<字符>
MOV AH,2
INT 21H
实现题目要求的程序段见下页:
MOV DI, 1000H ;(DI)←串偏移地址
MOV CX, 0AH ;(CX)←串长度
MOV AL, ’E’ ;搜索关键字=’E’
CLD ;从低地址到高地址进行搜索
REPNZ SCASB ;若未找到, 继续搜索
JZ FOUND ;找到, 转至
MOV DL, ’N’ ;串中无’E’,(DL)←’N’
JMP DONE ;转至DONE
FOUND: DEC DI ;指针回退
MOV ADDR, DI ;ADDR←’E’的地址
SUB DI, 1000H
MOV NUM, DI ;NUM←搜索次数
MOV DL, ’Y’ ;(DL)←’Y’
DONE: MOV AH, 2
INT 21H ;显示字符
HLT
串装入指令LODSB/LODSW
执行的操作为:
对字节:(AL)←((DS):(SI))
SI±1
对字:(AX)←((DS):(SI+1)(SI))
SI±2
串装入指令通常不加重复前缀。
LODSB等价于: LODSW等价于:
MOV AL,[SI] MOV AX,[SI]
INC SI INC SI
INC SI
串存储STOSB/STOSW
指令的操作为:
对字节:((ES):(DI))←(AL)
DI±1
对字:((ES):(DI+1)(DI))←(AX)
DI±2
本指令用于把一块存储区域填充成某一初始值(即对存储区进行初始化)。
存储区域的首地址要预先设置到ES:DI中。
要存储到串中的数据要预先存到AL(AX)中。
例1:把从A000H开始的100个内存单元清零。
程序段如下:
MOV DI,0A000H
MOV AX,0
MOV CX,100
CLD
REP STOSW
例2:把1000H开始的100个存储单元填入
ASCII码2AH(*)。
程序段如下:
MOV DI, 1000H ; 首地址
MOV AL, 2AH ;‘*’
MOV CX, 100 ; 重复执行100次
CLD ; 增量修改DI
REP STOSB
程序控制指令
转移指令
转移指令是指:改变IP或CS内容
所有转移指令不会影响标志位
分为无条件转移和条件转移两种
无条件转移JMP
转移到目标地址,以执行从该地方地址开始程序段
段内直接转移 8/16 位移量加到IP,CS不变JMP disp
转移的目标地址是指令直接给出,指令给出的目标地址实际上·11是相对于IP的位移量
位移量 转移范围 汇编语言中格式
8位 -128~+127 JMP SHORT OPRD
16位 -32768~+32767 JMP NEAR PTR OPRD
例:JMP 0120H ;直接转向0120H
JMP SHORT LP ;转向LP
JMP NEAR PTR BBB ;转向BBB
由于是段内转移,故转移后CS内容保持不变
段内间接转移转移 JMP 指令中给出16位的段和16位偏移地址送到CS和IP
转移目标地址由寄存器和存储单元
目标地址以段内偏移形式给出,而不是相对于IP的位移量,所以是16操作数,操作数存储器,前面要加上类型指示符WORD PTR,所以操作数是一个字
转移的目标地址由寄存器或存储单元的内容给出。
例1:JMP SI
若(SI)=1200H,则指令执行后,(IP)=1200H,于是转向代码段的偏移地址1200H处开始执行。
例2:JMP [BX+DI]
设指令执行前:
(DS)=3000H,(BX)=1300H,
(DI)=1200H,(32500H)=2350H;
则指令执行后:(IP)=2350H
在汇编语言中,段内间接寻址通常写成:
JMP WORD PTR[BX+DI]
表示所取得的目标地址是一个字。
段间直接转移
在指令中直接给出要转移到的目的段地址和偏移地址。
例:JMP 2000H:1000H
执行时,(IP)←1000H,(CS)←2000H
注:直接地址为符号地址时,段间直接转移指令中的符号地址前应加操作符FAR PTR。
例:JMP FAR PTR far_label
其中的far_label为远类型的标号。
段间间接转移 16位的段和16位偏移地址送到CSIP
转移目的地址在两个相邻的字存储单元
例如:
JMP DWORD PTR[SI]
设指令执行前:(DS)=4000H,(SI)=1212H,
(41212H)=1000H,(41214H)=4A00H
则指令执行后:(IP)=1000H,(CS)=4A00H
于是转到4B000H处开始执行指令。
例中的DWORD PTR表示转移地址是一个双字。
条件转移指令
条件转移指令可实现程序的条件分支
条件转移指令,根据标志位状态决定是否进行分支转移
格式:
JXX label ;xx为条件名称缩写
指令的转移范围为-128~+127字节。(直接寻址方式的短转移)
主要的条件转移指令参见p142表3-7。
① 根据单个标志位设置的条件转移指令
JB/JC ;低于,或CF=1,则转移
JNB/JNC/JAE ;高于或等于,或CF=0,则转移
JP/JPE ;奇偶标志PF=1(偶),则转移
JNP/JPO ;奇偶标志PF=0(奇),则转移
JZ/JE ;结果为零(ZF=1),则转移
JNZ/JNE ;结果不为零(ZF=0),则转移
JS ;SF=1,则转移
JNS ;SF=0,则转移
JO ;OF=1,则转移
JNO ;OF=0,则转移
根据组合条件设置条件转移指令
这类指令主要用来判断两个数的大小。一般指令序列为:
CMP dist,src ;比较
Jxx label ;根据比较结果转移
判断无符号数的大小
JA 高于则转移(dist>src)
转移条件为: CF=0且ZF=0
JNA/JBE 低于或等于则转移(dist≤src)
转移条件为: CF=1或ZF=1
判断有无符号大小
JG ;大于则转移(dist>src)
转移条件为: (SF⊕OF=0)∧ZF=0
JGE ;大于或等于则转移(dist≥src
转移条件为: (SF⊕OF=0)∨ZF=1
JL ;小于则转移(dist<src)
转移条件为: (SF⊕OF=1)∧ZF=0
JLE ;小于或等于则转移(dist≤src)
转移条件为: (SF⊕OF=1)∨ZF=1
根据CX内容决定是否转移指令
JCXZ label若 CX = 0 则转移到label开始执行
例:在内存的首地址为TABLE开始单元存放了100个8位有符号数,试统计其中正数、负数和零的个数,并分别将个数存入PLUS、MINUS和ZERO这3个单元中。
START:XOR AL,AL ;AL清零
MOV PLUS,AL
MOV MINUS,AL
MOV ZERO,AL ;将三个个数存储单元清零
LEA SI,TABLE
MOV CX,100
CLD ;DF=0,循环方向为正,小地址到大地址
CHECK:LODSB
OR AL,AL ;不损失AL中的原本内容,影响标志寄存器
JS X1 ;SF=1,结果为负时转移至X1
JZ X2 ;ZF=1,结果为0时转移到X2
INC PLUS ;否则结果为整数
JMP NEXT
X1: INC MINUS
JMP NEXT
X2: INC ZERO
NEXT: LOOP CHECK
HLT
例:在以DATA为首地址的內存中,存放有100个带符号数,试找出其中最大和最小的有符号数,并分别存放在MAX和MIN的内存单元中。
注意:应采用JG和JL等有符号数条件转移指令。
START:LEA SI,DATA
MOV CX,0064H
CLD
LODSB
MOV MAX,AX
MOV MIN,AX
DEC CX
NEXT:LODSB
CMP AX,MAX
JG LAB;大于转LAB
CMP AX,MIN
JL SML1;小于MIN转SML1
JMP GOON
LAB: MOV MAX,AX
JMP GOON
SML1: MOV MIN,AX
GOON:LOOP NEXT
HLT
例:以十六进制数形式显示BX 的内容。
MOV BX, 1234H
MOV CH, 4 ; CH做循环计数器
ROT: MOV CL, 4 ; CL做移位计数器
ROL BX, CL ; 将最高4位移到低4位
MOV AL, BL
AND AL, 0FH ; 取出低4位
ADD AL, 30H ; 转换为ASCII码
CMP AL, 39H ; 与 ’9’ 比较
JBE DISP ; 若(AL)≤‘9’, 则转显示
ADD AL, 7 ; 若(AL)>’9’, 再加7转为‘A’-‘F’
DISP: MOV DL, AL ; (DL)←字符
MOV AH, 2
INT 21H ; 显示输出
DEC CH ; 4个十六进制数显示完否?
JNZ ROT ; 没有, 循环
MOV DL, 48H ; ‘H’
MOV AH, 2
INT 21H ; 最后显示’H’
循环控制指令
在程序中判断是否要继续循环
循环次数通常CX
转移目标应在距离本指令 -128 ~127
循环控制指令不影响标志位
(1)LOOP
格式:LOOP label
操作:(CX)-1→CX;
若(CX)≠0,则转至label处执行;
否则退出循环,执行LOOP后面的指令。
注:LOOP lable指令与下面的指令段等价:
DEC CX
JNZ label
(2)LOOPZ (LOOPE)
格式:LOOPZ label 操作:(CX)-1→CX;
若(CX)≠0∧ZF=1,则转至label处执行;
否则退出循环,执行LOOP后面的指令。
(3)LOOPNZ (LOOPNE)
格式:LOOPNZ label 操作:(CX)-1→CX;
若(CX)≠0∧ZF=0,则转至label处执行;
否则退出循环,执行LOOP后面的指令。
例1:给1A000H开始的256个内存单元均减去1,若发现某个单元减为0则立即退出循环,其后的单元不再减1。程序段如下:(逻辑地址为1A00:0H)
MOV AX, 1A00H
MOV DS, AX ; 1A00H段
MOV DI, -1
MOV CX, 256
GOON: INC DI
DEC BYTE PTR[DI]
LOOPNZ GOON
HLT
例:统计以TAB为首地址的100个单元中正数的个数,并将统计出正数的个数送NUM单元。
XOR BL,BL
MOV CX,100
LEA SI,TAB
CLD
NEXT: LODSB
TEST AL,80H
JNZ GOON
INC BL
GOON:LOOP NEXT
MOV NUM,BL
例2:在8000H开始的长度为1000字节的字符串中 查找’S’,若找到,把其偏移地址记录在ADDR中,否则ADDR单元置为0FFFFH。
MOV DI, 8000H
MOV CX, 1000
MOV AL, ’S’
MOV ADDR, 0FFFFH
GOON: SCASB
LOOPNZ GOON
JNZ DONE
DEC DI
MOV ADDR,DI
DONE: HLT
过程调用返回指令
过程:一段具有特定功能的,供其他程序调用的共用程序
特点
- 调用子程序,IPCS内容被压入堆栈栈顶,从子程序返回,栈顶内容又被弹出到IP
- 子程序执行结束后一般要返回调用程序
- 以此定义多次调用
- 可滴啊参数调用
- 代码段
两条指令
- 子程序调用 CALL
- 子程序返回指令 RET
调用 CALL
-
段内直接调用
①段内直接调用 子程序的偏移地址直接由CALL指令给出。 格式:CALL near_proc CALL执行时,它首先将IP内容压栈,然后把指令中给出的位移量加到IP上。 注:汇编以后的调用地址是相对于CALL的下一条指令的位移量。 例:CALL 0120H ;子程序偏移地址由指令给出 位移量由汇编程序在汇编时进行计算,如下例: CS:0102 CALL 0120H ;3字节 CS:0105 …… 则位移量为: 0120-0105H=001BH 于是CALL 0120H的机器码为E8 1B 00 CS:0102 E8 CS:0103 1B CALL 0120H CS:0104 00 CS:0105 ……
-
段内间接调用
-
子程序的偏移地址在寄存器或存储器中。 格式:CALL mem16/reg16 CALL执行时,它首先将IP内容压栈,然后把指定的寄存器/存储器的内容送入IP。 例: CALL BX ;子程序地址由BX给出 CALL WORD PTR[SI] ;子程序地址在存储器中
-
段间直接调用
-
子程序的段地址和偏移地址直接由CALL指令给出。 格式:CALL far_proc ;far_proc为远过程的地址 指令的操作为: CS内容压栈 段地址 IP内容压栈 偏移地址 IP← 例:CALL 2000H:1000H CALL TIMER ;TIMER为远过程
-
段间间接调用
-
子程序的段和偏移地址为存储器的连续4个单元中的内容。 格式:CALL mem32 指令的操作为: SP←(SP)-2 ((SP)+1,(SP))←(CS) ;CS压栈 CS←(mem32+2) SP←(SP)-2 ((SP)+1,(SP))←(IP) ;IP压栈 IP←(mem32) 例:CALL DWORD PTR[DI] 调用地址在[DI],[DI]+1,[DI]+2,[DI]+3四个存储单元中。低字内容为偏移地址,高字内容为段地址。
例:下面的程序执行后,(AX)=? (DX)=?
CS: 2000H MOV AX, 2012H
2003H MOV CX, 200CH
2006H PUSH CX
2007H CALL 4000H
200AH ADD AX, BX
200CH ADD AX, DX
200EH HLT
… …
… …
CS: 4000H MOV BX, 200AH
POP DX
RET
返回指令RET
段内返回指令RET操作
恢复子程序质心搞钱IP内容,从栈顶部弹出一个字给IP
段间返回RET
恢复子程序执行齐纳IPCS 内容,从堆栈顶部他暗处两个字分别给IP和CS
中断指令
8086在程序中允许安排一条中断指令来引起一个中断过程,这个中断内部纠中断,软中断,被中断的指令地址叫断点,
INT n 执行该类型 n中断服务程序
- 将FLAGS压入堆栈
- 将INT 指令下一条指令地址压栈,把CSIP内容压栈
- 取中断服务程序入口地址宋如CSIP
- INT指令只影响IF和TF,对其余标志位无影响
- INT 课用于调用系统服务程序 INT 21H
INT o 执行溢出中断服务程序
INTO 检查溢出标志OF OF=1 启动一个类型4的张宗端过程OF-0,不需要任何操作
IRET 从中断服务程序返回调用程序
从中断服务程序返回被中断程序,IRET 负责恢复断点和恢复标志寄存器内容,任何中断服务程序不管是外部中断引起还是内部引起,最后都要yogaIRET返回
栈顶弹出IP
栈顶弹出CS
栈顶弹出FLAG
处理器控制
1.标志操作指令用来设置标志位的状态。
(1)CF设置指令
CLC 0→CF
STC 1→CF
CMC CF变反
(2)DF设置指令
CLD 0→DF (串操作的指针移动方向从低到高)
STD 1→DF (串操作的指针移动方向从高到低)
(3)IF设置指令
CLI 0→IF (禁止INTR中断)
STI 1→IF (开放INTR中断)
执行1HLT指令,CPU进入暂停状态,设置该指令通常是为了等待中断
汇编部分
机器语言:用二进制数码来表示指令和数据的语言
汇编语言:指令符号地址、助记符和伪指令来书写程序
数据段:存放数据,变量
堆栈段:堆栈区域
代码段:存放程序指令
DSEG SEGMENT ;定义数据段
DATA1 DW 0F865H ;定义被加数
DATA2 DW 360CH ;定义加数
DSEG ENDS ;数据段结束
ESEG SEGMENT ;定义附加段
SUM DW 2 DUP(?) ;定义存放结果区
ESEG ENDS ;附加段结束
CSEG SEGMENT ;定义代码段
ASSUME CS :CSEG,DS:DSEG,ES:ESEG
START: MOV AX,DSEG
MOV DS,AX ;初试化DS
MOV AX,ESEG
MOV ES,AX ;初试化ES
LEA SI,SUM ;存放结果的偏移地址送SI
MOV AX,DATA1 ;取被加数
ADD AX ,DATA2 ;两数相加
MOV ES:[SI] ,AX ;和送附加段的SUM单元中
HLT
CSEG ENDS ;代码段结束
END START ;源程序结束
语句格式
汇编语言语句
指令性语句:8086/8088指令助记符构成语句
指示性语句:由伪指令构成的语句
标号:指令助记符,目的操作数,源操作数,注释
指示性语句:名字 伪指令,操作数1,操作数2.。。。。
空格是分隔符
指令性语句:由CPU执行,每一条指令性语句都有一条机器码指令与其对应;
指示性语句:由汇编程序执行。它指出汇编程序应如何对源程序进行汇编,如何定义变量、分配存储单元以及指示程序开始和结束等。指示性语句无机器码指令与其相对应。
标号:只能出现在指令性语句,标号后加上冒号
名字:只能出现在指示性语句中,名字后不加冒号
注释 ;
数据项与表达式
数据项:常量变量标号,表达式
常量
二进制数,以B结尾。如01001101B。
十进制数,以D结尾如85D或85。
十六进制数,以H结尾。第1个数字为A-F时,前面应加0,如0F160H。
字符串:用引号括起来的1个或多个字符。如‘ERROR!’, ’a’,汇编时被翻译成对应的ASCII码45H,52H,52H,4FH,52H,21H和61H。
标号
指令所在内存单元的符号地址
段地址:标号所在段的段地址
偏移量:标号所代表存储单元的段内偏移地址
类型:NEAR FAR
NEAR:调用指令在同一码段,跳转只需要改变IP
FAR:不在同一代码段,跳转需要改变,CS:IP
默认NEAR
标号转移指令或CALL转移的地址
变量
变量:内存中存储单元数据区
变量名:存储单元的符号地址名字
变量也有三个属性
段地址—变量所在段的段地址
偏移量—变量单元地址与段首地址之间的位移量。
类 型—有BYTE、WORD和DWORD三种。
变量在程序中作为存储器操作数被引用
标号和变量名的使用规则
组成:A-Z(不分大小写), 0-9, ?@ . _ $
不能以数字开头(只能以字符开头)
长度小于31个字符
不能与保留字(指令助记符、伪指令、预定义符号等)重名
不能重复定义
表达式
汇编时按优先规则对表达式进行计算,计算出具体数值或地址
数字表达式,地址表达式
运算符:算术,逻辑,关系,取地址,属性,
用于数字表达式,例:
MOV AX,4*1024
汇编后的形式为:
MOV AX,4096
用于地址表达式,例:
LEA SI,TAB+3
若TAB的偏移地址为1000H,则汇编后的形式为:
LEA SI,[1003H]
逻辑运算符 AND,OR,XOR,NOT
逻辑运算符只能用于数字表达式中
关系运算符 EQ,NE,LT,GT,LE,GE
关系运算的结果是一个逻辑值,真或假
关系是真,结果1
关系假 结果是0
SEG:取变量/标号,段地址
OFFSET:取变量/标号偏移地址
例:VAR DB 12H
……
MOV BX,OFFSET VAR ;取变量VAR的偏移地址
MOV AX,SEG VAR ;取变量VAR的段地址
注意,以下指令的异同:
MOV BX, OFFSET VAR
LEA BX, VAR
TYPE 取变量类型
LENGTH 取所定义变量的长度
SIZE 取所定义存储区的字节数
属性运算符 PTR
用来指定地址操作数类型
格式 :<类型> PTR <地址操作数>
BYTE ,WORD ,DWORD 用于描述数据存储单元地址
NEAR,FAR 用于描述转移,调用目的地址
例:MOV BYTE PTR[DI],0 ;字节类型
MOV WORD PTR[DI],0 ;字类型
MOV [DI],0B5H ;类型不定
PTR也可用来进行强制类型转换
例:STR1 DW ? ;STR1定义为字类型
MOV AX,STR1 ;合法
MOV AL,STR1 ;非法
MOV AL,BYTE PTR STR1 ;合法
伪指令
汇编程序对源程序汇编期间由汇编程序处理,伪指令只是为汇编程序提供有关的信息,不产生相应的机器代码
DB 定义字节或字符串
DW 定义字节
DD 定义双字
操作数 可以是常数变量表达式
符号定义伪指令
EQU: 不能使用EQU对一个符号重复定义。
‘=’:用”=”定义的符号可在任何时候进行重定义。
二者均不占用存储空间,仅是给符号赋值
段定义伪指令
段段定义伪指令:SEGMENT、ENDS、ASSUME、ORG
段名 SEGMENT [定位类型] [组合方式] [类别]
<汇编语言语句>
段名 ENDS
SEGMENT和ENDS伪指令
这两个伪指令总是成对出现,二者前面的段名应一致。SEGMENT说明了一个段的开始,ENDS说明了一个段的结束。
CODE SEGMENT
<指令语句>
CODE ENDS
作词 : Marilyn Manson
作曲 : Twiggy Ramirez/Chris Vrenna
Remember when I took you up to the top of the hill
那时我和你登上山顶
We had our knives drawn
拔出刀子
They were as sharp as we were in love
它依然锋利而我们依然爱的深沉
If God crossed us we'd take all his drugs
如果上帝要惩罚,我们就拿走他的药药
Burn his money and his house down and wait for the fire to spread
烧掉他的票子,他的房子,让这场大火蔓延
Sometimes hate is not enough to turn this all to ashes
有时仅仅只有仇恨是不够让这一切化为灰烬的
Together as one against all others
我们相爱面对一切
Break all of their wings and make sure that it crashes
砍断天使的翅膀,让他们崩溃
We're running to the edge of the world
我们正向世界尽头
Running, running away
不停逃亡
We're running to the edge of the world
我们逃到世界尽头
I don't know if the world will end today
不知道这世界是否将在今天终结
I had no choice to erase the debt of our families
别无选择,清除我们的罪罚
Let you say goodbye with lips like dynamite
你来告别,用疯狂炙吻
Everyone turned their backs cause they knew
每个人都转过身去
When we held on tight to each other
因为他们知道当我们紧紧相拥
We were something fatal that fell into the wrong hands
我们就要亲手毁灭
Sometimes hate is not enough to turn this all to ashes
有时仅仅只有仇恨是不够让这一切化为灰烬的
Together as one against all others
我们相爱面对一切
Break all of their wings and make sure that it crashes
砍断天使的翅膀,让他们崩溃
We're running to the edge of the world
我们正向世界尽头
Running, running away
不停逃亡
We're running to the edge of the world
我们逃到世界尽头
I don't know if the world will end today
不知道这世界是否将在今天终结
We don't seek death, we seek destruction
我们不需要死亡,我们渴望毁灭
Death, we seek destruction
我们自我毁灭
We don't seek death, we seek destruction
我们不需要死亡,我们渴望毁灭
Death, we seek destruction
我们自我毁灭
We're running to the edge of the world
我们正向世界尽头
Running, running away
不停逃亡
We're running to the edge of the world
我们逃到世界尽头
But I don't know if the world will end today
不知道这世界是否将在今天终结
We're running to the edge of the world
我们正向世界尽头
Running, running away
不停逃亡
We're running to the edge of the world
我们奔跑到世界尽头
I don't know if the world will end today
不知道这世界是否将在今天终结
See a new beginning rise behind the sun
太阳落下又会有新的升起
We could never catch up to them as fast as we run
我们用尽全力也无法到达世界尽头
See a new beginning rise behind the sun
太阳落下又会有新的升起
We could never catch up to them as fast as we run
我们用尽全力也无法到达世界尽头
See a new beginning rise behind the sun
太阳落下又会有新的升起
We could never catch up to them as fast as we run
我们用尽全力也无法到达世界尽头
See a new beginning rise behind the sun
太阳落下又会有新的升起
We could never catch up to them as fast as we run
我们用尽全力也无法到达世界尽头
ASSUME伪指令
ASSUME CS:code, DS:data, ES:data
- CS将指向名字为code的代码段
- DS和ES将指向名字为data的数据段
ASSUME伪指令只是告诉汇编程序有关段寄存器与段有关系,并没有给段寄存器赋予实际的初值
代码段基地址不需要装入CS寄存器,由OS负责装入
SEGMENT语句后可以带有可选参数,用以规定逻辑段的其他一些属性。
定位类型
PARA 逻辑段从一个节的边界开始
BYTE:逻辑段从字节边界开始
WORD:逻辑段从字节边界开始,段的起始地址必须是偶数
PAGE:逻辑段从页边界开始 256字节是一页
组合类型
PUBLIC:同名段组合逻辑段,公用一个地址,运行时装入同一个物理段中
COMMON :具有相同起始地址,共享相同存储区域
AT:按绝对地址定位,段地址就是表达式值
STACK:说明堆栈段
ORG伪指令
ORG规定了段内指令数据存放其实地址
表达式的值即为起始地址,由此地址起连续存放程序或数据。
例:将两个模块中的同名段进行组合。
STACK SEGMENT STACK
DB 100 DUP(0)
STACK ENDS
DATA SEGMENT COMMON
AREA1 DB 1024 DUP(0)
DATA ENDS
CODE SEGMENT PUBLIC
︰
CODE ENDS
模块2:
STACK SEGMENT STACK
DB 50 DUP(0)
STACK ENDS
DATA SEGMENT COMMON
AREA1 DB 8192 DUP(0)
DATA ENDS
CODE SEGMENT PUBLIC
︰
CODE ENDS
END
过程定义伪指令 PROC,ENDP
过程就是一段具有某种功能的子程序
过程定义伪指令的格式为
<过程名> PROC [类型]
…
…
RET
<过程名> ENDP
注意:PROC和ENDP必须成对出现
过程类型
NEAR:默认类型表示段内调用
FAR:段间调用
过程可以嵌套,一个过程可以调用另一个过程,也可以递归,过程可以调用过程本身
NAME1 PROC FAR
:
CALL NAME2
:
RET
NAME2 PROC
:
RET 过程NAME2嵌入在过程NAME1中
NAME2 ENDP
NAME1 ENDP
例:编写一个延时20ms的子程序
DELAY PROC ;定义一个过程
PUSH BX ;保护BX原来的内容
PUSH CX ;保护CX原来的内容
MOV BL,2 ;外循环次数
NEXT:MOV CX,2801 ;内循环次数(实现延时10ms)
W10MS:LOOP W10MS ;(CX )≠0则循环
DEC BL ;修改外循环计数值
JNZ NEXT ;(BX )≠0则进行第2轮循环
POP CX ;恢复CX原来的内容
POP BX ;恢复BX原来的内容
RET ;过程返回
DELAY ENDP ;过程结束
程序段定义一个宏指令,宏指令来替代程序段
指令的格式为:
<宏指令名> MACRO [形参表]
<宏定义体>
ENDM
- 宏调用与过程(子程序)调用都是一次定义,多次调用。它们之间的差别:
① 执行形式:宏命令由宏汇编程序在汇编过程中进行处理,而CALL、RET则是由CPU执行的指令。
② 汇编结果:宏命令伪指令汇编后被展开。
③ 执行速度:宏命令执行速度较快(因无调用转移)
④ 占用内存:宏指令简化了源程序,但不能简化目标程序,并不节省内存单元。使用过程可以节省代码占用的内存空间。
汇编结束伪指令 END
使汇编程序结束
格式: END [表达式]
END后跟的表达式通常就是程序第一条指令的标号,指示程序的启动地址(既执行的第一条指令的地址)。
DOS功能调用
系统功能调用分为:DOS和BIOS调用
用户程序在调用这些系统服务程序,采用软中断指令 INT n实现
DOS系统中,功能调用都是软中断指令INT 21H来实现
NT 2lH功能大致可以分为四类:
设备管理、目录管理、文件管理和其它。
DOS系统功能调用实现方法
- AH
- 设置功能要求的接口参数
- 执行INT 21H指令
- 分析出口参数
DOS键盘输入功能
功能号 1,7,8 0A,1号有回显
从键盘输入一个字符
MOV AH,1
INT 21H
例:程序中有时需要用户对提示应答。
KEY: MOV AH,1 ;等待键入字符
INT 21H ;结果在AL中
CMP AL,’Y’ ;是’Y’?
JZ YES ;是,转YES
CMP AL,’N’ ;是’N’?
JZ NO ;是,转NO
JMP KEY ;否则继续等待输入
YES: …
…
NO: …
输入字符串
MOV AH, 0AH
LEA DX, <字符串缓冲区首地址>
INT 21H
N1: 缓冲区长度(最大键入字符数)
N2: 实际键入的字符数(不包括回车符)
用户定义输入字符串缓冲格式
例:编写将键入‘hello’字符串,并在串尾加结束标志‘$’
DATA SEGMENT
STRING DB 10,0,10DUP(?)
DATA ENDS
CODE SEGMENT
ASSUME CS:CODE,DS:DATA
START:MOV AX,DATA
MOV DS,AX
LEA DX,STRING
MOV AH,0AH
INT 21H
MOV CL,STRING+1
XOR CH,CH
ADD DX,CX
MOV BX,DX
MOV BYTE PTR[BX+2],‘$’
LEA DX,STRING
MOV AH,4CH
INT 21H ;终止当前程序,返回调用程序
CODE ENDS
END START
DOS显示功能调用
功能号:2,6,9, 其中功能9用来显示字符串
(1) 在显示器上显示一个字符(功能号2)
MOV AH, 2
MOV DL, <要显示的字符>
INT 21H
例:在显示器上显示一个字符‘A’
MOV AH, 2
MOV DL, ’A’ ;或MOV DL, 41H
INT 21H
MOV AH, 9
LEA DX, <字符串>
INT 21H
注意:被显示的字符串必须以’$’结束。
如果希望自动换行,则应在$前加入回车及换行的ASCII码:0DH和0AH。
例:在屏幕上显示:’HELLO,WORLD!’
;在数据段定义字符串:
DATA SEGMENT
STR1 DB ‘HELLO,WORLD!,0DH,0AH,‘$’
DATA ENDS
CODE SEGMENT
ASSUME CS:CODE, DS:DATA
START: MOV AX, DATA
MOV DS, AX
;在代码段中进行显示输出
MOV AH,9
LEA DX,STR1
INT 21H
MOV AH,4CH ;调用返回DOS功能号
INT 21H ;返回DOS
CODE ENDS
END START
例:屏幕显示“ PASSWORD?”,随后从键盘读入字符串,并比较这个字符串与程序内部设定的字符串。若两者相同则显示“OK”,否则不显示(0DH是回车、0AH是换行的ASCII码)。
D SEGMENT
PASS1 DB’12AB’ ;程序内部设定字符串
N EQU $-PASS1
D1 DB’PASSWORD?’, 0DH,0AH,’$’
PASS2 DB 20, 0,20 DUP(?)
D2 DB 0DH, 0AH,’OK$’
D ENDS
C SEGMENT
ASSUME CS : C,DS : D,ES : D ;
说明代码段、数据段、附加段
BG : MOV AX ,D
MOV DS ,AX ;给DS赋段值
MOV ES ,AX ;给ES赋段值
LEA DX ,D1 ;将D1表示的相对地址 送DX
MOV AH , 9
INT 21H ;显示‘PASSWORD?’并回车换行
LEA DX , PASS2
MOV AH , 0AH
INT 21H ;输入字符串
LEA SI , PASS1
LEA DI , PASS2
CMP BYTE PTR [DI+1] ,N
JNE LAST ;不等
MOV CX ,N
LEA DI ,PASS2+2
CLD
REPZ CMPSB ;重复比较
JCXZ DISOK
LAST : MOV AH ,4CH
INT 21H
DISOK : LEA DX ,D2
MOV AH ,9
INT 21H ;显示‘OK’
JMP LAST
C ENDS
END BG
返回DOS
一个实际可运行的用户程序在执行完后,返回DOS提示符状态
1)用4CH功能返回DOS
MOV AH,4CH
INT 21H
BIOS功能调用
BIOS:基本I/O系统,固化在EPROM中的一组实现基本I/O功能的子程序。
BIOS调用通过多个软中断提供,调用方法为:
MOV AH,<功能号>
<设置入口参数,一般将参数放在寄存器中>
INT <中断类型>
BIOS中的几个主要中断类型如下:
INT 10H——屏幕显示
INT 13H——磁盘操作
INT 14H——串行口操作
INT 16H——键盘操作
INT 17H——打印机操作
每类中断由包含许多子功能,调用时通过功能号指定。