汇编语言简明教程
上QQ阅读APP看本书,新人免费读10天
设备和账号都新为新人

1.2.3 8086的存储器组织

个人计算机主板上的主存条和一个ROM芯片构成主存储器,保存正在运行使用的指令和数据。处理器从存储器读取指令,在执行指令的过程中读写数据。对存储器的基本操作是按照要求向指定地址(位置)存进(即写入Write)或取出(即读出Read)信息。应该注意的是,存储器内容不会因为被读出而消失,所以更准确地说是获取其副本,而且可以重复取出;只有存入新的信息后,原有信息才会被更改。

1. 存储单元和存储单位

主存储器是一个很大的信息储存库,被划分成许多存储单元。为了区分和识别各个存储单元,并按指定位置进行存取,就给每个存储单元编排一个顺序号码,称为存储单元地址或存储器地址(Memory Address)。现代计算机中,主存储器的每个存储单元具有一个地址,保存一个字节(8个二进制位)的信息,这称为字节编址(Byte Addressable),也直译为字节可寻址,因为通过一个存储器地址可以访问到一个字节信息。

计算机中信息的基本单位是一个二进制位(bit,中文译为比特),一般使用小写字母 b表示,一个二进制位可表示一位二进制数:0 或 1。8 个二进制位组成一个字节(Byte),常用大写字母B表示,位编号由右向左(由低位向高位)从0开始递增计数为D0~D7,如图1-6所示。8086是16位结构的处理器(即字长为16位),主要处理的数据长度是16位;所以称16个二进制位为一个字(Word),位编号自右向左为D0~D15。一个16位字由2个字节组成。32位数据由4个字节组成,称为双字(Double Word),位编号自右向左为D0~D31。

图1-6 数据的位格式

一个二进制数据的右边最低位称为最低有效位LSB(Least Significant Bit),即D0位;左边最高位称为最高有效位MSB(Most Significant Bit),对应字节、字、双字长度的数据依次指D7、D15和D31位。

主存储器使用字节作为基本存储单位,表1-3罗列了表达更大的存储容量时常使用的单位及关系。虽然借用了日常生活中千、兆、吉等单位,但没有使用其103的十进制倍数关系,而是使用 210=1024 的二进制倍数关系(近似等于 103=1000)。但有些产品,例如硬盘、U盘的生产厂商给出容量却采用103倍数关系,注意分辨。

表1-3 常用存储单位

2. 物理地址和逻辑地址

主存条和ROM芯片构成的主存储器需要处理器通过总线进行访问,被称为物理存储器。物理存储器的每个存储单元有一个唯一的地址,就是物理地址(Physical Address)。物理地址空间从0开始顺序编排,直到处理器支持的最大存储单元。

我们知道一个二进制位有0和1两种状态,即2(=21)个编码;那么,2位有00、01、10和11共4(22)个编码,以此类推,借助排列组合知识,可以得到N位有2N个编码。计算机使用数字信号传输信息,一个数字信号也只有低电平和高电平两个状态,可以分别用0和1表达,所以N位数字信号同样也有2N个不同的编码。如果用N个数字信号传输访问存储器的地址信息,就可以区别出2N个不同的存储单元,也就是说可以直接访问到2N个存储单元。

8086处理器具有20位地址总线,即用20个数字信号访问存储器,故8086可以支持220,即1M个存储单元。由于每个存储单元保存一个字节数据,所以8086可以支持1MB存储器容量,其物理地址空间是0~220−1。地址(编号)习惯用十六进制数表达,20位数字信号对应二进制20位,可以用5位十六进制数表达为:00000H~FFFFFH,参见图1-7左侧所示。

图1-7 物理地址和逻辑地址

但是,8086处理器只有16位寄存器,没有设计可以完整保存20位物理地址的寄存器。而使用二进制16位(对应十六进制4位)表示存储器地址,可以表达的存储器容量是64KB (=216字节),范围是:0000H~FFFFH。

于是,8086处理器将1MB物理存储器空间分成许多不超过64KB的区域进行管理,这种区域被称为(区)段(Segment)。段用于8086内部和程序设计中,所以常被称为逻辑段。

由于规定每段最大64KB,段内的存储单元就可以使用16位地址表示。同时,8086处理器还规定每个段只能起始于低4位(二进制)全为0的物理地址位置,这种地址是模16地址,也就是可以被 16 整除的地址(用十进制表达是:0、16、2×16、3×16……),用十六进制表达是:XXXX0H(X表示十六进制一位,可以是0~F任何值)。既然段起始地址的低4位都是0(对应十六进制是一位0),可以省略不用表达,那这个20位物理地址就可以只表达出高16位。

