本文大纲

  1. 关于80x86系列
  2. 8086 16-bit 寄存器
  3. 80386 32-bit 寄存器
  4. 实模式
  5. 16-bit保护模式
  6. 32-bit保护模式

如何看懂boot.S以及boot.c文件,需要做一些预备

关于80x86系列

  • 8088,8086:早期PC的CPU使用,仅支持1M空间,仅在实模式(real mode)下工作。在这种模式下,程序可以访问任何内存,即使该内存是其他程序的。同时,内存被分成段,每个段不能超多64K。

  • 80286:AT系列CPU使用。新特性是16位保护模式,在这个模式下可扩至16M,并且保护程序获取其他程序的内存。段依旧不能超过64K。

  • 80386:提升了8028。拓展了许多寄存器能够支持32位,增加了两个新的16位寄存器FS和GS。新增加了32位的保护模式。在这种模式下,能获取4G空间。与此同时,段也能访问到4G。

8086 16-bit 寄存器

  • 4个16位通用寄存器一般用于数据转移和算数指令:AX,BX,CX,DX。 每个寄存器有低8位与高8位,例如AX:AH AL

  • 2个16位索引寄存器,它们一般当作指针,和通用寄存器的目标类似,但是不能分为8位寄存器,它们是SI和DI。

  • 16位BP和SP寄存器用来指向在机器语言栈中的数据,之后会讨论到。

  • 4个段寄存器代表程序的不同部分的内存:CS代表代码段,DS代表数据段,SS代表栈段,ES代表附加段。

  • 指令指针寄存器IP与CS寄存器配合使用,追踪下一条CPU执行段指令的地址。

  • 标志寄存器,即FLAGS寄存器储存了之前指令结果的重要信息。

图:8086寄存器

80386 32-bit 寄存器

在8086基础的拓展,例如将16位的AX拓展为32位。为了向后兼容,AX依旧是16位寄存器,EAX是拓展32位寄存器。AX是EAX的低16位,就像AL是AX的低8位一样。

段寄存器依旧是16位,并且增加了两个新的段寄存器:FS和GS。它们和ES一样,就是额外的寄存器(备胎)。

实模式

在实模式下,内存只有1M大小,也就是2^20字节。对应的有效地址就是从00000到FFFFF。但是这么多的地址需要20位的数才能表示。但是对于8086的16位寄存器无法表示完整。Intel便通过两个16位的数才得到实模式下的地址。那么具体怎么得到呢,前16位的值叫做selectorselector值必须储存在段寄存器中。后16位的值叫做offset。这样物理地址就可以用一个32-bit的selector:offset来表示出来。通过一下的公式:

16*selector+offset

在16进制中乘以一个16很简单,就像在10进制中乘一个10一样,仅需要在selector后面加一个0,然后再将offset的值加上即可得到物理地址,例如

047C:0048

等于

047C0+0048,即04808

selector是16字节的数(也就是它有 24个地址,而每个地址有1字节内存)。当然,实段地址有一些不好的地方:

一个单一的select寄存器只能检索到64K大小,上界便是16-bit的offset。那如果有一个程序,其要运行的程序有大于64K的大小,那么这和问题如何解决?

  • 即将程序分为小于64K大小的sections中,当执行从一个段到另一个段时,CS的值必须改变。在大量数据以及DS寄存器下也会发生类似的问题。

在内存中的每个字节并不一定只有唯一的段地址。物理地址04808有可能是047C:0048, 047D:0038, 047E:0028或者047B:0058。这样段地址的比较就非常复杂。

16-bit保护模式

在80286的16位保护模式下,selector值与实模式下的值的解释是完全不一样的。 在实模式下,selector值为paragraph memory(16字节)。 在保护模式下,selector是到描述表(descriptor table)的一个索引值(index)。 两种模式下,程序都分为段: 在实模式下,这些段在物理内存的固定地址上,selector就是段开头的paragraph数, 在保护模式下,段不再在物理内存段固定地址,事实上,它们不一定要在内存中了。

在保护模式下,运用了一个叫做虚拟内存的技术一个虚拟内存的基本想法是,只要保证程序此时在用的数据和代码在内存中。其他的数据和代码可以暂时储存在磁盘上知道它们需要再次被使用。 在16-bit保护模式下,段在内存和磁盘之间移动: 当段从磁盘回到内存时,很有可能该段会被放在和它移动到磁盘之前的一个不同的地方。而这就时操作系统所做的。

保护模式下,每个段在描述表中分配了一个入口。这个入口上有系统想要知道该段段所有信息:它是否还在内存;如果在,那么在哪里;允许获取(例如只读)。那么,该段入口的索引值就是存储在段寄存器里的selector值。

不好的地方就是,offset依旧时16位的。因此段大小依旧限制在64K。

32-bit保护模式
  • 386的32-bit与286的16-bit保护模式比较,有两个主要的不同:

  • Offsets拓展到32-bits。这就允许一个offset达到4 billion,段的大小升级到4G。 段可以被分为更小的4K大小的页(pages)。虚拟内存就不再与段合作而是与页合作。

注意

关于内存,有一些计量单位,如下表:

名称 含义
word 2 bytes
double word 4 bytes
quad word 8 bytes
paragraph 16 bytes

参考资料: