保护模式

核心目的:实现由实模式到保护模式的转换

核心步骤:

    1)程序定义了GDT数据结构

    2)16位代码进行了一些与GDT有关的操作

    3)程序最后跳到32位代码中做了一点操作显存的工作

进入保护模式的主要步骤:

    1)准备GDT

    2)用lgdt加载gdtr

    3)关中断、打开A20

    4)置cr0的PE位

    5)跳转,进入保护模式

逻辑地址到线性地址的转换:

    1)先从GDTR寄存器中获得GDT基址。

    2)然后再GDT中以段选择器高13位位置索引值得到段描述符。

    3)段描述符符包含段的基址、限长、优先级等各种属性,这就得到了段的起始地址(基址),再以基址加上偏移地址yyyyyyyy才得到最后的线性地址。

怎样查看线性地址的内容:

    sudo ndisasm -o 0x7c00 pmtest1.bin >> wz.asm 同

    x /80bx 0x00007c80 命令对比,可以看到线性地址中的内容一一对应



; ==========================================

; pmtest1.asm

; 编译方法:nasm pmtest1.asm -o pmtest1.bin

; ==========================================

%include "pm.inc" ; 常量, 宏, 以及一些说明

org 07c00h

        jmp LABEL_BEGIN


[SECTION .gdt]

; GDT

;                                                           段基址,      段界限 ,                       属性

LABEL_GDT:   Descriptor                    0,                0,                                0          ; 空描述符

LABEL_DESC_CODE32: Descriptor   0,                 SegCode32Len - 1,    DA_C + DA_32; 非一致代码段

LABEL_DESC_VIDEO:  Descriptor      0B8000h,    0ffffh,                            DA_DRW     ; 显存首地址

; GDT 结束


GdtLen equ $ - LABEL_GDT ; GDT长度

GdtPtr dw GdtLen - 1 ; GDT界限

            dd 0 ; GDT基地址


; GDT 选择子

SelectorCode32 equ LABEL_DESC_CODE32 - LABEL_GDT

SelectorVideo equ LABEL_DESC_VIDEO - LABEL_GDT

; END of [SECTION .gdt]


[SECTION .s16]

[BITS 16]

LABEL_BEGIN:

        mov ax, cs

        mov ds, ax

        mov es, ax

        mov ss, ax

        mov sp, 0100h   //栈顶指针寄存器

        ; 初始化 32 位代码段描述符

        xor eax, eax

        mov ax, cs

        shl eax, 4

        add eax, LABEL_SEG_CODE32                        //eax为 cs:LABEL_SEG_CODE32

        mov word [LABEL_DESC_CODE32 + 2], ax      //将LABEL_SEG_CODE32放到第二个字(也即3 4字节)

        shr eax, 16

        mov byte [LABEL_DESC_CODE32 + 4], al          //将al放到低字节

        mov byte [LABEL_DESC_CODE32 + 7], ah          //将ah放到高字节

        ; 为加载 GDTR 作准备

        xor eax, eax

        mov ax, ds

        shl eax, 4

        add eax, LABEL_GDT ; eax <- gdt 基地址

        mov dword [GdtPtr + 2], eax ; [GdtPtr + 2] <- gdt 基地址

        ; 加载 GDTR

        lgdt [GdtPtr]

        ; 关中断

        cli

        ; 打开地址线A20

        in al, 92h

        or al, 00000010b

        out 92h, al

        ; 准备切换到保护模式

        mov eax, cr0

        or eax, 1

        mov cr0, eax

        ; 真正进入保护模式

        jmp dword SelectorCode32:0 ; 执行这一句会把 SelectorCode32 装入 cs,

                                                        ; 并跳转到 Code32Selector:0  处

; END of [SECTION .s16]


[SECTION .s32]; 32 位代码段. 由实模式跳入.

[BITS 32]

LABEL_SEG_CODE32:

        mov ax, SelectorVideo

        mov gs, ax ; 视频段选择子(目的)

        mov edi, (80 * 11 + 79) * 2 ; 屏幕第 11 行, 第 79 列。

        mov ah, 0Ch ; 0000: 黑底    1100: 红字

        mov al, 'P'

        mov [gs:edi], ax

        ; 到此停止

        jmp $

SegCode32Len equ $ - LABEL_SEG_CODE32

; END of [SECTION .s32]


1.实模式

    Intel 8086 16位CPU,有16位的寄存器、16位的数据总线以及20位的地址总线(1MB的寻址能力)。

    物理地址 = 段地址 x 16 + 偏移

    此时段地址可以看做是地址的一部分。

2.保护模式

    Intel 80386进入32位时代,有32位地址总线(寻址空间可达4GB)。

    保护模式下段的概念发生了变化,段地址仍虽然由原来16位cs、ds寄存器表示,但此时它变成了一个索引,这个索引指向一个数据结构的一个表项,表项中详细定义了段的起始地址、界限、属性等。这个数据结构,就是GDT(LDT),GDT中的表项也有一个专门的名字,叫做描述符。

    GDT的作用是提供段式存储机制,这种机制是通过段寄存器和GDT中描述符共同提供的。