这样,某个存储单元还可以通过它所在的(区)段及在该段中的位置指示,这就是在8086内部以及编程中使用的逻辑地址(Logical Address),它包括段基地址和偏移地址,都可以使用 16 位表示。段基地址(常简称段地址)确定该段在主存中的起始地址。以段基地址为起点,段内的位置可以用距离该起点的位移量表示,称为偏移地址(Offset)。

逻辑地址常借用MASM汇编程序的方法,使用英文冒号“:”分隔段基地址和偏移地址,形如“段基地址:偏移地址”。并且在 8086 中,段基地址常只表达高 16 位。例如逻辑地址“1460H:0100H”表示段基地址是1460H,即该存储单元所在的段起始于物理地址14600H;该存储单元的偏移地址是0100H,说明它位于距离段起始位置的0100H处,参见图1-7中间所示。

编程使用的逻辑地址由8086总线接口单元BIU的地址加法器电路转换为物理地址,然后通过处理器引脚输出外部访问物理存储器。进行转换时,两个 16 位组成的逻辑地址中的段地址需要左移4位(十六进制一位),加上偏移地址才能得到20位物理地址。例如某存储单元的逻辑地址是“1460H:0100H”,其物理地址是14700H,参见图1-7右边所示。

某个存储单元可以处于不同起点的逻辑段中(当然对应的偏移地址也就不同),所以可以有多个逻辑地址,但只有一个唯一的物理地址。或者说,同一个物理地址可以有多个逻辑地址。例如,物理地址14700H还可以用逻辑地址“1380H:0F00H”表示,该段起始于13800H,参见图1-7所示。

3. 应用程序的基本段

8086设计有4种类型的逻辑段实现存储器的分段管理,有4个段寄存器保存对应段的段基地址(注意,只是保存高16位),如表1-4所示。

表1-4 8086的4种逻辑段

分段管理存储器空间也符合程序的模块化思想,应用程序通常需要使用3种类型的段:代码段、堆栈段和数据段,8086还设计有一个属于数据段类型的附加段。

程序的指令代码必须安排在代码段,否则将无法正常执行。程序利用代码段寄存器 CS获得当前代码段的段基地址,指令指针寄存器IP保存代码段中指令的偏移地址。处理器利用CS:IP取得下一条要执行的指令。

程序使用的堆栈(临时存放数据的区域)一定在堆栈段。程序利用SS获得当前堆栈段的段基地址,堆栈指针寄存器SP保存堆栈栈顶的偏移地址。处理器利用SS:SP操作堆栈数据。

一个程序可以使用多个数据段,便于安全有效地访问不同类型的数据。例如,程序的主要数据存放在一个数据段,只读的数据存放在另一个数据段,动态分配的数据安排在第3个数据段。8086 规定程序当前访问的数据默认安排在数据段(应用中无须特别说明),也允许将数据安排在其他段(需要明确指明),数据的偏移地址由各种存储器寻址方式计算出有效地址EA(详见第2章)。

4. 存储器的分段管理

8086 规定段基地址低 4 位均为 0,每段最大不超过 64KB。但并没有要求每段必须是64KB,各段之间可以完全分开,也可以部分重叠,甚至完全重叠。当然各段的内容是不允许发生冲突的。图1-8说明了这种情况。

图1-8 存储器的分段管理

图1-8(a)是各段独立的分配示例。CS=0150H、DS=4200H、SS=1CD0H、ES=B000H,它们分别为代码段、数据段、堆栈段和附加段的段地址。自每个段地址开始,各段均占64KB字节的范围,各段之间互不重叠。

图1-8(b)则是相互重叠段的分配示例。CS=0200H、DS=0400H、SS=0480H,这样代码段、数据段和堆栈段的物理起始地址分别为02000H、04000H和04800H。其中代码段大小为8KB,数据段占2KB,而堆栈段只有256字节,SP=0100H。由于该程序没有使用附加段,所以没有设置 ES 值。从这里可以看出,各段大小应根据实际需要来分配,可以重叠。有时,甚至可以将所有4种段都集中在一个逻辑段内,形成一个短小紧凑的程序,其大小不超过64KB。例如,在图1-8(b)所示的情况下,如果设置CS=DS=SS=0200H;这时,代码段将占据该逻辑段从偏移地址0000~1FFFH的8KB,而数据段在偏移地址2000H~27FFH位置,堆栈顶指针SP=2900H。