内存寻址模式

程序的内存寻址是一个重要的概念。现在来具体介绍一下这方面的概念。比如内存地址可以分为逻辑地址,线性地址和物理地址,以及内存寻址模式中的实模式、保护模式,分段模型以及平坦模型。

2.3.1 逻辑地址,线性地址,物理地址

1.逻辑地址是编译器生成的,我们使用在linux环境下,使用C语言指针时,指针的值就是逻辑地址。对于每个进程而言,他们都有一样的进程地址空间,类似的逻辑地址,甚至很可能相同。逻辑地址由段地址+段内偏移组成

2.线性地址是由分段机制将逻辑地址转化而来的,如果没有分段机制作用,那么程序的逻辑地址就是线性地址了。

3.物理地址是CPU在地址总线上发出的电平信号,要得到物理地址,必须要将逻辑地址经过分段,分页等机制转化而来。

 

实模式和保护模式相对,实模式运行于20位地址总线,保护模式则启用了32位地址总线,地址使用的是虚拟地址,引入了描述符表;虽然二者都引入了段这样一个概念,但是实模式的段是64KB固定大小,只有16个不同的段,CS,DS等存储的是段的序号。保护模式则引入了GDTLDT段描述符表的数据结构来定义每个段。

扁平模型和分段模型相对,区别在于程序的线性地址是共享一个地址空间还是需要分成多个段,即为多个程序是同时运行在同一个CSDS的范围内还是每个程序都拥有自己的CSDS:也就是说前者(flat)指令的逻辑地址要形成线性地址,不需要切换CSDS;后者的逻辑地址,必须要经过段选择子去查找段描述符,切换CSDS,才能形成线性地址。

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这个范围的地址(即1M 而寄存器16位,还有4位怎么办?于是8086CPU1MB的存储器空间分成许多逻辑段,每个段最大限制为64KB(为了能让16位寄存器寻址,2^20=2^10*2^10=2^10*2^6*2^4==16*64K), 段地址就是逻辑段在主存中的起始位置。为了能用16位寄存器表示段地址,8086规定段地址必须是模16地址,即为xxxx0H形式,省略低40,段地址就可以用16位数据表示,它通常被保存在16位的段寄存器中。存单元距离段起始位置的偏移量简称偏移地址,由于限定每段不超过64KB,所以偏移地址也可以用16位数据表示。物理地址:在1M字节的存储器里,每一个存储单元都有一个唯一的20位地址,称为该存储单元的物理地址,把段地址左移4(因为段地址低4位都是零)再加上偏移地址就形成物理地址。Seg<<4+Offset 对于 8086/8088 运行在实模式的程序,其实就是运行在实模式分段模型中。

对于不同的程序,有不同的CSDS值,每个程序的段起始地址都不同。对于这样的程序而言,偏移地址16位的特性决定了每个段只有64KB大小。

2.3.3保护模式平坦模型

Linux Window XP/7采用的内存寻址模型,Linux中,段主要分为4种,即为内核代码段,内核数据段,用户代码段,用户数据段。对于内核代码段和数据段而言,CS,DS的值是0xC00000000,而用户代码和数据段的CS,DS的值是0x00000000 CPU运行于32位模式时,不管怎样,寄存器和指令都可以寻址整个线性地址空间,所以根本就不需要像16位系统中为了寻址的需要再去使用基地址。基址可以设为一个统一的值,此即为平坦模式。

周哥教IT,分享编程知识,提高编程技能,程序员的充电站。跟着周哥一起学习,每天都有进步。

通俗易懂,深入浅出,一篇文章只讲一个知识点。

当你决定关注「周哥教IT」,你已然超越了90%的程序员!

IT黄埔-周哥教IT技术交流QQ群:213774841,期待您的加入!

二维码
微信扫描二维码关注