切换到保护模式

切换到保护模式很简单:只需在控制寄存器中设置一个位即可。但是保持在保护模式下,由于不知道接下来要做什么而没有 CPU 丢失并重置自己,需要做很多准备。

简而言之,所需的步骤如下:

  • 需要设置全局描述符表的内存区域以定义至少三个描述符:

    1. 零,NULL 描述符;

    2. 代码段的另一个描述符;

    3. 数据段的另一个描述符。

      这可以用于数据和堆栈。

  • 需要初始化全局描述符表寄存器(GDTR)以指向该定义的存储区域;

     GDT_Ptr    dw      SIZE GDT
                dd      OFFSET GDT
    
                ...
    
                lgdt    [GDT_Ptr]
    
  • 需要设置 CR0 中的 PM 位:

         mov   eax, cr0      ; Get CR0 into register
         or    eax, 0x01     ; Set the Protected Mode bit
         mov   cr0, eax      ; We're now in Protected Mode!
    
  • 需要从 GDT 加载段寄存器以删除当前的实模式值:

         jmp   0x0008:NowInPM  ; This is a FAR Jump. 0x0008 is the Code Descriptor
    
    NowInPM:
         mov   ax, 0x0010      ; This is the Data Descriptor
         mov   ds, ax
         mov   es, ax
         mov   ss, ax
         mov   sp, 0x0000      ; Top of stack!
    

请注意,这是最小,只是为了让 CPU 进入保护模式。要实际使整个系统准备就绪可能需要更多步骤。例如:

  • 可能必须启用高端存储区 - 关闭 A20 门;
  • 绝对应该禁用中断 - 但是在进入保护模式之前可能会设置各种故障处理程序,以便在处理过程中尽早发生错误。

本节的原作者编写了一个关于进入保护模式并使用它的完整教程