8086/8088存储器和I/O组织

(一)8086/8088存储器组织

一,8086/8088存储空间

8086/8088有20根地址线,可直接对1M个存储单元进行访问。

每个存储单元都有1个20位的地址。这1M个存储单元对应的地址为00000H-FFFFFH

一个存储单元中存放的信息称为该存储单元的内容。
如图3.10所示,00001H单元的内容为9FH,记为:(00001H)=9FH。
这里写图片描述

①20条AB,寻址1M空间
②按字节组织,每个字节唯一地址。
字节: 顺序存放
③字: 低位字节放在低地址中,高位字节放在高地址中
④双字: 低位字是偏移量, 高位字是段地址
⑤规则字: 低位字节存放在偶数地址
⑥非规则字: 低位字节存放在奇数地址


若存放的是字型数据(16位二进制数),则将字的低位字节存放在低地址单元,高位字节存放在高地址单元。如从地址0011FH开始的两个连续单元中存放一个字型数据,则该数据为DF46H,记为:(0011FH)=DF46H。

若存放的是双字型数据(32位二进制数,这种数一般作为地址指针,其低位字是被寻址地址的偏移量,高位字是被寻址地址所在段的段地址),这种类型的数据要占用连续的4个存储单元,同样,低字节存放在低地址单元,高字节存放在高地址单元。如从地址E800AH开始的连续4个存储单元中存放了一个双字型数据,则该数据为66A65E65H,记为:(E800AH)=66A65E65H。

二,存储器的段结构

8086/8088CPU中有关可用来存放地址的寄存器如IP、SP等都是16位的,故只能直接寻址64 KB。为了对1 M个存储单元进行管理,8086/8088采用了段结构的存储器管理方法。

8086/8088将整个存储器分为许多逻辑段,每个逻辑段的容量小于或等于64 KB,允许它们在整个存储空间中浮动,各个逻辑段之间可以紧密相连,也可以互相重叠。

用户编写的程序(包括指令代码和数据)被分别存储在代码段、数据段、堆栈段和附加数据段中,这些段的段地址分别存储在段寄存器CS、DS、SS和ES中,而指令或数据在段内偏移地址可由对应的地址寄存器或立即数给出,如表所示。
这里写图片描述
如果从存储器中读取指令,则段地址来源于代码段寄存器CS,偏移地址来源于指令指针寄存器IP。

如果从存储器读/写操作数,则段地址通常由数据段寄存器DS提供(必要时可通过指令前缀实现段超越,将段地址指定为由CS、ES或SS提供),偏移地址则要根据指令中所给出的寻址方式确定,这时,偏移地址通常由寄存器BX、SI、DI以及立即数等提供,这类偏移地址也被称为“有效地址”(EA)。如果操作数是通过基址寄存器BP寻址的,则此时操作数所在段的段地址由堆栈段段寄存器SS提供(必要时也可指定为CS、SS或ES)(详见第4章“寻址方式”一节)。

如果使用堆栈操作指令(PUSH或POP)进行进栈或出栈操作,以保护断点或现场,则段地址来源于堆栈段寄存器SS,偏移地址来源于堆栈指针寄存器SP 

如果执行的是字符串操作指令,则源字符串所在段的段地址由数据段寄存器DS提供(必要时可指定为CS、ES或SS),偏移地址由源变址寄存器SI提供;目的字符串所在段的段地址由附加数据段寄存器ES提供,偏移地址由目的变址寄存器DI提供。

以上这些存储器操作时段地址和偏移地址的约定是由系统设计时事先已规定好的,编写程序时必须遵守这些约定。

三,逻辑地址与物理地址

  • 逻辑地址:由于采用了存储器分段管理方式,8080/8088 CPU在对存储器进行访问时,根据当前的操作类型(取指令或存取操作数)以及读取操作数时指令所给出的寻址方式,CPU就可确定要访问的存储单元所在段的段地址以及该单元在本段内的偏移地址(如上表所示)。我们把通过段地址和偏移地址来表示的存储单元的地址称为逻辑地址,记为:段地址:偏移地址。

  • 物理地址: CPU在对存储单元进行访问时,必须在20位的地址总线上提供一个20位的地址信息,以便选中所要访问的存储单元。我们把CPU对存储器进行访问时实际寻址所使用的20位地址称为物理地址。

