x86 实模式和32位保护模式

2020/09/01 os 共 1581 字,约 5 分钟

@[TOC]

x86寻址方式

基址-偏移寻址

x86 cpu的寻址方式在历史早期主要是分片寻址(segmentation),其基本设计是任何地址由base 和 offset组成,通过将地址空间按不同规则切分成多块,每块起始地址作为base,在每个区块的偏移作为offset即可定位到具体物理地址,分片寻址在x86历史主要有两种

  • real mode
  • 32bit protect mode real mode(实模式) 主要用在早期16bit机器上,其寻址范围为[0, 1Mb], 32bit protect mode是从里程碑式的80386 cpu开始使用的,将寻址范围扩展到整个32位空间即[0, 4Gb].

分页寻址

在现代的操作系统和处理器中已经基本不再使用分片寻址方式,仅作为历史适配,更为广泛使用的是分页寻址(paging), 分页寻址将地址区分为虚拟地址和物理地址,通过页表将两者映射,这样对于编程语言而言只需要关注虚拟地址即可,因为这种情况下虚拟地址空间是完全平坦统一的,因此又被称为flat addr space(平坦地址空间).

实模式寻址

实模式寻址(real mode)非常简单,其形式为cs:ip,其中cs为分片寄存器(segment register),x86一共有6个分片寄存器,这里暂时只需要关注cs知道其为代码段的分片寄存器即可。cs作为基址,ipeip寄存器代表偏移值,两者的范围均为[0, 0xffff], 可以发现只使用了16位,这是因为实模式只在16位机器时代运用,现代32或者64bit机器出于适配在启动时仍然会进入模拟16bit模式以使用实模式。

实模式下地址为addr = cs * 0x10 + ip,因此该模式下最多访问到1Mb地址空间,每个分片寻址空间为64kb。

x86 分片寄存器

registerusage
CSCode Segment
DSData Segment
SSStack Segment
ESExtra Segment
FSGeneral Purpose Segments
GSGeneral Purpose Segments

32位保护模式寻址

32 bit protected mode 是随着80386诞生而出现的,该寻址模式将地址空间扩展到整个32bit,最大寻址4Gb,这里的保护模式指的是每个分片可以指定CPU的执行权限等级,即 cpu ring0~ ring3,这样同时增加了权限保护。

这种模式的分片不再是固定,而是通过一个特殊格式的表来确定,称为GDT(global descriptor table), 使能时需要将该表的地址通过lgdt命令载入,GDT表的有多个entry,对应多个分片,运行时cs寄存器不再使用具体的值,而是赋值为需要的分片entry在GDT中的偏移。

GDT结构

GDT head

2020/09/GDT

  • size 为所有GDT entry的大小减1,减1是因为最大size可为65536,而32bit最大只能表示65535,同时size也不会为0.
  • offset为之后的GDT entry 表的起始物理地址

GDT entry

2020/09/gdt_entry

每个GDT entry 大小为8个byte, 其中Base一共有4个字节,范围[0, 4Gb], Limit一共占据20bit, 范围 [0, 1Mb], 剩余为一个8bit的AccessByte 和Flags,他们的结构如下:

2020/09/gdt_flag

其中每个位的详细含义可以查阅 12,其中值得关注的主要有:

  • Privi : 0~3代表CPU ring0~ring3
  • Ex: 为1代表可执行用于代码段,为0用于数据段
  • Gr: 分片粒度,为0则每个offset代表一个byte,为1则每个offset代表4Kb,如果此时将base设为0,Limit设为0xfffff,则此时一个分片即扩展到整个32bit空间即4Gb,通常在用不到分片而使用页表时这样设置

文档信息

Search

    Table of Contents