汇编学习笔记之实模式/保护模式内存寻址

实模式下的内存地址
    2的10次方是1K,20次方就是1M,30次方就是1G。
    Intel 8086是16位CPU,它只有16位寄存器、16位数据总线和20位地址总线,它只能运行在实模式。在实模式,物理地址=段值*16+偏移,段值和偏移都是16位的 具有1MB(2^16 * 2^4 + offset)的寻址能力。
    从80386开始CPU有32位地址线,所以寻址空间可以达到4GB。单从寻址这方面说,使用16位寄存器的方法已经不够用了,必须要开发一种新方法。在保护模式下,虽然CPU还是使用原来16位的cs、ds寄存器表示内存地址的段值,不过保护模式下的段值只是一个索引,这个索引指向一个数据结构的一个表项就是GDT(or LDT)。
在保护模式下,CPU有着巨大的寻址能力,并为强大的32位操作系统提供了更好的硬件保障。
    注:
    1.32位地址线的CPU下,16位cs/ds寄存器表示的内存地址段值只是一个索引,指向全局描述符表GDT,通过查表可知真实的基址。
    2.8086CPU与80386CPU,只有cs与ds两个段寄存器还是16位!!!

    问题来了!!!!!!!!!!!!!!!
    x86CPU工作在保护模式时,可以使用全部32根地址线访问4GB的内存,然而x86CPU(80386)的所有通用寄存器都是32位的.因此,用任何一个通用寄存器来间接寻址,不用分段就可以访问4G空间中任意的内存地址。
    那么为什么还需要分段寻址?
    在保护模式下,一个地址空间是否可以被写入,可以被多少优先级的代码写入,是不是允许执行等等涉及保护的问题就出来了。要解决这些问题,必须对一个地址空间定义一些安全上的属性。段寄存器这时就派上了用场。
    但是设计属性和保护模式下段的参数,要表示的信息太多了,要用64位长的数据才能表示。我们把着64位的属性数据叫做段描述符,上面说过,它包含3个变量:段物理首地址、段界限、段属性 80386的段寄存器是16位(注意:通用寄存器在保护模式下都是32位,但段寄存器没有被改变)的,无法放下保护模式下64位的段描述符。如何解决这个问题呢?方法是把所有段的段描述符顺序存放在内存中的指定位置,组成一个段描述符表(Descriptor Table);而段寄存器中的16位用来做索引信息,这时,段寄存器中的信息不再是段地址了,而是段选择子(Selector)。可以通过它在段描述符表中“选择”一个项目已得到段的全部信息。那么段描述符表存放在哪里呢?80386引入了两个新的寄存器来管理段描述符,就是GDT和LDT。这样,用以下几步来总体体验下保护模式下寻址的机制
1、段寄存器中存放段选择子Selector
2、GDT中存放着段描述符表的首地址
3、通过选择子根据GDT中的首地址,就能找到对应的段描述符
4、段描述符中有段的物理首地址,就得到段在内存中的首地址
5、加上偏移量,就找到在这个段中存放的数据的线性地址(只有分段机制情况下,就是真实物理地址)。

    接上面所述,GDT的作用就是用来提供段式存储机制,这种机制是通过段寄存器和GDT中的描述符共同提供的。因为要能够访问4GB内存,所以在32位模式下物理地址不能等于 段值*16+偏移 (这种方法寻址1MB)。于是,设计者让段值*16指向一个数据结构的一个表项就是GDT(or LDT),表项中详细定义了段的起始地址,界限和属性等内容。于是原先“段:偏移”形式的逻辑地址经过段机制转化成线性地址。如果只有分段机制,那么这个地址就是对应的真实内存的物理地址。
    注:如何实现8086CPU与80386CPU的兼容,判断段地址表示意义。

另:
    为什么要分页?
    其实它的主要目的在于实现虚拟存储器。
    接上面所述,刚刚说到线性地址,并且说如果只有分段机制,线性地址就是物理地址
    如果打开了分页机制后:
        逻辑地址-》分段机制-》线性地址-》分页机制-》物理地址
    是这样一套转化机制。

    另外,如果你写完一个程序后,复制了一份,然后同时调试。你会发现,从变量地址到寄存器的值,这两个程序几乎全部是都是一样的,而这些一样的地址之间完全不会被混淆,而是各自完成自己的职责,这也是分页机制的功劳。
    另外,因为分页机制的存在,程序使用的都是线性地址空间,而不再直接是物理地址。这好像是操作系统位应用程序提供了一个不依赖于硬件(物理内存)的平台,应用程序不必关心实际上有多少物理内存,也不必关心正在使用的是哪一段内存,甚至不必关心某一个地址是在物理内存里面还是在硬盘中。只要像操作系统申请就行,而操作系统全权负责了这其中的转换工作。

你可能感兴趣的:(汇编)