物理地址是由CPU内部总线接口单元BIU中的地址加法器根据逻辑地址产生的。由逻辑地址形成20位物理地址的方法为:段地址*10H+偏移地址。其形成过程如下图所示:
这里写图片描述

这里写图片描述
上图给出了存储器分段示意。如果当前的(IP)=1000H,那么,下一条要读取的指令所在存储单元的物理地址为:

(CS)*10H+(IP)=1000H*10H+1000H=11000H

如果某操作数在数据段内的偏移地址为8000H,则该操作数所在存储单元的物理地址为

(DS)*10H+8000H=2A0FH*10H+8000H=320F0H

注:对于一个存储单元而言,它有惟一的物理地址,但由于8086/8088允许段与段之间的重叠,因此,存储单元的逻辑地址可以不是惟一的,但其物理地址一定是惟一的。

四,堆栈操作

8086/8088系统中的堆栈使用段定义语句在存储器中定义的一个堆栈段,和其它逻辑段一样,它可以在1M字节的存储空间中浮动,其容量可达64KB,这是一个具有“先进后出”特性的存储区域。

堆栈由SS和SP来寻址。SS给出堆栈段的段地址,而SP给出当前栈顶(偏移地址),即指出从段地址到栈顶的偏移量。

堆栈是在存储器中开辟的一个特定区域。开辟堆栈的目的主要有以下两点:

1,存放指令操作数(变量)。此时,对操作数进行访问时,段地址由堆栈段寄存器SS来提供,操作数在该段内的偏移地址由基址寄存器BP来提供。

2,保护断点和现场。此为堆栈的主要功能。

堆栈操作指令:
堆栈操作指令是用来完成压入和弹出堆栈操作的。8086/8088指令系统中提供了完成这两种操作的相应指令。

压入堆栈指令
指令格式及操作:
PUSH src ;(SP) ←(SP)-2,
((SP)+1:(SP)) ←(src)

弹出堆栈指令
指令格式及操作:
POP dst ; (dst) ←((SP)+1:(SP)),
(SP) ←(SP)+2

进栈和出栈操作过程:

在执行进栈和出栈操作时,段地址由堆栈段寄存器SS提供,段内偏移地址由堆栈指针寄存器SP提供,SP始终指向栈顶,当堆栈空时,SP指向栈底。如下图所示,设在存储器中开辟了100H个存储单元的堆栈段,当前(SS)=2000H,堆栈空时(SP)=0100H,即此时SP指向栈底(如图(a)所示)。由于PUSH和POP指令要求操作数为字型数据,因此,每进行一次进栈操作,SP值减2(如图(b)所示),每进行一次出栈操作,SP值加2(如图(c)所示)。在进栈和出栈操作过程中,SP始终指向栈顶。

这里写图片描述

五,8086/8088存储器结构

8086存储器高低位库的连接如下图所示:
这里写图片描述

8086的1MB存储空间实际上分为两个512 KB的存储体,又称存储库,分别叫高位库和低位库,如图3.13所示。低位库与数据总线D7~D0相连,该库中每个存储单元的地址为偶数地址;高位库与数据总线D15~D8相连,该库中每个存储单元的地址为奇数地址。地址总线A19~A1可同时对高、低位库的存储单元寻址,A0和BHE用于对库的选择,分别连接到库选择端SEL上。当A0=0时,选择偶数地址的低位库;当BHE=0时,选择奇数地址的高位库;当两者均为0时,则同时选中高低位库。利用A0和BHE这两个控制信号,既可实现对两个库进行读/写(即16位数据),也可单独对其中一个库进行读/写(8位数据),如下表所示:
这里写图片描述

