zoukankan      html  css  js  c++  java
  • 段描述符表(GDT+LDT)的有感

    【0】写在前面

    要知道,在汇编中,代码的装入顺序决定了在内存中的地址位置。所有的代码或者数据都在硬盘上,当调试或者启动的时候,加载到内存;当需要对数据进行处理的时候,我们通过将数据从内存载入到registers 通过cpu来进行处理的。
    这里写图片描述
    这里写图片描述

    【1】初始化各种段描述符

    初始化 32 位代码段描述符 为例

    【2】有感

    首先:要先定义这段描述符(占据内存空间),然后向里面传入真正处理数据的地址;

    2.1 定义阶段

    为什么 LABEL_GDT 必须跟在最前面呢?

    • 因为它的地址要作为段的基地址,而选择子的地址作为偏移地址来定位某个段。你想想你C语言的数组,是不是这样排列的。首先数组首地址在开头,然后后面存储的是元素的地址,呵呵。碉堡了。一句话说完;
      只要吧LABEL_GDT放在某段内存的起始位置,跟在它后面的哪些段描述符(内存地址),都可以作为GDT中的元素(或者称为表项),这就是一个表(或者数组)的定义由来。

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

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

    2.2 定义选择子

    说白了,选择子就是某个段相对于全局描述符GDT的偏移地址; 当我们知道GDT的地址后,将其作为基地址,并将选择子作为偏移地址,来定位该段描述符的。

    ; GDT 选择子
    SelectorCode32      equ LABEL_DESC_CODE32   - LABEL_GDT
    

    2.3 往段描述符空间装干货地址

    干货就是真正的处理数据的代码。(如向屏幕显示打印字符)

    [SECTION .s16]
    [BITS   16]
    LABEL_BEGIN:
     ;start point: jmp会跳到这里
    mov ax,trong
    mov ax,GdtLen
    mov ax, cs
    mov ds, ax  
    mov es, ax
    mov ss, ax
    mov sp, 0100h
    
    ; 初始化 32 位代码段描述符(装干货地址)
    xor ax, ax
    mov ax, cs
    shl ax, 4
    add ax, LABEL_SEG_CODE32
    mov word [LABEL_DESC_CODE32 + 2], ax
    shr ax, 16
    mov byte [LABEL_DESC_CODE32 + 4], al
    mov byte [LABEL_DESC_CODE32 + 7], ah
    
    ; 为加载 GDTR 作准备(将全局描述符表GDT装入全局描述符表寄存器GDTR,目的是跳转的时候,程序要到GDTR取段基地址)
    xor ax, ax
    mov ax, ds
    shl ax, 4
    add ax, 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
    
    ; 真正进入保护模式 (这里就要查询GDTR了,跳转到干货地址)
    jmp dword SelectorCode32:0  ; 执行这一句会把 SelectorCode32 装入 cs,
                    ; 并跳转到 Code32Selector:0  处
    ; END of [SECTION .s16]
    

    2.4 真正的干货

    [SECTION .s32]; 32 位代码段. 由实模式跳入.
    [BITS   32]
    LABEL_SEG_CODE32:
    mov ax, SelectorData
    mov ds, ax          ; 数据段选择子
    mov ax, SelectorVideo
    mov gs, ax          ; 视频段选择子
    mov ax, SelectorStack
    mov ss, ax          ; 堆栈段选择子
    mov esp, TopOfStack
    。。。。。。
    

    【3】GDT + LDT (全局描述符表+局部描述符表) from p49.asm

    3.1 GDT的首地址(基地址)定义, 跟在它后面的都是其表项

    3.1.1 GDT定义

    [SECTION .gdt]
    ; GDT
    ;                                         段基址,       段界限     , 属性
    LABEL_GDT:         Descriptor       0,                 0, 0         ; 空描述符
    LABEL_DESC_NORMAL: Descriptor       0,            0ffffh, DA_DRW    ; Normal 描述符
    LABEL_DESC_CODE32: Descriptor       0,  SegCode32Len - 1, DA_C + DA_32  ; 非一致代码段, 32
    LABEL_DESC_CODE16: Descriptor       0,            0ffffh, DA_C      ; 非一致代码段, 16
    LABEL_DESC_DATA:   Descriptor       0,       DataLen - 1, DA_DRW+DA_DPL1    ; Data
    LABEL_DESC_STACK:  Descriptor       0,        TopOfStack, DA_DRWA + DA_32; Stack, 32 位
    LABEL_DESC_LDT:    Descriptor       0,        LDTLen - 1, DA_LDT    ; LDT (局部描述符表)
    LABEL_DESC_VIDEO:  Descriptor 0B8000h,            0ffffh, DA_DRW    ; 显存首地址
    ; GDT 结束
    

    3.1.2 LDT定义

    ; LDT
    [SECTION .ldt]
    ALIGN   32
    LABEL_LDT:
    ;                            段基址       段界限      属性
    LABEL_LDT_DESC_CODEA: Descriptor 0, CodeALen - 1, DA_C + DA_32 ; Code, 32 位
    LDTLen      equ $ - LABEL_LDT
    ; LDT 选择子
    SelectorLDTCodeA    equ LABEL_LDT_DESC_CODEA    - LABEL_LDT + SA_TIL
    ; END of [SECTION .ldt] 
    ; CodeA (LDT, 32 位代码段)
    

    3.2 初始化

       ; 初始化 LDT 在 GDT 中的描述符
    xor eax, eax
    mov ax, ds
    shl eax, 4
    add eax, LABEL_LDT
    mov word [LABEL_DESC_LDT + 2], ax
    shr eax, 16
    mov byte [LABEL_DESC_LDT + 4], al
    mov byte [LABEL_DESC_LDT + 7], ah
    ; 初始化 LDT 中的描述符
    xor eax, eax
    mov ax, ds
    shl eax, 4
    add eax, LABEL_CODE_A
    mov word [LABEL_LDT_DESC_CODEA + 2], ax
    shr eax, 16
    mov byte [LABEL_LDT_DESC_CODEA + 4], al
    mov byte [LABEL_LDT_DESC_CODEA + 7], 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 基地址
    

    版权声明:本文为博主原创文章,未经博主允许不得转载。

  • 相关阅读:
    ixgb 中断
    libvirt
    docker 查看虚拟机xml
    什么是可串行化MVCC
    算法题:实现 strStr()函数
    Python库 numpy基础内容学习笔记
    python3.6+torch1.2实现Sentiment Analysis(数据集MR)
    人工智能能力提升指导总结
    深度学习入门篇01(Tensorflow-gpu的安装)
    走进PEP8——代码规范
  • 原文地址:https://www.cnblogs.com/pacoson/p/4893177.html
Copyright © 2011-2022 走看看