保护模式_第1张图片

; 宏 ------------------------------------------------------------------------------------------------------

;

; 描述符

; usage: Descriptor Base, Limit, Attr

;            Base:  dd

;            Limit: dd (low 20 bits available)

;            Attr:  dw (lower 4 bits of higher byte are always 0)

%macro Descriptor 3

        dw      %2 & 0FFFFh                            ; 段界限1   //将limit的低16位放在最低0 1两个字节

        dw      %1 & 0FFFFh                            ; 段基址1   //将base的低16位放在2 3字节

        db      (%1 >> 16) & 0FFh                      ; 段基址2   //将base的第三位字节放在4字节

        dw      ((%2 >> 8) & 0F00h) | (%3 & 0F0FFh)    ; 属性1 + 段界限2 + 属性2  //按字节位置进行拼凑成 5 6字节

        db      (%1 >> 24) & 0FFh                      ; 段基址3   //将base的第四字节(从低位开始计数)放在7字节

%endmacro ; 共 8 字节

3.保护模式——段选择子(段选择符)

    段选择子包括三部分:描述符索引(index)、TI、请求特权级(RPL)。他的index(描述符索引)部分表示所需要的段的描述符在描述符表的位置,由这个位置再根据在GDTR中存储的描述符表基址就可以找到相应的描述符。然后用描述符表中的段基址加上逻辑地址(SEL:OFFSET)的OFFSET就可以转换成线性地址,段选择子中的TI值只有一位0或1,0代表选择子是在GDT选择,1代表选择子是在LDT选择。请求特权级(RPL)则代表选择子的特权级,共有4个特权级(0级、1级、2级、3级)。


保护模式_第2张图片

    SelectorVideo equ LABEL_DESC_VIDEO - LABEL_GDT  //  所需要的段的描述符在描述符表的位置

    mov ax, SelectorVideo

    mov gs, ax ; 视频段选择子(目的)      //段选择子(Selector)由GDTR访问全局描述符表是通过“段选择子”(实模式下的段寄存器)来完成的。段选择子是一个16位的寄存器(同实模式下的段寄存器相同),这里是寄存器gs


保护模式_第3张图片
逻辑地址到线性地址的转换


    mov [gs:edi], ax   //gs的之为SelectorVideo,它对应显存的描述符DESC_VIDEO,这条指令将ax的值写入段DESC_VIDEO显存中偏移位edi的位置。

4.实模式到保护模式

step1.将描述符LABEL_DESC_CODE32初始化完成:将LABEL_SEG_CODE32的物理地址赋值给eax,并将它分成三部分赋值给描述符LABEL_DESC_CODE32中的相应位置。

保护模式_第4张图片

step2.将GdtPtr指示的6字节加载到寄存器gdtr

    GdtLen equ $ - LABEL_GDT ; GDT长度

    GdtPtr dw GdtLen - 1 ; GDT界限

            dd 0 ; GDT基地址

    lgdt [GdtPtr]


step3.关中断,保护模式下中断处理机制是不同的

step4.打开A20地址线。A20地址不打开,只能寻址1MB

step5.将寄存器cr0的第0位置为1

    寄存器cr0的第0位是PE位,0-实模式,1-保护模式


保护模式_第5张图片

step6.此时cs的值仍是实模式下的值,需要把代码段的选择子装入cs

    jmp dword SelectorCode32:0

    jmp dword ptr内存地址:以内存地址单元处的双字来修改指令,高地址内容修改CS,低地址内容修改IP,内存地址可以以任何合法的方式给出

    sudo ndisasm -o 0x7c00 pmtest1.bin >> wz.asm查看值

    00007C75  66EA000000000800  jmp dword 0x8:0x0   这里的SelectorCode32为8,赋值给cs

    bochs调试模式中,sreg可以看到cs的内容:

    cs:0x0008, dh=0x00409900, dl=0x7c800014, valid=1

    Code segment, base=0x00007c80, limit=0x00000014, Execute-Only, Non-Conforming, Accessed, 32-bit

5.描述符属性

LABEL_DESC_CODE32: Descriptor  0,                SegCode32Len - 1,    DA_C + DA_32; 非一致代码段

LABEL_DESC_VIDEO:  Descriptor      0B8000h,    0ffffh,                         DA_DRW     ; 显存首地址


DA_C            EQU    98h    ; 存在的只执行代码段属性值                       1001 1000

DA_32          EQU    4000h  ; 32 位段                                     100 0000 0000 0000

DA_DRW      EQU    92h    ; 存在的可读写数据段属性值                        1001 0010


dw      ((%2 >> 8) & 0F00h) | (%3 & 0F0FFh)    ; 属性1 + 段界限2 + 属性2  //按字节位置进行拼凑成 5 6字节

保护模式_第6张图片

你可能感兴趣的:(保护模式)