在8086系统中,存储器这种分体结构对用户来说是透明的。当用户需要访问存储器中某个存储单元,以便进行字节型数据的读/写操作时,指令中的地址码经变换后得到20位的物理地址,该地址可能是偶地址,也可能是奇地址。如果是偶地址(A0=0),BHE=1,这时由A0选定偶地址存储体,通过A19A1从偶地址存储体中选中某个单元,并启动该存储体,读/写该存储单元中一个字节信息,通过数据总线的低8位传送数据,如图3.14(a)所示;如果是奇地址(A0)=1,则偶地址存储体不会被选中,也就不会启动它。为了启动奇地址存储体,系统将自动产生BHE=0,作为奇地址存储体的选体信号,与A19A1一起选定奇地址存储体中的某个存储单元,并读/写该单元中的一个字节信息,通过数据总线的高8位传送数据,如图3.14(b)所示。可以看出,对于字节型数据,不论它存放在偶地址的低位库,还是奇地址的高位库,都可通过一个总线周期完成数据的读/写操作。

如果用户需要访问存储器中某两个存储单元,以便进行字型数据的读/写时,可分两种情况来讨论。一种情况是用户要访问的是从偶地址开始的两个连续存储单元(即字的低字节在偶地址单元,高字节在奇地址单元),这种存放称为规则存放,这样存放的字称为规则字。对于规则存放的字可通过一个总线周期完成读/写操作,这时A0=0,BHE=0,如图3.14(c)所示;另一种情况是用户要访问的是从奇地址开始的两个存储单元(即字的低字节在奇地址单元,高字节在偶地址单元),这种存放称为非规则存放,这样存放的字称为非规则字,对于非规则存放的字需要通过两个总线周期才能完成读/写操作,即第一次访问存储器时读/写奇地址单元中的字节,第二次访问存储器时读/写偶地址单元中的字节,如图3.14(d)所示。显然,为了加快程序的运行速度,希望字型数据在存储器中规则存放。
这里写图片描述

在8088系统中,可直接寻址的存储空间同样也是1 MB,但其存储器的结构与8086有所不同,它的1MB 存储空间同属于一个单一的存储体,即存储体为1 M8位。它与总线之间的连接方式很简单,其20根地址线A19A0与8根数据线分别与8088 CPU对应的地址线和数据线相连。8088 CPU每访问一次存储器只能读/写一个字节信息,因此在8088系统的存储器中,字型数据需要两次访问存储器才能完成读/写操作。

(二)8086/8088的I/O组织

8086/8088系统和外部设备之间是通过I/O接口电路来联系的。每个I/O接口都有一个或几个端口。在微机系统中每个端口分配一个地址号,称为端口地址。一个端口通常为I/O接口电路内部的一个寄存器或一组寄存器。

8086/8088 CPU用地址总线的低16位作为对8位I/O端口的寻址线,所以8086/8088系统可访问的8位I/O端口有65536(64 K)个。两个编号相邻的8位端口可以组成一个16位的端口。一个8位的I/O 设备既可以连接在数据总线的高8位上,也可以连接到数据总线的低8位上。一般为了使数据/地址总线的负载平衡,希望接在数据/地址总线高8位和低8位的设备数目最好相等。当一个I/O设备接在数据总线的低8位(AD7AD0)上时,这个I/O设备所包括的所有端口地址都将是偶数地址(A0=0);若一个I/O设备接在数据总线的高8位(AD15AD8)上时,那么该设备包含的所有端口地址都是奇数地址(A0=1)。如果某种特殊I/O设备既可使用偶地址又可使用奇地址时,此时必须将A0和BHE两个信号结合起来作为I/O设备的选择线。

8086 CPU对I/O设备的读/写操作与对存储器的读/写操作类似。当CPU与偶地址的I/O设备实现16位数据的存取操作时,可在一个总线周期内完成;当CPU 与奇地址的I/O设备实现16位数据的存取操作时,要占用两个总线周期才能完成。

