文章目录
- 0. 计组先导知识
-
- 0.1 进位计数制
- 0.2 计算机中数字和字符的表示
- 1. 基础知识
-
- 1.1 汇编语言
- 1.2 硬件接口
- 2. 80x86计算机组织
-
- 2.1 计算机系统
- 2.2 8086微处理器
- 2.3 存储器地址
- 第1次作业
- 3. 地址与指令
-
- 3.1 寻址方式
-
- 3.1.1 数据搜索模式
-
- 3.1.1.1 立即数寻址
- 3.1.1.2 寄存器寻址
- 3.1.1.3 存贮器寻址
-
- 直接寻址
- 间接搜索寄存器
- 相对地址的寄存器
- 寻址基址
- 相对基址变址寻址
- 3.1.2 指令寻址
- 第2次作业
- 3.2 操作数寻址
-
- 3.2.1 伪指令的功能和格式
- 3.2.2 主要伪指令类型
- 3.2.3 汇编语言程序格式
- 3.2.4 汇编语言上机过程
- 第3次作业
- 3.3 8086的指令系统
-
- 3.3.1 数据传输指令
-
- 通用数据传输指令
- 累加器专用传输指令
- 地址传输指令
- 标志寄存器传输指令
- 3.3.2 算数指令
-
- 加法指令
- 减法指令
- 乘法指令
- 除法指令
- 3.3.3 逻辑指令
-
- 逻辑操作指令
- 移位指令
- 3.3.4 串处理指令
- 3.3.5 控制转移指令
-
- 无条件转移指令
- 条件转移指令
- 循环指令
- 调用指令
- 返回指令
- 中断指令
- 标识处理说明:
- 3.3.6 处理机控制及杂项操作指令
- 第四次作业
- 4. 分支程序设计
-
- 4.1 转移指令
- 4.2 分支结构程序设计
-
- 4.2.1 双分支结构
- 4.2.2 多分支结构
- 第五次作业
- 5. 循环程序设计
-
- 5.1 循环指令
- 5.2 循环程序设计
-
- 第六次作业
- 6. 子程序结构
-
- 6.1 调用格式
- 6.2 调用过程
- 6.3 子程序实例
- 第七次作业
- 7. BIOS 和DOS中断
- 8. I/O端口地址译码技术
-
- 8.1 I/O地址空间
- 8.2 I/O 端口
- 8.3 I/O 端口地址分配
- 8.4 I/O 译码端口地址
- 8.5 I/O 端口地址译码电路设计
-
- 第八次作业
0. 计组先导知识
0.1 进位计数制
N表示进制数: 例如,表示16进制数:
- 十进制整数→非十进制整数 除基取余法: 【例】将233D转换为二进制数。
- 十进制小数→非十进制小数 乘基取整法: 【例】将0.6875D转换为二进制数
- 二进制数←→ 八进制数,十六进制数
0.2 计算机中数字和字符的表示
-
: 用 、-正负数称为真值
-
:数0表示正,用1表示负。
-
:原码的最高位表示真值的数字符,其余为数字值,与真值相同,必要时在数字值前加0。
-
:正数的反码=原码;负反码=原码数值位取反。
-
:当一个数为正数时,其补码就是该数本身;如果是负数,则其补码等于模值与该数绝对值之间的差异。
- :正数的补码=原码;负补码=原码数值位取反加1=反码 1。
- :正数的真值=补码;负真值=补码数值位取反且末位加1 (补码补码=原码)
- :ASCⅡ码
-
:补码加法规则 [X Y]补=[X]补 [Y]补:补码减法规则:[X-Y]补=[X]补 [-Y]补
最高位向前位的进位同样自动丢失,而不影响运算的结
1. 基础知识
1.1 汇编语言
- 汇编语言的地位
- 汇编语言的特点
- 面向机器的低级语言,具有专用性。
- 保持了机器语言的优点,具有直接和简捷的特点。
- 可有效地访问、控制计算机的各种硬件设备,如磁盘、存储器、CPU、I/O端口等。
- 目标代码简短,占用内存少,执行速度快,是高效的程序设计语言
- 经常与高级语言配合使用,应用十分广泛。
- 汇编语言的应用 系统程序、高效率代码、I/O驱动程序
- 很多系统软件是用汇编语言编写的。
- 某些快速处理、位处理、访问硬件设备等高效程序是用汇编语言编写的。
- 高级绘图程序、视频游戏程序一般是用汇编语言编写的。
1.2 硬件接口
- 接口发展的几个阶段
- 无接口阶段(微型企业,老板与员工): CPU与外围设备直接相连,直接控制;信号线不兼容,效率低,复杂,速度不兼容,耦合性强,不易扩展等缺点。
- 简单接口阶段(小型企业,老板,独立性很差的中层干部、员工):在CPU与外设间引入接口电路,可以使连接标准化;CPU(用户程序)通过接口对外设进行间接控制;
- 复杂接口阶段(大中型企业,老板,独立性较强的中层干部、员工):接口电路通过复杂的接口协议软件可较为独立地控制外围设备,控制过程对外设用户不可见/不可控(即接口的底层,如总线驱动程序),PCI/USB等就是复杂接口。用户对外设的控制需由用户程序(接口的用户层)和底层设备如PCI总线的驱动程序(接口的底层)共同配合完成。
-
(1)执行CPU命令 接口电路对CPU发来的命令信息(在命令寄存器中,称为命令口)进行识别和分析,分解成若干个控制信号,传送到I/O设备,使其产生具体的操作。 CPU不是直接把命令送到被控对象,而是通过接口电路进行控制。 (2)返回外设状态信息 接口执行CPU的命令后,将整个过程的状态存在接口的状态寄存器(状态口)中,供CPU读取。状态是:“忙”,“闲”,“就绪”,“错”等。 (3)数据缓冲能力 避免因速度的差异而丢失数据。接口中一般都有数据缓冲寄存器,称为数据口。数据缓冲器分为输入和输出缓冲器两种。 (4)信号转换功能 由于外设提供或需要的信号与CPU的总线不兼容,因此信号必须转换。 (5)设备选择功能(大型的部门) 微机系统中一般有多个外设,一个外设中也有多个端口,接口中必须有端口选择能力。 (6)数据宽度与数据格式转换的功能 如:并/串转换、串/并转换等。
-
(1)接口逻辑电路 包括:命令寄存器,状态寄存器,数据缓冲寄存器(数据收发速率不匹配时)。 可编程大规模集成芯片中都包含这些电路。 (2)端口地址译码电路 作用是进行设备选择。需由用户自行设计。 (3)附加电路 需根据接口不同的任务和功能添加的功能模块电路。
-
接口的软件编程 (1)初始化程序段 对可编程接口芯片进行初始化,完成设置。 (2)传送方式处理程序段 传送方式的处理。如:查询,中断,DMA等传送过程中的处理程序。 (3)主控程序段 完成接口任务的程序段。 (4)程序终止与退出程序段 包括程序结束前对接口中硬件的保护程序段。 (5)配置段 包括人-机对话,菜单设计等内容。
-
CPU与接口交换数据的方式 查询方式,中断方式, DMA方式
-
接口电路的分析与设计基本方法(如何当好中层干部?) (1)两侧分析法 凡是接口都有两侧,一侧是CPU,另一侧是外设。 对CPU一侧就是三总线,因此分析比较容易主要搞清楚是什么类型的CPU以及数据总线、地址总线的宽度和控制线的逻辑定义,时序关系。 对外设一侧情况很复杂,这是因为被控对象外设种类繁多,所提供的信号线五花八门;其逻辑定义,时序关系,电平高低差异甚大。要搞清两点:一是外设的信号引脚的功能定义和逻辑定义(外部表现),二是了解被控外设的工作过程(内部原理)。
(2)硬软结合法
- 硬件设计方法(接口硬件有一定设计自由度) 合理选用外围接口芯片。 如有需要,需在接口芯片之外设计附加电路。
- 软件设计方法(接口硬件固定) 采用汇编语言(或高级语言)直接对底层硬件编程,多用于控制非微机标准设备。 采用DOS功能调用和BIOS调用编程,多用于控制微机标准设备。
- 32微机上的接口
- 微机接口是接口的一类,其它数字电路系统中CPU与外设之间也有接口
- 特指低速I/O设备与本地总线如ISA之间的接口
- PCI总线上的高速I/O设备、CPU总线上的主存/AGP等在本质上也是通过高速接口与CPU或总线桥接口电路相连的
- 与16位微机相比,在总线结构上(for 扩展性、速度匹配等)、OS(for总线驱动程序)、存储管理机制(for I/O设备编址、访问保护等)上都有很大不同
2. 80x86计算机组织
2.1 计算机系统
2.2 8086微处理器
- 8086的基本性能指标
- 16位微处理器
- 16根数据线、20根地址线,可寻址的地址空间达1MB (220=1M) (因此其逻辑地址分为段地址和偏移地址)
- 可以和浮点运算器、I/O处理器或其他处理器组成多处理器系统,从而提高系统的数据吞吐能力和数据处理能力。
-
功能:负责指令译码、数据运算和指令执行(控制和执行指令) 组成:算术逻辑运算部件ALU、EU单元控制系统、寄存器(所有的寄存器和数据线都是16位的) 指令执行的两个主要阶段:取指和执行 取指:EU不直接同外部总线相连,它从总线接口单元BIU的指令队列中获取指令 执行:执行指令时,若需要访问存储器或外部设备,EU就向BIU发出操作请求,由BIU完成相应的操作。
-
功能:负责管理与系统总线的接口,负责对存储器和外设访问(预取指令和数据,总线 操作,信息传递) 组成:指令队列、指令指针寄存器、地址加法器和总线控制逻辑
-
8个16位寄存器分别为AX、BX、CX、DX、SP、BP、SI和DI,标志寄存器为FLAGS。
-
- 8086处理器的指令读取,实际上是指令预取 8086处理器维护着长度为6个字节的指令队列 EU单元译码、执行指令,同时BIU单元读取后续指令 BIU和EU两个单元相互独立,可以并行操作
- 最简单的指令流水线技术,节省许多取指时间,提高了工作效率
- 指令指针寄存器IP 保存将要执行的指令在主存的地址 不能由指令直接修改 发生程序转移、中断、异常时由处理器自动改变
- 标志寄存器
特别说明:堆栈的两种访问方式: 随机访问方式:用BP寄存器来指示随机访问地址是内存! 先进后出访问方式:用SP寄存器来表示栈顶也是堆栈!
:
寄存器 | 存储器 |
---|---|
在CPU内部 ,访问速度快 ,容量小,成本高 ,用名字表示,没有地址 | 在CPU外部,访问速度慢,容量大,成本低用地址表示,地址可用各种方式形成 |
- FLAGS是一个16位的寄存器,共9个标志,其中6个状态标志,3个控制标志
- 状态标志反映EU执行算术逻辑运算后的结果特征
- 控制标志用来控制CPU的工作方式或工作状态
——记录程序运行结果的状态信息 最基本的标志,有6个
- 用来记录指令执行结果的辅助信息
- 主要由加减运算和逻辑运算指令设置
- 处理器主要使用其中5个构成各种条件,分支指令判断这些条件实现程序分支
- (Carry Flag) 当加减运算的最高有效位有进位(加法)或借位(减法)时,CF=1,否则CF=0 针对无符号整数,判断加减结果是否超出表达范围 N个二进制位表达无符号整数的范围: 0 ~ 2 N − 1 0~2^N-1 0~2N−1
例1:00111010+01111100= 10110110 最高位无进位, CF=0 例2:10101010+01111100 = [1]00100110 最高位有进位,CF=1
- (Overflow Flag) 有符号数加减结果有溢出则OF=1,否则OF=0 针对有符号整数,判断加减结果是否超出表达范围 N个二进制位表达有符号整数的范围: − 2 N − 1 ~ 2 N − 1 − 1 -2^N-1~2^{N-1}-1 −2N−1~2N−1−1
例1:00111010+01111100 = 10110110 超出表达范围,OF=1 例2:10101010+01111100 = [1]00100110 未超出表达范围,OF=0
进位和溢出的区别
- CF反映无符号整数运算结果是否超出范围 有进位,加上进位或借位后运算结果仍然正确
- OF反映有符号整数运算结果是否超出范围 有溢出,运算结果已经不正确
- 处理器按照无符号整数求得结果 设置进位标志CF 设置溢出标志OF
- 程序员决定 操作数是无符号数,关心进位 操作数是有符号数,注意溢出
溢出标志的判断
- 处理器硬件判断规则 最高位和次高位同时有进位或同时无进位,无溢出;最高位和次高位进位状态不同,有溢出
- 人工判断的简单规则 只有当两个相同符号数相加(含两个不同符号数相减),而运算结果的符号与原数据符号相反时,产生溢出;其他情况下,不会产生溢出
- (Zero Flag) 运算结果为0则ZF=1,否则ZF=0
例1:00111010+01111100 = 10110110 结果不是0,ZF=0 例2:10000100+01111100 = [1]00000000 结果是0,ZF=1
- (Sign Flag) 运算结果最高位为1则SF=1,否则SF=0
例1:00111010+01111100 = 10110110 最高位为1,SF=1 例2:10000100+01111100 = [1]00000000 最高位为0,SF=0
- (Parity Flag) 当运算结果最低字节中“1”的个数为零或偶数时,PF=1;否则PF=0
例1:00111010+01111100 = 10110110 “1”的个数为5个,PF=0 例2:10000100+01111100 = [1]00000000 “1”的个数为0个,PF=1
-
方向标志 DF(Direction Flag) 仅用于串操作指令,控制地址的变化方向 设置DF=0,每次串操作后的存储器地址就自动增加,即从低地址向高地址处理数据串 设置DF=1,每次串操作后的存储器地址就自动减少,即从高地址向低地址处理数据串 执行CLD指令设置DF=0 执行STD指令设置DF=1
-
中断允许标志IF(Interrupt-enable Flag)
-
追踪标志TF(Trace Flag)
段是安排相关代码或数据的主存区域 段寄存器表明段在主存中的位置 3个16位段寄存器:CS DS SS
2.3 存储器地址
存储器的组织采用分段方式,20位的物理地址由16位的段地址和16位的偏移地址形成,每个段的最大寻址空间为64KB; 段地址必须是16的倍数,即末尾4位必须为0。
- 存储单元的地址 将存储单元编号,这个编号就是存储器地址 用十六进制数来表示地址
- 存储单元的内容 存储单元中存放的信息 存储地址加括号“( )”(编程时用[])
字单元由两个字节单元组成,其地址采用它的低地址来表示。 字存入存储器:低位字节存入低地址单元,高位字节存入高地址单元。(小端存储)
因为地址一定是16位的,所以(0004H)对应的字内容是5678H (5678H)可能是字单位或者字节单位,对应的值可能是1EH或者2F1EH
段地址:表示一个段的开始 偏移地址:在段内相对于段起始地址的偏移值 优点: 允许程序在存储器内重定位;有利于程序和数据的分离。
物理地址:每一个存储单元有一个唯一的20位地址 表示范围:00000H~FFFFFH 。 物理地址形成:段地址左移4位再加上偏移地址值 逻辑地址的形式:指令操作数,指令间的相对地址 物理地址:MEM的绝对地址 逻辑地址到物理地址的转换过程因CPU ARCH的不同而不同
: 20 根地址线: 地址范围 00000H ~ FFFFFH (1MB) 机器字长16位:仅能表示地址范围 0000H ~ FFFFH (64KB) 小段: 小段的首地址 小段的尾地址 00000 H ~ 0000F H 00010 H ~ 0001F H 00020 H ~ 0002F H … FFFF0 H ~ FFFFF H 每16个字节为一小段,共有64K个小段 段起始地址:小段首地址
实模式下,在8086~Pentium微处理机中,代码段的段地址放在CS中;数据段的段地址放在DS中;堆栈段的段地址存放在SS中;附加段的段地址存放在ES中。 将CS,DS,SS,ES称为段寄存器
各段在存储器中的分配是由操作系统负责的。一般情况下,根据需求量分配。 注意:只有CS段寄存器是OS分配的,应用程序可读但不可写,其它的段寄存器都可以被修改。 8086~Pentium微处理机中,段寄存器和偏移寄存器组合有一定规则。
段 | 偏移 | 主要用途 |
---|---|---|
CS | IP | 指令寻址 |
SS | SP或BP | 堆栈寻址 |
DS | BX,DI,SI或16位数 | 数据寻址 |
ES | 串指令 | 目标串寻址 |
注意:当BX/BP与SI/DI组合作为偏移地址时,默认的段寄存器是BX/BP所在段的寄存器,而不是SI/DI所在段的寄存器。
例1:(DS) = 2100H, (BX) = 0500H 物理地址 = 21000H + 0500H = 21500H 例2:(CS) = 3000H, (IP) = 1000H 物理地址 = 30000H + 1000H = 31000H 例3:(SS) = 1000H, (SP) = 0010H 物理地址 = 10000H + 0010H = 10010H 例4:(DS) = 3100H, (SI) = 1000H 物理地址 = 31000H + 1000H = 32000H
第1次作业
- 有两个16位字1EE5H和2A3CH分别存放在微机存储器000B0H和000B3H单元中,请用图示表示出它们在存储器里的存储情况。
按照小段存储模式,低位字节放在低地址,高位字节放在高地址。且按照低地址的位置表示存储位置。故存储情况如下图所示:
- 微机存储器里存放的信息如右图示,试读出30022H和30024H字节单元的内容,以及30021H和30022H字单元内容。
30022H 字节单元
内容 : AB H 30024H 字节单元
内容 : EF H 30021H 字单元
内容 : AB34 H 30022H 字单元
内容 : CDAB H
- 在实模式下,段地址和偏移地址为3017H:000AH的存储单元的物理地址是什么?如果段地址和偏移地址是3015H:002AH和3010H:007AH呢?
段地址和偏移地址为3017H:000AH的存储单元的物理地址= 30170H+000AH =3017AH 段地址和偏移地址为3015H:002AH的存储单元的物理地址= 30150H+002AH =3017AH 段地址和偏移地址为3010H:007AH的存储单元的物理地址= 30100H+007AH =3017AH
- 如果在一个程序开始执行之前(CS)=0A7F0H(如果十六进制数的最高位为字母,则应该在其前加1个0),(IP)=2B40H,试问该程序的第1个字的物理地址是多少?
物理地址=0A7F00H+2B40H=0AAA40H
3. 地址与指令
3.1 寻址方式
为取得操作数或指令地址所使用的方法
- 操作数寻址:与数据有关的寻址方式
- 指令寻址:与转移地址有关的寻址方式 8086汇编指令格式
3.1.1 数据寻址方式
(1)操作数包含在指令中——立即数寻址 (2)操作数在CPU的内部寄存器中——寄存器寻址 (3)操作数在存储器中 ——存储器寻址
3.1.1.1 立即数寻址
- ——操作数在指令中
MOV AX 1100H
操作数从指令代码中立即得到,即立即数(Immediate),用常量形式直接表达 因此操作数存储在中。
3.1.1.2 寄存器寻址
- ——操作数在寄存器中
MOV AX,BX
操作数在寄存器中,不需要访问存储器,速度快
3.1.1.3 存贮器寻址
-
- 操作数在存储器中,用存储单元的地址表示
- 编程时使用包含段寄存器和偏移地址的逻辑地址 段寄存器指示段基地址 偏移地址由各种寻址方式计算,常被称为有效地址EA(Effective Address)
- 一般情况下存储器地址由有效地址表示,段寄存器不用显式说明,数据在默认的段中。如果不使用默认段寄存器,则要用段超越指令前缀加以说明
(1)
访问存储器的方式 | 默认 | 可超越 | 偏移地址 |
---|---|---|---|
取指令 | CS | 无 | IP |
堆栈操作 | SS | 无 | SP |
一般数据访问 | DS | CS、ES、SS、FS、GS | 有效地址EA |
一般数据访问 | SS | CS、ES、SS、FS、GS | 有效地址EA |
串操作的源操作数 | DS | CS、ES、SS、FS、GS | SI |
串操作的目的操作数 | ES | 无 | DI |
(2) 16位有效地址 EA=基址寄存器+变址寄存器+位移量 基址寄存器:BX或BP 变址寄存器:SI或DI 位移量:8或16位有符号值 一般情况下,由基址寄存器决定哪个段寄存器作为段指针(如果不使用段超越越前缀)
(3)
- 直接寻址
- 寄存器间接寻址
- 寄存器相对寻址
- 变址寻址
- 带比例的变址寻址
直接寻址
- 指令中直接包含了操作数的有效地址EA,在指令操作码之后
- 默认段地址在DS寄存器中,即操作数的实际地址是DS:EA
- 常用于存取变量
试比较下列指令中源操作数的寻址方式(VARW是内存字变量): MOV AX, 1234H MOV AX, [1234H] ;前者是立即寻址,后者是直接寻址 MOV AX, VARW MOV AX, [VARW] ;两者是等效的,均为直接寻址
1.直接地址可用数值表示,包括在[ ]之中,也可以用变量表示,例如:MOV AL,VALUE;这里,VALUE为变量,变量是有属性的,它由数据段中定义数据的伪指令确定(伪指令将在第4章介绍)。 2. 若操作数在代码段、堆栈段或附加段中,则应在操作数地址之前使用前缀指出段寄存器名,这种前缀称为段超越前缀.段超越前缀也可以用于其他存储器寻址方式中,以使得给定的段寄存器取代默认的段寄存器。 MOV AL,ES:[2000H]; 将ES段2000H单元的内容传入AL中 3. 直接寻址方式适合于处理存储器的单个单元。IBM-PC机中为了避免指令字的长度过长,规定双操作数指令除立即寻址方式之外必须有一个操作数使用寄存器或段寄存器,这就是一个变量常常先要送到寄存器中去的原因
寄存器间接寻址
- 操作数的有效地址EA存放在基址寄存器(BP,BX)或变址寄存器(SI/DI)。不能放在AX\CX\DX中
- 可以方便地对数组的元素或字符串的字符进行操作
- 寄存器间接寻址没有说明存储单元类型
EA= (BX)/ (BP) / (SI) / (DI) PA=16*(DS) + (BX)/(SI)/(DI) PA=16*(SS)+BP
寄存器相对寻址
- 有效地址是与之和
- 适用于数组、字符串、表格的操作
有效地址=(BX)/(BP)/(SI)/(DI) + 8/16 位移量 例子: MOV AL, [BP][80H] MOV AL,[BP+80H] MOV AX, ARRAY1[SI] MOV ARRAY2[DI],AX
基址变址寻址
- 有效地址是和之和
- 适用于二维数组、字符串、表格的操作
- 必须是一个基址寄存器和一个变址寄存器的组合
有效地址=(BX)/(BP) + (SI)/(DI) MOV AX, [BX][BP] 错误 MOV AX, [SI][DI] 错误
相对基址变址寻址
有效地址= (BX)/(BP)+ (SI)/(DI) +8/16位位移量。
3.1.2 指令寻址
- 转向的有效地址 = 当前(IP) + 位移量(8bit/16bit)
例: JMP NEAR PTR NEXT; 近转移 -32768 ~ +32767 汇编时,位移量为16位 JMP SHORT NEXT; 短转移 -128 ~ +127 汇编时,位移量为8位
-
- CS不变,但IP变化。转向的有效地址是一个寄存器或存储单元的内容。
- 可用除立即数以外的任何一种数据寻址方式得到
例: TABLE = 20A1H (BX) = 1256H (SI) = 528FH (DS) = 2000H (232F7H) = 3280H (264E5H)= 2450H JMP BX ; (IP)=1256H JMP TABLE[BX] JMP WORD PTR TABLE[BX] ; (IP)=3280H JMP [BX][SI] JMP WORD PTR [BX][SI] ; (IP)=2450H
- CS与IP都变化(一般仅供OS使用) 转向的有效地址是XXXX:YYYY形式
JMP 1234H:5678H ; (CS)=1234H ,(IP)=5678H
第2次作业
1、现有(DS)=2000H,(BX)=0100H,(SI)=0002H,(20100)=12H,(20101)=34H,(20102)=56H,(20103)=78H,(21200)=2AH,(21201)=4CH,(21202)=0B7H,(21203)=65H,试说明下面各条指令执行后AX寄存器的内容。 (1)MOV AX,1200H (2)MOV AX,BX (3)MOV AX,[1200H] (4)MOV AX,[BX] (5)MOV AX,1100[BX] (6)MOV AX,[BX][SI] (7)MOV AX,1100[BX][SI]
Answer:
- 立即数寻址:1200H
- 寄存器寻址: 0100H
- 直接寻址:4C2AH
- 寄存器间接寻址:3412H
- 寄存器相对寻址:4C2AH
- 基址变址寻址:7856H
- 相对基址变址寻址:65B7H
2、假设(DS)=2000H,(ES)=2100H,(SS)=1500H,(SI)=00A0H,(BX)=0100H,(BP)=0010H,数据段中的变量名VAL的偏移地址值为0050H,试指出下列源操作数的寻址方式试什么?其物理地址值是什么? (1)MOV AX,0BAH (2)MOV AX,[100H] (3)MOV AX,[BX] (4)MOV AX,[BP] (5)MOV AX,[BX+10] (6)MOV AX,[BX][SI] (7)MOV AX,BX (8)MOV AX,VAL (9)MOV AX,ES: [BX] (10)MOV AX, [SI] (11)MOV AX,VAL [BX] (12)MOV AX,VAL [BX][SI]
Answer :
- 立即数寻址;物理地址不确定,因为立即数来自指令,而指令的地址不能确定
- 直接寻址;物理地址=100H+20000H=20100H
- 寄存器间接寻址:物理地址=0100H+20000H=20100H
- 寄存器间接寻址:物理地址=0010H+15000H=15010H (特别注意:BP是堆栈段指针,因此段地址是堆栈段地址)
- 寄存器间接寻址:物理地址=0100H+20000H+000AH=2010AH (特别注意:题目中的10是十进制,要转化位16进制0AH)
- 基址变址寻址:物理地址 =0100H+00A0H+20000H=201A0H
- 寄存器寻址: 无物理地址,因为来自于寄存器,寄存器没有物理地址
- 直接寻址:物理地址=20000H+0050H=20050H(特别注意:使用变量名的寻址属于直接寻址)
- 寄存器间接寻址:物理地址=21000H+0100H=21100H
- 寄存器间接寻址:物理地址=20000H+00A0H=200A0H
- 寄存器相对寻址:物理地址=0100H+20000H+0050H=20150H
- 寄存器相对基址变址: 物理地址=20000H+0050H+0100H+00A0H=201F0H
3.2 操作数寻址
3.2.1 伪指令的功能与格式
- 语句类型:
- 指令性语句:能够直接翻译成机器代码并让CPU直接执行的语句
- 指示性语句:指导汇编程序如何编译汇编语言的源程序,并不翻译成机器代码,CPU也不执行。
-
- 指令语句(处理器指令、硬指令)
[名字:] 操作码 [操作数[,操作数]][;注释]
- 伪指令语句(汇编程序命令、伪指令)
[名字:]伪操作码 [操作数[,操作数]][;注释]
[名字]
:由用户按一定规则定义的标识符 组成:英文字母、数字、特殊符号 形式:标号和变量;[;注释]
: 语句的说明部分[操作码]
:含义:指明操作的性质或功能。 书写规则:操作码与操作数之间用空格分开[操作数]
: 含义:指定参与操作的数据。 个数:一般指令,1个或2个,也可以没有; 伪指令和宏指令,可以有多个。 书写规则:操作数多于1个时,操作数之间用 逗号分开 - 指令语句(处理器指令、硬指令)
-
- 程序员提高编程效率 数据定义及存储器分配伪操作,表达式赋值伪操作,地址计数器与对准伪操作
- 指导编译器如何编译汇编程序 选择处理器型号,定义存储模式,定义段,指示程序开始/结束
3.2.2 主要伪指令类型
data segment; 定义数据段
...
data ends
stack segment; 定义堆栈段
...
stack ends
code segment; 定义代码段
assume cs:code, ds:data, ss:stack
start:
mov ax,data
mov ds,ax;
...
code ends
end start
ASSUME <段寄存器名>:<段名>[,<段寄存器名>:<段名>…]
功能:建立段寄存器与段的缺省关系
- 在代码段开始处进行DS、SS、ES的段基址装填
例:MOV AX, DATA MOV DS, AX 程序装入内存后,段寄存器的指向
-
END(S) [ label ]
-
[变量] 助记符 操作数[,操作数,…][;注释]
助记符:DB DW DD DF DQ(64位) DT(80位) DB: 定义字节 DW:定义字 DD: 定义双字
例: DATA_BYTE DB 10,4,10H,? DATA_WORD DW 100,100H,-5,?
例: ARRAY DB ‘HELLO’ DB ‘AB’ DW ‘AB’
例:操作数用复制操作符DUP,表示操作数重复若干次 VAR DB 100 DUP (?) # 占100个空位置 DB 2 DUP (0,2 DUP(1,2),3) # 0212302123
PAR1 DB 100,20H PAR2 DW 300H,400H ADDR_TABL1 DW PAR1,PAR2 ;存放偏移地址16位 ADDR_TABL2 DD PAR1,PAR2 ;存放偏移和段地址各16位
-
表达式名 EQU 表达式
ALPHA EQU 9 BETA EQU ALPHA+18
表达式名=表达式
注意:EQU指令不占用内存空间! 如: BUF1 DW 1,2,3 INTT EQU 5 BUF2 DW 4,5,6 那么3和4的地址是连续的!
同一个程序中“=”可以对一个符号重复定义,但EQU不能对同一个符号重复定义 Y1=7 Y1=128 √ Y1 EQU 7 Y1 EQU 128 ×
格式:PURGE <符号1,符号2,…,符号n> 功能:解除指定符号的定义 例: Y1 EQU 7 PURGE Y1 Y1 EQU 128
-
- 在代码段,$表示当前正在汇编的指令的地址
ORG $+8 ; 跳过8个字节的存储区 JNE $+6 ; 转向地址是 JNE 的地址 +6 JMP $+2 ; 转向下一条指令
- 在数据段,$表示当前地址计数器的值
ARRAY DW 1, 2 , $+4 , 3 , 4 , $+4
- 地址计数器$的常用使用方法: 常用来确定数组中元素的个数
例:BUF1 DB 1,2,3,4,5 CNT1 EQU $ -BUF1 (常用) BUF2 DW 1,2,3,4,5 CNT2 EQU ($-BUF2)/2 CNT1、CNT2分别为数组BUF1、BUF2中数据元素的个数
- 指明下一条汇编语句的偏移地址 ,本身不占内存空间
- 在指令中出现,主要是对常量进行运算 (1) 算术操作符: +、-、*、/、Mod (2)逻辑和移位操作符: AND(与)、OR(或)、XOR(异或)、NOT(非)、SHL(左移)、SHR(右移) (3)关系操作符 EQ(相等)、NE(不等)、LT(小于)、LE(小于或等于)、GT(大于)、GE(大于或等于) (4) 数值回送操作符 OFFSET、SEG、LENGTH、SIZE
OFFSET / SEG 变量 / 标号
功能:回送变量或标号的偏址 / 段址 如MOV DX,SEG FUNCLENGTH 变量
功能:回送由DUP定义的变量的单元数(最外层的DUP定义的数量),其它情况回送1SIZE 变量
功能:LENGTH * TYPE ;DB的TYPE值为1,DW的TYPE值为2
例: ARRAY DW 100 DUP (?) TABLE DB ‘ABCD’ MOV CX, LENGTH ARRAY ; MOV CX, 100 MOV CX, LENGTH TABLE ; MOV CX, 1 MOV CX, SIZE ARRAY ; MOV CX, 200 MOV CX, SIZE TABLE ; MOV CX, 1
(5) 属性修改的伪指令: PTR 用于暂时改变内存变量或标号的原有属性,但不能修改寄存器的原有属性 格式: 新属性 PTR (旧属性的)表达式 MOV WORD PTR [BX], 5
PTR指令的应用场合 1、有一些指令中,操作数或表达式的属性是不明显 的,需要加以明确,如: 例:CALL DWORD PTR [BX] ;远调用 CALL BYTE PTR [BX] ;段内近调用 2、需要修改操作数或表达式的属性的,如: 例:F1 DW 1234H MOV AL,BYTE PTR F1 ;AL=34H 例:F2 DB 23H,56H,18H MOV BX,WORD PTR F2 ;BX=5623H
- (6) 定位类型的伪指令: PARA para (Paragraph,节)表明该段起始地址对齐到para,供OS使用 一般说来,各个逻辑段的首地址在‘节’的整数边界上(每16个存储单元叫做一节, 1para = 16Bytes),即每个逻辑段的起始地址是16的整数倍,或地址的最低4位为0。
例如: code segment para ‘code’
3.2.3 汇编语言程序格式
- 汇编语言源程序结构 完整段定义结构:用段定义伪指令
- 汇编语言前缀结构 把整个程序定义成一个FAR型过程(或子程序),该过程能够让其它汇编文件中的段来调用,而near则不能。
- 代码段中程序的两种结束方式
3.2.4 汇编语言上机过程
- 程序运行步骤以及生成的文件
- 建立、运行汇编语言程序
- 汇编程序功能 汇编程序的主要功能: 检查源程序,给出出错信息 产生目标文件(.obj)和列表文件(.lst) 展开宏指令
第3次作业
1、画图说明下列语句所分配的存储空间及初始化的数据 (1)AA DB ‘BYTE’,12,-12H, 3 DUP(0,?,2 DUP(1,2),?) (2)BB DW 5 DUP(0,1,2),?,-5,‘BY’, ‘TE’,256H
(1) 如下图
(2)如下图(注意: 左边为低地址,右边为高地址)
2、假设程序中的数据定义如下: PARTNO DW ? PNAME DB 16 DUP(?) COUNT DD ? PLENTH EQU $-PARTNO 问PLENTH的值是多少?它表示什么意义?
PLENTH的值为2+16+4=22=16H 表示PARTNO、PNAME、COUNT 这三个变量所占用的字节数的和 (即这段代码之前数据段的长度)
3、请设置一个数据段DATASG,其中定义以下变量 (1)FLD1为字符串变量:‘computer’ (2)FLD2为十进制字节变量:32 (3)FLD3为十六进制字节变量:20 (4)FLD4为二进制字节变量:01011001 (5)FLD5为10个0的字节变量 (6)FLD6为数字的ASCII字符字节变量32654 (7)FLD7为包括5个十进制数的字变量:5,6,7,8,9 (8)FLD8为100个字变量
DATASG SEGMENT
FLD1 db 'computer'
FLD2 db 32
FLD3 db 20H
FLD4 db 01011001B
FLD5 db 10DUP(0)
FLD6 db '32654'
FLD7 dw 5,6,7,8,9
LFD8 dw 100DUP(?)
DATASG ENDS
易错点总结
- 汇编语言源程序中的数字,默认是十进制,因此使用十六进制的数字的时候,必须有h或H后缀
- 字符、字符串、字节数值数组都是用DB定义。一个字符占一个字节的方式,顺序依次存储的。
// 汇编程序:
mov al,'a'
mov ax,'a'
mov ax,'ab'
//执行后的结果
al = 61h
ax = 0061h
ax = 6162h
参考博客
3.3 8086的指令系统
3.3.1 数据传送指令
通用数据传送指令
:MOV DST, SRC
执行操作:(DST)<-(SRC)
注意:
- DST,RST 不能同时为段寄存器
- 立即数不能直接送至段寄存器
- 不能使用AX、CX、DX存放EA
- DST不能是立即数和CS (CS和IP寄存器的修改只能使用JMP XX:YY指令进行修改,不能用MOV指令修改。通常来说,CS都是由OS分配的,应用程序不能对其进行修改。)
- DST 和SRC不能同时为存储器寻址,因为两者的位宽是否匹配不确定
- 不影响标志位(对所有的数据传输指令而言)
:PUSH SRC
执行操作: SP <- SP – 2 ; (SP+1), (SP) <-(SRC) :POP DST
执行操作:(DST) <- (SP+1), (SP) ; SP <- SP + 2
堆栈:“先进后出”的存储区。段地址存放在SS中,SP在任何时候都指向栈顶,进出栈后自动修改SP 堆栈用于保存子程序返回地址和断点地址以及主程序通用寄存器内容的保护和恢复 因为堆栈遵从“后进先出”原则,在保存寄存器和恢复寄存器的内容时要按照相反的顺序执行一组压入和弹出指令。 8086/8088堆栈操作都是字操作,不允许对字节操作。例如:PUSH AH不是正确指令。
注意
- 堆栈操作必须以字为单位
- 不影响标志位
- 不能用立即寻址方式
- DST不能是CS (CS只能用JMP指令间接修改)
: XCHG OPR1,OPR2
执行操作: (OPR1) <-> (OPR2)
注意
- 不影响标志位
- 不允许使用段寄存器和立即数
- 两个操作数必须有一个在寄存器中(内存之间不能相互传送数据,因为不知位宽是否匹配)
累加器专用传送指令
累加器专用传送指令(IN/OUT)
- 只能使用AX或AL来存放数据,只限8位立即数或DX来存放端口号;
- IN/OUT指令中AX(AL)操作数的位置是不同的,一个是目标操作数位置,另一个是源操作数位置;
- IN/OUT指令操作期间,端口地址处将产生一个负脉冲信号
:IN
执行操作: (I/O->CPU) 长格式: IN AL, PORT
(字节) IN AX, PORT
(字) 执行操作:AL <-(PORT) (字节)AX <- (PORT+1),(PORT) (字)
短格式: IN AL, DX
(字节)IN AX, DX
(字) 执行操作:AL <- (DX) (字节) AX <- (DX+1),(DX) (字)
OUT
执行操作:(CPU -> I/O) 长格式: OUT PORT, AL
(字节) OUT PORT, AX
(字) 执行操作:(PORT) <- AL (字节) (PORT+1),(PORT) <- AX(字)
短格式: OUT DX, AL
(字节) OUT DX, AX
(字) 执行操作: (DX) <- AL (字节) (DX+1),(DX) <- AX(字)
注意:
- 不影响标志位
- 前256个端口号00H~FFH可直接在指令中指定(长格式)
- 如果端口号>= 256,端口号-> DX(短格式)
:XLAT
或 XLAT OPR
执行操作:AL <- ( BX + AL ) 功能:AL给出偏移量,然后存储该偏移地址处的内容
例子: MOV BX, OFFSET TABLE ; BX=0040H MOV AL, 3 XLAT TABLE 指令执行后 AL=33H
注意
- 不影响标志位
- BX是16位寄存器,AL是8位寄存器,偏移地址AL只有8位二进制,所以表格的最大容量是256字节
- BX中存放段首地址,段首地址可以是DS,也可以是用户定义的DATA;
- xlat查表指令只能是字节操作;每次偏移一个字节;
地址传送指令
:LEA REG, SRC
执行操作: REG<- SRC (将源操作数的有效地址EA传送给通用寄存器) SRC:不能是立即寻址,寄存器寻址
MOV BX,0408H
MOV SI,2000H
LEA BP,[BX+SI+6]; 将240EH送BP, 而不是240EH单元的内容送BP
:LDS REG, SRC
执行操作: REG<- (SRC) : 将源操作数指定的存储单元中的双字(通常为段地址和有效地址)传送给DS及目的操作数,高两字节送DS,低两字节送目的操作数。 获取DS段的指针 DS<-(SRC+2) 相继二字-> 寄存器、DS
(DS)=30C0 H, 相关的存储区情况以及执行的指令的功能如下图: LDS SI,[40H]
:LES REG, SRC
执行操作: REG <-(SRC) 获取ES段的指针 ES <- (SRC+2) 相继二字 ->寄存器、ES
例子:
注意:
- 不影响标志位
- REG 只能是16位通用寄存器,不能是段寄存器,SRC 必须为存储器寻址方式
- LEA指令与LDS、LES指令所传送的有效地址有区别。LEA指令所传送的有效地址为源操作数的有效地址,而LDS及LES指令所传送的有效地址在源操作数所指的存储单元中
标志寄存器传送指令
(FLAGS为16位寄存器) : LAHF
执行操作: AH <- (FLAGS的低字节) : 将标志寄存器低8位送AH。
:SAHF
执行操作: (FLAGS的低字节) <-AH : 将(AH)送标志寄存器低8位。
: PUSHF (FLAGS的高和低两字节) 执行操作: (SP) <- (SP) - 2 ( (SP)+1, (SP) ) <- (FLAGS) : POPF(FLAGS的高和低两字节)
执行操作: (FLAGS) <- ( (SP)+1, (SP) ) (SP) <- (SP) + 2
注意: 数据传送指令中仅SAHF及POPF影响标志寄存器的内容。
3.3.2 算数指令
有关符号位加减法指令中的OF 1、计算机中,当确定为有符号数运算时,符号数一律用补码表示,运算时符号位和数字位一起参加运算。 2、在加法/减法运算中的OF含义说明: 不溢出(OF=0),说明运算结果正确。 溢出(OF=1),说明运算结果错误。 3、 O F = A n ‾ ⋅ B n ‾ ⋅ S n + A n ⋅ B n ⋅ S n ‾ O F=\overline{A n} \cdot \overline{B n} \cdot S_{n}+A n \cdot B_{n} \cdot \overline{S_{n}} OF=An⋅Bn⋅Sn+An⋅B 标签: 集成电路sn74ls164nad1814jp集成电路ic集成电路系列op77gs