段地址问题,十六的倍数
过往牛人帮帮忙,有一句话不明白什么意思:cpu内一个段的起始地址一定是16的倍数,牛人本能不能帮忙解释一下这句话的含义啊,我在网上找了好长时间答案,相关论坛也去了不少,可就是没有能帮我解答的,纠结很长时间了! 回复 1# 玉成珏要回答你这个问题,就是回到intel的历史上。
段寄存器的产生源于Intel 8086 CPU体系结构中数据总线与地址总线的宽度不一致。
数据总线的宽度,也即是ALU(算数逻辑单元)的宽度,平常说一个CPU是“16位”或者“32位”指的就是这个。8086CPU的数据总线是16位。
地址总线的宽度不一定要与ALU的宽度相同。因为ALU的宽度是固定的,它受限于当时的工艺水平,当时只能制造出16位的ALU;但地址总线不一样,它可以设计得更宽。地址总线的宽度如果与ALU相同当然是不错的办法,这样CPU的结构比较均衡,寻址可以在单个指令周期内完成,效率最高;而且从软件的解决来看,一个变量地址的长度可以用整型或者长整型来表示会比较方便。
但是,地址总线的宽度还要受制于需求,因为地址总线的宽度决定了系统可寻址的范围,即可以支持多少内存。如果地址总线太窄的话,可寻址范围会很小。如果地址总线设计为16位的话,可寻址空间是2^16=64KB,这在当时被认为是不够的;Intel最终决定要让8086的地址空间为1M,也就是20位地址总线。
地址总线宽度大于数据总线会带来一些麻烦,ALU无法在单个指令周期里完成对地址数据的运算。有一些容易想到的可行的办法,比如定义一个新的寄存器专门用于存放地址的高4位,但这样增加了计算的复杂性,程序员要增加成倍的汇编代码来操作地址数据而且无法保持兼容性。
Intel想到了一个折中的办法:把内存分段,并设计了4个段寄存器,CS,DS,ES和SS,分别用于指令、数据、其它和堆栈。把内存分为很多段,每一段有一个段基址,当然段基址也是一个20位的内存地址。不过段寄存器仍然是16位的,它的内容代表了段基址的高16位,这个16位的地址后面再加上4个0就构成20位的段基址。而原来的16位地址只是段内的偏移量。这样,一个完整的物理内存地址就由两部分组成,高16位的段基址和低16位的段内偏移量,当然它们有12位是重叠的,它们两部分相加在一起,才构成完整的物理地址。
Base b15 ~ b12 b11 ~ b0
Offset o15 ~ o4 o3 ~ o0
Address a19 ~ a0
这种寻址模式也就是“实地址模式”。在8086中,段寄存器还只是一个单纯的16位寄存器,而且操作寄存器的指令也不是特权指令。通过设置段寄存器和段内偏移,程序就可以访问整个物理内存,无安全性可言。
总之一句话,段寄存器的设计是一个权宜之计,现在看来可以说是一个临时性的解决方案,设计它的目的是为了把地址空间从64KB扩展为1MB,仅此而已。但是它的加入却为日后Intel系列芯片的发展带来诸多不便,也为理解i386体系带来困扰。
从上面的分析可以看出,段寄存器的最低位对应地址的第5位,低4位的自由度为2^4 = 16! 因此段寄存器0x01对应的地址为16, 0x2对应的地址为32。也就是你说的16的倍数。
特别特别的感谢您,哈哈:roll: 有问题先百度google。如果也没能找到你的问题答案。请放开的CU的发贴。这里的大侠很多,我这小兵只是显显丑。论坛里头有很多精华贴,建议你多看看。
页:
[1]