存储器分段和地址计算
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,则要在两个或多个数据段中存取数据,此时
需要改变数据段寄存器的段值。
转自:http://blog.csdn.net/yanxiansheng/article/details/7183042