保護模式

保護模式(英語:Protected Mode,或有時簡寫為 pmode)是一種80286系列和之後的x86兼容CPU的操作模式。保護模式有一些新的特性,如記憶體保護分頁系統以及硬體支援的虛擬記憶體,能夠增強多任务处理和系統穩定度。現今大部分的x86作業系統都在保護模式下運行,包含LinuxFreeBSD、以及微軟Windows 2.0和之後版本。

另外一種286和其之後CPU的操作模式是真實模式,這是一種向前相容且關閉了保护模式這些特性的CPU运行模式,用來讓新的晶片可以執行舊的軟體。所有的x86 CPU都是在真實模式下開機,來確保傳統作業系統的相容性。為了使用保護模式的特性,要由程式主動地切換到保護模式。在現今的電腦上,這種切換通常是作業系統在開機時候完成的第一件工作。當CPU在保護模式下運行時,可以使用虚拟86模式來執行為真實模式設計的程式碼。

儘管用軟體的方式也有某些可能在真實模式的系統下使用多工,但保護模式下記憶體保護的特色,可以避免有問題的程式破壞其他工作或是作業系統核心所擁有的記憶體。保護模式也有中斷正在執行程式的硬體支援,可以實現先佔式多工

大部分可以使用保護模式的CPU也擁有32位元暫存器的特性(例如80386系列和其後任何的晶片),導入了融合保護模式而成為32位元處理的概念。80286晶片雖有支援保護模式,但是仍然只有16位元暫存器。Windows 2.0和之後版本中的保護模式增強稱為"386增強模式",是因為他們除了保護模式外,還需要32位元的暫存器,並且無法在286上面執行(即使286支援保護模式)。

即使在32位元晶片上已經打開了保護模式,但是為了仿照IBM XT系統記憶體連續的設計特性,1 MiB以上的記憶體並無法存取。這種限制可以由打開A20总线來迴避。

在保護模式下,前面32個中斷都是保留給CPU例外處理用。例如,中斷0D(十進制13)是一般保護模式錯誤,而中斷00是除以零

286的保护模式寻址

 
286CPU在保护模式下的寻址

286出现之前,x86的地址总线为20位,使用16位的段基址(段首地址的高16位)与4位的段内偏移量,段基址左移4位后与段内偏移量相加形成20位的物理地址,来对220(即1MiB)的地址空间寻址。1982年问世的286 CPU首次使用了保护模式寻址。286 CPU的地址总线为24位,寻址空间为224(即16 MiB)。而286 CPU的寄存器仍为16位。[1]寻址时,段寄存器保存的数据不再是内存物理地址,而是称作选择器(selector),其中高13位指向描述符表(descriptor table)的条目;最低的两位数据定义了请求的权限,从0到3,0是最高权限,3是最低权限;剩下的一位表示是使用全局描述符表(GDT)还是局部描述符表英语Local Descriptor Table(LDT)。描述符表的条目为8字节长,包括24位长的段起始物理地址、16位长的段长(因此段的长度范围从1 B到216 B,即不超过64 KiB)。每次内存操作所要访问的物理地址为描述符表相应条目给出的24位段起始物理地址再加上16位的偏移量。可见,286保护模式下的应用程序能访问的内存线性地址空间仅为64 KB,非常有限。所以程序员编写使用大内存的应用程序时还必须使用远指针、近指针,相当繁琐。这影响了286保护模式的推广使用。

从386开始的IA32保护模式寻址

 
IA32 CPU保护模式下的4KiB分页寻址
 
IA32 CPU保护模式下的4 MiB分页寻址
 
应用程序的虚拟线性地址空间映射到分页管理的物理地址空间

1985年问世的80386开启了32位CPU时代。[2]地址总线为32比特,寻址空间为232(即4 GiB)。[3]386 CPU保护模式下有两种内存寻址方式:

  • 可以分页寻址,这是此后的x86上的Windows操作系统与Linux操作系统最广泛采用的方法;
  • 也可以非分页寻址而采取与286保护模式兼容的寻址方式,采用16位的选择器(selector)寄存器与32位的偏移量寄存器寻址,这时描述符表的条目中保存的段起始物理地址为32位,而段长的数据宽度为20位,但可以设置段长的粒度为1 B或4 KiB,所以段的最大长度可以是1 MiB或者4 GiB。

386 CPU开创的分页内存管理,比286保护模式寻址具有更多的优点:

  • 操作系统可以控制与限制进程对页面的访问权限
  • 为应用程序创造一个连续的、独立的、线性的虚拟内存空间
  • 页面可以移出主存,存入更慢速的次级外存硬盘。这使得操作系统可以使用比物理内存更大的存储空间。

IA32的CPU通过两级:页目(page directory)与页表(page table)实现4 KiB的分页管理,这是最常见的IA32分页寻址方式。CR3寄存器保存了进程的页目的物理地址。页目与页表中每4字节为一个单元,是一个32位的值,当页目项第0位为1时,表明页表已经在物理内存中;当页表项第0位为1时,表明访问的数据已经在内存中。另外,当页目项第7位为1时,表明这是一个4M的页面,这值已经是物理页地址,用虚拟地址的低22位作为偏移量。

从应用程序角度,不再使用段地址寄存器(或称选择器),仅使用32位的偏移量,为232(即4 GiB)的连续线性寻址空间。

进入保护模式

进入保护模式前,必须初始化全局描述符表,并最少包含三个描述符:空描述符、代码段描述符以及数据段描述符。并把(全局描述符表的所占用的字节数-1)和全局描述符表的物理内存地址保存到GDTR寄存器中。如果是IBM兼容的机器,则还需要打开A20总线

通过设置CR0寄存器的PE位进入保护模式。在设置完CR0寄存器的PE位后,需要进行远转移以清空PIQ。

; 设置CR0寄存器的PE位
mov eax, cr0       ; 必须通过其他寄存器来修改CR0寄存器
or eax, 1
mov cr0, eax

; 远转移 (cs = 代码段描述符)
jmp cs:@pmode

[bits 32]
@pmode:
; 现在已经进入了保护模式

参见

参考资料

  1. ^ A+ - Hardware. PC Microprocessor Developments and Features Tutorials. BrainBell.com. [2007-07-24]. (原始内容 (Tutorial/Guide)存档于2022-03-31). 
  2. ^ Intel Global Citizenship Report 2003. [2007-07-14]. (原始内容 (Timeline)存档于2008-03-22). 1985 Intel launches Intel386 processor 
  3. ^ 80386 Programmer's Reference Manual (PDF). Santa Clara, CA: Intel. 1986. Section 2.1 Memory Organization and Segmentation [2022-05-09]. (原始内容 (PDF)存档于2018-12-28). 

外部連結