2008-05-21 1:24
存储器分段和地址计算
1. 存储单元的地址和内容 在8086 CPU系统中,以字节为单位线性地组织存储器。一个字节就是一个 存储单元,为了标识和访问每个存储单元,给每个存储单元规定一个编号,即 存储单元的地址 存储单元的地址用二进制无符号数表示,从0开始,顺序加1,则n位二进制 数可以表示2^n个存储单元的地址。 一个存储单元中存放的信息称为该存储单元的内容。当将一个字存放到存 储器时需要占用两个连续的字节,系统规定:把一个字存放到存储器时,低字节 存放在地址较低的字节单元,高字节存放在地址较高的字节单元, 例如:地址33451H中的字单元的内容为5612H _________________________00000H | ...... | |_______________________|33450H | 34H | |_______________________|33451H | 12H | |_______________________|33452H | 56H | |_______________________|33453H | 29H | |_______________________| | ...... | |_______________________| 这种存储原则称为“高高低低”原则。对于由四个连续字节构成的双字单元, 也使用同样的原则,例如地址33450H的双字单元中存放着数据29561234H。 2. 存储器的分段 8086 CPU有20根地址线,可直接寻址的地址空间为2^20=1M字节,即存储单元 的物理地址是20位的二进制无符号数,范围为00000H~FFFFFH。 但是,8086 CPU内部的算术逻辑单元只能进行16位运算,而且存放存储单元 地址偏移的指针寄存器(SP、BP、SI、DI、BX)均为16位,无法直接寻址1MB物理 地址。为此,把1MB地址空间划分成若干逻辑段,每个逻辑段满足如下条件: (1)逻辑段的开始地址必须是16的倍数——与段寄存器长16位有关 即逻辑段的起始地址最后四位必定为0000 (2)逻辑段的最大长度为64K——与指针寄存器长16位有关 3. 物理地址的计算 根据存储器的逻辑分段,如何计算实际的物理地址?很明显,逻辑段的起始 地址是16的倍数,即逻辑段的起始地址均具有如下形式: xxxxxxxxxxxxxxxx0000B = XXXX0H 这种段起始地址可以压缩为XXXXH,称为段值,即段起始地址等于段值成语16。 而要访问的存储单元总属于某个段,将存储单元地址与所在段起始地址的差 称为段内偏移,简称偏移。在给定段内,通过偏移完全可以确定要访问的存储单元, 因此在整个1MB地址空间中, 存储单元的物理地址 = 段起始地址 + 段内偏移 = 段值 × 16 + 段内偏移 = 段值 : 偏移 (简化表示) 采用“段值:偏移”构成逻辑地址后,段值由寄存器给出,偏移可以由指令指针IP、 堆栈指针SP、以及其它可用作存储器指针的寄存器(SI、DI、BX、BP)给出、或者直接用 16位数给出。指令中不使用物理地址,而使用逻辑地址,由CPU的总线接口单元BIU根据 段值和偏移自动计算出物理地址。 4. 段寄存器的引用 8086 CPU有四个段寄存器,可保持4个段值,故可同时使用4个段,但四个段各有分工。 每当需要生成物理地址时,BIU会自动引用特定的段寄存器来计算物理地址。 (1)取指令时,BIU自动引用代码段寄存器CS,再加上指令指针IP的16位偏移,得到 指令的物理地址; (2)当涉及堆栈操作时,则自动引用堆栈段寄存器SS,再加上SP的16位偏移,得到 堆栈操作所需的物理地址;当偏移涉及BP寄存器时,默认引用的段寄存器也是 堆栈段寄存器SS; (3)在存取存储器中的操作数时,自动选择数据段寄存器DS或附加段寄存器ES,再 加上16位偏移,得到操作数的物理地址。此时的16位偏移,可以说包含在指令 中的直接地址,也可以是某个16位存储器指针寄存器的值,也可以是指令中的 偏移再加上存储器指针寄存器的值,主要取决于指令的寻址方式。 在不改变段寄存器值的情况下,寻址范围最大是64KB。若某程序使用的总存储长度 (包括代码、堆栈、数据区)不超过64K,则整个程序可以合用一个段;若某程序的代码 长度、堆栈长度、数据区长度均不超过64KB,则可在程序开始处分别给DS、SS等段寄存 器赋值;若某程序的数据区长度超过64KB,则要在两个或多个数据段中存取数据,此时 需要改变数据段寄存器的段值。 |