全部博文(395)
分类: LINUX
2011-03-21 18:41:48
x86体系的处理器刚开始时只有20根地址线,寻址寄存器是16位。我们知道16位的寄存器可以访问64K的地址空间,如果程序要想访问大于64K的内存,就需要把内存分段,每段64K,用段地址+偏移量的方式来访问,这样使20根地址线全用上,最大的寻址空间就可以到1M字节,这在当时已经是非常大的内存空间了。 物理地址=左移4位的段地址+偏移地址。
可是当你仔细想一下你就会发现,这是为什么呢?其中的原理他还是没有说清楚,我就是郁闷了快半个学期了,后来找了老师问了一下,才算真的明白了
教科书上只讲:16+4=20位,所以16位段地址左移4位+16位偏移=20位物理地址。很多人也只是死记,其实并不知道其含义,而且还会感到晕,怎么16位左移4位,再加16位偏移就成20位了?
这下面是我在google上搜索的一个博客,挺有意思的,如下:
最近实在颓废,居然捡起一本汇编来看
人生实在是杯具
就在刚才,忽然发现自己对实模式的理解,有些错误(也许现在的理解才是错的)
问么个,么个说他忘光了,我一下就杯具了
8086 的 CPU 寄存器有 16位宽,也就是说它能取到的最大值为 FFFF H
如果一切都是如此美好,8086的CPU能够控制的地址也是16位的,从0000~到FFFF H
可是事实总是不近人情,8086的地址总线是20位宽的,也就是说它一次能通过的最大数据是 FFFFF H(比16位多了一个F)
为了充分的利用那20位的位宽,intel的工程师,设计了一种间接的寻址方式
实际地址=段寄存器内容×10H+偏移量寄存器内容
有趣的事发生了
寄存器能取到的最大值是 FFFF H,
我们把FFFF H带入到上面的公式,算一算
FFFF H * 10 H + FFFF > FFFFF H
所得到的结果,超过了20位
so
我在想,我们是不是搞反了一个问题,限制内存访问的是20位宽的数据总线,而不是实模式下的内存访问方式
即 实际地址=段寄存器内容×16+偏移量寄存器内容 -> 这种方式能够访问超过20位的地址空间(很真确,但是这个并不是重点)
但是,数据总线只有20位的宽
类似段寄存器内容为 FFFF ,偏移寄存器为 FFFF 的情况是不可能出现的?
但愿我没有错.. ...(怎么不会出现,也会出现,下面我就介绍一下为什么)
其实,道理也简单,如果基址寄存器(16位),偏移量寄存器(16位)都用上的话(不过确实也都用上了),
基址 1111 1110 1010 0011 1001
4《
1110 1010 0011 1001 0000
+
偏移量: 1001 1110 1100 0101 1010
===================================
1000 1000 1111 1110 1010
即物理地址为:0x88fea=561130 相当于大约是56k的地址了,但是这个56k(一个段中)的固定的物理地址也可以由另外的基址和偏移量构成,你想一想也就清楚了,是不是呀。
也就是说,一个基址和偏移量对应的是一个固定的物理地址,但是一个物理地址可以对应多个基址和偏移量了,
所以说程序员在访问一个实际地址的时候可以用不同的数据,
有一个问题就是程序用是以段来管理的,此时,如果你知道了一个段的基址和偏移量,此时如果你想知道下一个段得地址的话,程序员就得自己算了,因为段的值是不连续的,呵呵,
总算解释完了,应该明白了吧,呵呵(这个时候你该知道了,为啥一个段容量是64k了吧,其实就是偏移量寄存器的最大值,而你任意给出一个值,就会对应着一个段中的唯一地址,可能你给的两个值会指向同一个物理地址呢。。。。)