需要说明的是,8086/8088CPU的I/O指令可以用16位的有效地址A15A0来寻址0000FFFFH共64 K个端口,但IBM PC系统中只使用了A9A0 10位地址来作为I/O端口的寻址信号,因此,其I/O端口的地址仅为0003FFH共1K个。

  • 17
    点赞
  • 70
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
本书分为三部分。第一部分是基础部分,以8086/8088为背景,以DOS和PC兼容机为软硬件平台,以MASM和TASM为汇编器,介绍汇编语言的有关概念,讲解汇编语言程序设计技术。第二部分是提高部分,以80386为背景,以新一代微处理器Pentium为目标,细致和通俗地介绍了保护方式下的有关概念,系统和详细地讲解了保护方式下的编程技术,真实和生动地展示了保护方式下的编程细节。第三部分是上机实验指导。 本书的第一部分适合初学者,可作为学习汇编语言程序设计的教材。本书的第二部分适合已基本掌握8086/8088汇编语言的程序员,可作为学习保护方式编程技术的教材或参考书,也可作为其他人员了解高档微处理器和保护方式编程技术的参考书,还可作为程序员透彻地了解Windows程序设计技术的参考书。 第一部分 基础部分 第1章 绪论 1.1 汇编语言概述 1.1.1 汇编语言 1.1.2 汇编语言的特点 1.1.3 恰当地使用汇编语言 1.2 数据的表示和类型 1.2.1 数值数据的表示 1.2.2 非数值数据的表示 1.2.3 基本数据类型 1.3 Intel系列CPU简介 1.3.1 8位微处理器 1.3.2 16位微处理器 1.3.3 32位微处理器 1.3.4 Pentium和Pentium Pro 1.4 习题 第2章 8086/8088寻址方式和指令系统 2.1 8086/8088寄存器组 2.1.1 8086/8088 CPU寄存器组 2.1.2 标志寄存器 2.2 存储器分段和地址的形成 2.2.1 存储单元的地址和内容 2.2.2 存储器的分段 2.2.3 物理地址的形成 2.2.4 段寄存器的引用 2.3 8086/8088的寻址方式 2.3.1 立即寻址方式 2.3.2 寄存器寻址方式 2.3.3 直接寻址方式 2.3.4 寄存器间接寻址方式 2.3.5 寄存器相对寻址方式 2.3.6 基址加变址寻址方式 2.3.7 相对基址加变址寻址方式 2.4 8086/8088指令系统 2.4.1 指令集说明 2.4.2 数据传送指令 2.4.3 堆栈操作指令 2.4.4 标志操作指令 2.4.5 加减运算指令 2.4.6 乘除运算指令 2.4.7 逻辑运算和移位指令 2.4.8 转移指令 2.5 习题 第3章 汇编语言及其程序设计初步 3.1 汇编语言的语句 3.1.1 语句的种类和格式 3.1.2 数值表达式 3.1.3 地址表达式 3.2 变量和标号 3.2.1 数据定义语句 3.2.2 变量和标号 3.3 常用伪指令语句和源程序组织 3.3.1 符号定义语句 3.3.2 段定义语句 3.3.3 汇编语言源程序的组织 3.4 顺序程序设计 3.4.1 顺序程序举例 3.4.2 简单查表法代码转换 3.4.3 查表法求函数值 3.5 分支程序设计 3.5.1 分支程序举例 3.5.2 利用地址表实现多向分支 3.6 循环程序设计 3.6.1 循环程序举例 3.6.2 多重循环程序举例 3.7 习题 第4章 子程序设计和DOS功能调用 4.1 子程序设计 4.1.1 过程调用和返回指令 4.1.2 过程定义语句 4.1.3 子程序举例 4.1.4 子程序说明信息 4.1.5 寄存器的保护与恢复 4.2 主程序与子程序间的参数传递 4.2.1 利用寄存器传递参数 4.2.2 利用约定存储单元传递参数 4.2.3 利用堆栈传递参数 4.2.4 利用CALL后续区传递参数 4.3 DOS功能调用及应用 4.3.1 DOS功能调用概述 4.3.2 基本I/O功能调用 4.3.3 应用举例 4.4 磁盘文件管理及应用 4.4.1 DOS磁盘文件管理功能调用 4.4.2 应用举例 4.5 子程序的递归和重入 4.5.1 递归子程序 4.5.2 可重入子程序 4.6 习题 第5章 输入输出与中断 5.1输 入和输出的基本概念 5.1.1 I/O端口地址和I/O指令 5.1.2 数据传送方式 5.1.3 存取RT/CMOS RAM 5.2 查询方式传送数据 5.2.1 查询传送方式 5.2.2 读实时钟 5.2.3 查询方式打印输出 5.3 中断 5.3.1 中断和中断传送方式 5.3.2 中断向量表 5.3.3 中断响应过程 5.3.4 外部中断 5.3.5 内部中断 5.3.6 中断优先级和中断嵌套 5.3.7 中断处理程序的设计 5.4 基本输入输出系统BIOS 5.4.1 基本输入输出系统BIOS概述 5.4.2 键盘输入 5.4.3 显示输出 5.4.4 打印输出 5.5 软中断处理程序举例 5.5.1 打印I/O程序 5.5.2 时钟显示程序 5.6 习题 第6章 简单应用程序的设计 6.1 字符串处理 6.1.1 字符串操作指令 6.1.2 重复前缀 6.1.3 字符串操作举例 6.2 十进制数算术运算调整指令及应用 6.2.1 组合BCD码的算术运算调整指令 6.2.2 未组合BCD码的算术运算调整指令 6.2.3 应用举例 6.3 DOS程序段前缀和特殊情况处理程序 6.3.1 DOS程序段前缀PSP 6.3.2 对Ctrl+C键和Ctrl+Break键的处理 6.4 TSR程序设计举例 6.4.1 驻留的时钟显示程序 6.4.2 热键激活的TSR程序 6.5 习题 第7章 高级汇编语言技术 7.1 结构和记录 7.1.1 结构 7.1.2 记录 7.2 宏 7.2.1 宏指令的定义和使用 7.2.2 宏指令的用途 7.2.3 宏指令中参数的使用 7.2.4 特殊的宏运算符 7.2.5 宏与子程序的区别 7.2.6 与宏有关的伪指令 7.2.7 宏定义的嵌套 7.3 重复汇编 7.3.1 伪指令REPT 7.3.2 伪指令IRP 7.3.3 伪指令IRPC 7.4 条件汇编 7.4.1 条件汇编伪指令 7.4.2 条件汇编与宏结合 7.5 源程序的结合 7.5.1 源程序的结合 7.5.2 宏库的使用 7.6 习题 第8章 模块化程序设计技术 8.1 段的完整定义 8.1.1 完整的段定义 8.1.2 关于堆栈段的说明 8.1.3 段组的说明和使用 8.2 段的简化定义 8.2.1 存储模型说明伪指令 8.2.2 简化的段定义伪指令 8.2.3 存储模型说明伪指令的隐含动作 8.3 模块间的通信 8.3.1 伪指令PUBLIC和伪指令EXTRN 8.3.2 模块间的转移 8.3.3 模块间的信息传递 8.4 子程序库 8.4.1 子程序库 8.4.2 建立子程序库 8.4.3 使用举例 8.5 编写供Turbo C调用的函数 8.5.1 汇编格式的编译结果 8.5.2 汇编模块应该遵守的约定 8.5.3 参数传递和寄存器保护 8.5.4 举例 8.6 习题 第二部分 提高部分 第9章 80386程序设计基础 9.1 80386寄存器 9.1.1 通用寄存器 9.1.2 段寄存器 9.1.3 指令指针和标志寄存器 9.2 80386存储器寻址 9.2.1 存储器寻址基本概念 9.2.2 灵活的存储器寻址方式 9.2.3 支持各种数据结构 9.3 80386指令集 9.3.1 数据传送指令 9.3.2 算术运算指令 9.3.3 逻辑运算和移位指令 9.3.4 控制转移指令 9.3.5 串操作指令 9.3.6 高级语言支持指令 9.3.7 条件字节设置指令 9.3.8 位操作指令 9.3.9 处理器控制指令 9.4 实方式下的程序设计 9.4.1 说明 9.4.2 实例 9.5 习题 第10章 保护方式下的80386及其编程 10.1 保护方式简述 10.1.1 存储管理机制 10.1.2 保护机制 10.2 分段管理机制 10.2.1 段定义和虚拟地址到线性地址转换 10.2.2 存储段描述符 10 2.3 全局和局部描述符表 10.2.4 段选择子 10.2.5 段描述符高速缓冲寄存器 10.3 80386控制寄存器和系统地址寄存器 10.3.1 控制寄存器 10 3.2 系统地址寄存器 10.4 实方式与保护方式切换实例 10.4.1 演示实方式和保护方式切换的实例(实例一) 10.4.2 演示32位代码段和16位代码段切换的实例(实例二) 10.5 任务状态段和控制门 10.5.1 系统段描述符 10.5.2 门描述符 10.5.3 任务状态段 10.6 控制转移 10.6.1 任务内无特权级变换的转移 10.6.2 演示任务内无特权级变换转移的实例(实例三) 10.6.3 任务内不同特权级的变换 10.6.4 演示任务内特权级变换的实例(实例四) 10.6.5 任务切换 10.6.6 演示任务切换的实例(实例五) 10.7 80386的中断和异常 10.7.1 80386的中断和异常 10.7.2 异常类型 10.7.3 中断和异常的转移方法 10.7.4 演示中断处理的实例(实例六) 10.7.5 演示异常处理的实例(实例七) 10.7.6 各种转移途径小结 10.8 操作系统类指令 10.8.1 实方式和任何特权级下可执行的指令 10.8.2 实方式及特权级0下可执行的指令 10 8.3 只能在保护方式下执行的指令 10.8.4 显示关键寄存器内容的实例(实例八) 10.8.5 特权指令 10.9 输入/输出保护 10.9.1 输入/输出保护 10.9.2 重要标志保护 10.9.3 演示输入/输出保护的实例(实例九) 10.10 分页管理机制 10.10.1 存储器分页管理机制 10.10.2 线性地址到物理地址的转换 10.10.3 页级保护和虚拟存储器支持 10.10.4 页异常 10.10.5 演示分页机制的实例(实例十) 10.11 虚拟8086方式 10.11.1 V86方式 10.11.2 进入和离开V86方式 10.11.3 演示进入和离开V86方式的实例(实例十一) 10.11.4 V86方式下的敏感指令 10.12 习题 第11章 80486及Pentium程序设计基础 11.1 80486程序设计基础 11.1.1 寄存器 11.1.2 指令系统 11.1.3 片上超高速缓存 11.2 80486对调试的支持 11 2.1 调试寄存器 11.2.2 演示调试故障/陷阶的实例 11.3 Pentium程序设计基础 11.3.1 寄存器 11.3.2 指令系统 11.3.3 处理器的识别 11.3.4 片上超高速缓存 11.4 基于Pentium的程序优化技术 11.4.1 流水线优化技术 11.4.2 分支优化技术 11.4.3 超高速缓存代化技术 11.5 习题 第三部分 上机实验指导 第12章 实验指导 12.1 实验的一般步骤 12.2 汇编器和连接器的使用 12.2.1 MASM的使用 12.2.2 LINK的使用 12.2.3 TASM的使用 12.2.4 TLINK的使用 12.3 调试器DEBUG的使用 12.3.1 启动和退出DEBUG 12.3.2 命令一览 12.3.3 利用DEBUG调试程序 12.4 Turbo Debugger的使用 12.4.1 启动和退出TD 12.4.2 利用TD调试汇编程序 参考文献 附录 Pentium指令与标志参考表

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值