内存寻址模式
程序的内存寻址是一个重要的概念。现在来具体介绍一下这方面的概念。比如内存地址可以分为逻辑地址,线性地址和物理地址,以及内存寻址模式中的实模式、保护模式,分段模型以及平坦模型。
2.3.1 逻辑地址,线性地址,物理地址
1.逻辑地址是编译器生成的,我们使用在linux环境下,使用C语言指针时,指针的值就是逻辑地址。对于每个进程而言,他们都有一样的进程地址空间,类似的逻辑地址,甚至很可能相同。逻辑地址由段地址+段内偏移组成
2.线性地址是由分段机制将逻辑地址转化而来的,如果没有分段机制作用,那么程序的逻辑地址就是线性地址了。
3.物理地址是CPU在地址总线上发出的电平信号,要得到物理地址,必须要将逻辑地址经过分段,分页等机制转化而来。
实模式和保护模式相对,实模式运行于20位地址总线,保护模式则启用了32位地址总线,地址使用的是虚拟地址,引入了描述符表;虽然二者都引入了段这样一个概念,但是实模式的段是64KB固定大小,只有16个不同的段,CS,DS等存储的是段的序号。保护模式则引入了GDT和LDT段描述符表的数据结构来定义每个段。
扁平模型和分段模型相对,区别在于程序的线性地址是共享一个地址空间还是需要分成多个段,即为多个程序是同时运行在同一个CS,DS的范围内还是每个程序都拥有自己的CS,DS:也就是说前者(flat)指令的逻辑地址要形成线性地址,不需要切换CS,DS;后者的逻辑地址,必须要经过段选择子去查找段描述符,切换CS,DS,才能形成线性地址。
X86体系结构下,使用的较多的内存寻址模型主要有三种:
1. 实模式扁平模型 real mode flat model
2. 实模式分段模型 real mode segment model
3. 保护模式扁平模型 protected mode flat model
2.3.2 实模式分段模型
在实模式里,20位地址总线,16位的寄存器无法表示,一个基址寄存器+一个段寄存器联合起来则可以表示更大的一个地址空间。于是发明了这种段寄存器左移4位+基址寄存器用以间接寻址。
20根地址线,表示 0x00000
- 0xfffff这个范围的地址(即
对于不同的程序,有不同的CS,DS值,每个程序的段起始地址都不同。对于这样的程序而言,偏移地址16位的特性决定了每个段只有64KB大小。
2.3.3 保护模式平坦模型
Linux, Window XP/7采用的内存寻址模型,Linux中,段主要分为4种,即为内核代码段,内核数据段,用户代码段,用户数据段。对于内核代码段和数据段而言,CS,DS的值是0xC00000000,而用户代码和数据段的CS,DS的值是0x00000000 当CPU运行于32位模式时,不管怎样,寄存器和指令都可以寻址整个线性地址空间,所以根本就不需要像16位系统中为了寻址的需要再去使用基地址。基址可以设为一个统一的值,此即为平坦模式。