zoukankan      html  css  js  c++  java
  • 保护模式详解

    在ia32下,cpu有两种工作模式:实模式和保护模式。

    在实模式下,16位的寄存器用“段+偏移”的方法计算有效地址。

    段寄存器始终是16位的。在实模式下,段值xxxxh表示的以xxxx0h开始的一段内存。但在保护模式下,段寄存器的值变成了一个索引(还有附加信息)这个索引指向了一个数据结构的表(gdt/ldt)项,表项(描述符)中详细定义了段的其实地址、界限、属性等内容。

    保护模式需要理解:描述符,选择子

    描述符包括,存储段描述符(代码段,数据段,堆栈段),系统描述符(任务状态段TSS,局部描述符表LDT),门描述符(调用门,任务门,中断门,陷阱门),下面以存储段描述符位例

    我们看一下描述符的结构:

    描述符共8个字节:

    0,1字节是段界限(2字节)

    2,3,4字节是段基址的低24位(3字节)

    5,6字节是段基址的属性(2字节)

    7字节是段机制的高8位(1字节)

    属性:

        (1) P:存在(Present)位。

        P=1 表示描述符对地址转换是有效的,或者说该描述符所描述的段存在,即在内存中;

        P=0 表示描述符对地址转换无效,即该段不存在。使用该描述符进行内存访问时会引起异常。

        (2) DPL:  表示描述符特权级(Descriptor Privilege level),共2位。它规定了所描述段的特权级,用于特权检查,以决定对该段能否访问。 
        (3) DT:说明描述符的类型。
        对于存储段描述符而言,DT=1,以区别与系统段描述符和门描述符(DT=0)。 
        (4) TYPE: 说明存储段描述符所描述的存储段的具体属性。
        数据段类型 类型值说明
        ----------------------------------
        0只读 
        1只读、已访问 
        2读/写 
        3读/写、已访问 
        4只读、向下扩展 
        5只读、向下扩展、已访问 
        6读/写、向下扩展 
        7读/写、向下扩展、已访问 

    选择子的结构:

     

    RPL(Requested Privilege Level): 请求特权级,用于特权检查。
        TI(Table Indicator): 引用描述符表指示位
        TI=0 指示从全局描述符表GDT中读取描述符;
        TI=1 指示从局部描述符表LDT中读取描述符。

    看一下段描述符的一个宏定义:

    
    
    1. ; 存储段描述符类型值说明  
    2. ;----------------------------------------------------------------------------  
    3. DA_DR       EQU 90h ; 存在的只读数据段类型值  1001 0000  
    4. DA_DRW      EQU 92h ; 存在的可读写数据段属性值 1001 0010  
    5. DA_DRWA     EQU 93h ; 存在的已访问可读写数据段类型值 1001 0011  
    6. DA_C        EQU 98h ; 存在的只执行代码段属性值 1001 1000  
    7. DA_CR       EQU 9Ah ; 存在的可执行可读代码段属性值 1001 1010  
    8. DA_CCO      EQU 9Ch ; 存在的只执行一致代码段属性值 1001 1100  
    9. DA_CCOR     EQU 9Eh ; 存在的可执行可读一致代码段属性值 1001 1110  


    59
    .; 宏 ------------------------------------------------------------------------------------------------------ 60.; 61.; 描述符 62.; usage: Descriptor Base, Limit, Attr 63.; Base: dd 64.; Limit: dd (low 20 bits available)低二十位可用 65.; Attr: dw (lower 4 bits of higher byte are always 0)高字节的低四位始终为0 66.%macro Descriptor 3 ;段界限为低地址 1代表Base 2代表Limit 3代表属性 67. dw %2 & 0FFFFh ; 段界限 1 (2 字节) 68. dw %1 & 0FFFFh ; 段首地址 1 (2 字节) 69. db (%1 >> 16) & 0FFh ; 段首地址 2 (1 字节) 70. dw ((%2 >> 8) & 0F00h) | (%3 & 0F0FFh) ; 属性 1 + 段界限 2 + 属性 2 (2 字节) 71. db (%1 >> 24) & 0FFh ; 段首地址 3 (1 字节) 72.%endmacro ; 共 8 字节

    base传递的是段基址:dd双字,32位

    limit传递的是段界限:dd双子,但只会用到低20位    ((%2>>8)& 0f00h)

    Attr传递的是属性:字16位,高字节的低4位会被抹去。(%3 & 0f0ffh)

    gdtr寄存器格式:

     (1)准备gdt。

    (2)加载gdt。

    (3)关中断,保护模式下的中断处理方式是不同的,不关中断可能发生错误。

    (4)打开a20地址线。

    (5)置cr0的PE位。

    (6)跳转进入保护模式。

    实例:

    
    


    ; ┏━━━┳━━━━━━━┳━━━━━━━━━━━┳━━━━━━━┓
    ; ┃31..24┃ (见下图) ┃ 段基址(23..0) ┃ 段界限(15..0)┃
    ; ┃ ┃ ┃ ┃ ┃
    ; ┃ 基址2┃③│② │ ①┃基址1b│ 基址1a ┃ 段界限1 ┃
    ; ┣━━━╋━━━┳━━━╋━━━━━━━━━━━╋━━━━━━━┫
    ; ┃ %6 ┃ %5 ┃ %4 ┃ %3 ┃ %2 ┃ %1 ┃
    ; ┗━━━┻━━━┻━━━┻━━━┻━━━━━━━┻━━━━━━━┛
    ; │ \_________
    ; │ \__________________
    ; │ \________________________________________________
    ; │
    ; ┏━━┳━━┳━━┳━━┳━━┳━━┳━━┳━━┳━━┳━━┳━━┳━━┳━━┳━━┳━━┳━━┓
    ; ┃ 7 ┃ 6 ┃ 5 ┃ 4 ┃ 3 ┃ 2 ┃ 1 ┃ 0 ┃ 7 ┃ 6 ┃ 5 ┃ 4 ┃ 3 ┃ 2 ┃ 1 ┃ 0 ┃
    ; ┣━━╋━━╋━━╋━━╋━━┻━━┻━━┻━━╋━━╋━━┻━━╋━━╋━━┻━━┻━━┻━━┫
    ; ┃ G ┃ D ┃ 0 ┃ AVL┃ 段界限 2 (19..16) ┃ P ┃ DPL ┃ S ┃ TYPE ┃
    ; ┣━━┻━━┻━━┻━━╋━━━━━━━━━━━╋━━┻━━━━━┻━━┻━━━━━━━━━━━┫
    ; ┃ ③: 属性 2 ┃ ②: 段界限 2 ┃ ①: 属性1 ┃
    ; ┗━━━━━━━━━━━┻━━━━━━━━━━━┻━━━━━━━━━━━━━━━━━━━━━━━┛
    ; 高地址 低地址
    ;
    ;
    %macro Descriptor 3 ;base(dd) limit(dd) attr(dw)
    dw %2 & 0FFFFh ; 段界限 1 (2 字节)
    dw %1 & 0FFFFh ; 段基址 1 (2 字节)
    db (%1 >> 16) & 0FFh ; 段基址 2 (1 字节)
    dw ((%2 >> 8) & 0F00h) | (%3 & 0F0FFh) ; 属性 1 + 段界限 2 + 属性 2 (2 字节)
    db (%1 >> 24) & 0FFh ; 段基址 3 (1 字节)
    %endmacro ; 共 8 字节

    
    

    DA_32 EQU 4000h ; 32 位段
    DA_DR EQU 90h ; 存在的只读数据段类型值
    DA_DRW EQU 92h ; 存在的可读写数据段属性值

    
    
    
    
    


    org 0100h
    jmp LABEL_BEGIN

    
    

    [SECTION .gdt]
    ;利用Descriptor 宏 base , limit ,attr
    LABEL_GDT: Descriptor 0, 0, 0 ;空描述符
    LABEL_DESC_32: Descriptor 0,CODE32_LEN-1,DA_32+DA_DR
    LABEL_DESC_VEDIO Descriptor 0B8000h,0ffffh,DA_DRW
    GDT_LEN EQU $-LABEL_GDT
    GDTPTR dw GDT_LEN-1 ;gdt界限
    dd 0
    ;GDT 选择子
    SelectorCode32 equ LABEL_DESC_32 - LABEL_GDT
    SelectorVedio equ LABEL_DESC_VEDIO - LABEL_GDT

    
    

    [SECTION .c16]
    [BITS 16]
    LABEL_BEGIN:
    mov ax,cs
    mov ds,ax
    mov es,ax
    mov ss,ax
    mov sp,0100h
    ;初始化gdt
    xor eax,eax
    mov ax,cs
    shl eax,4
    add eax,LABEL_SEC_CODE32
    mov word [LABEL_DESC_32+2],ax
    shr eax,16
    mov byte [LABEL_DESC_32+4],al
    mov byte [LABEL_DESC_32+7],ah
    ; 为加载 GDTR 作准备
    xor eax,eax
    mov ax,ds
    shl eax,4
    add eax,LABEL_GDT
    mov dword [GDTPTR+2], eax
    ;加载gtd
    lgtd [GDTPTR]
    ;关中断
    cli
    ;打开a20地址线
    in al,92h
    or al,00000010h
    out 92h,al
    ;cr0
    mov eax,cr0
    or eax,1
    mov cr0,eax

    
    

    ;jmp
    jmp dword SelectorCode32:0

    
    


    LABEL_SEC_CODE32:
    mov ax,SelectorCode32
    mov gs,ax
    mov edi, (80 * 10 + 0) * 2 ;10行0列
    mov ah, 0Ch ; 0000: 黑底 1100: 红字
    mov al,'P'
    mov [gs:edi],ax

    
    

    jmp $

    
    

    CODE32_LEN EQU $-LABEL_SEC_CODE32

     

    参考《自己动手写操作系统》

  • 相关阅读:
    docker学习(3) 容器的启动过程
    docker学习(2) mac中docker-machine使用vmware fusion以及配置国内镜像加速
    docker学习(1) 安装
    maven/gradle 打包后自动上传到nexus仓库
    bash/shell编程学习(3)
    jenkins 入门教程(下)
    jenkins 入门教程(中)
    jenkins 入门教程(上)
    bash/shell编程学习(2)
    ssh远程执行目标机器上的命令
  • 原文地址:https://www.cnblogs.com/andyhe/p/3753747.html
Copyright © 2011-2022 走看看