【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; 打开地址线A20in  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 基地址

段描述符表(GDT+LDT)的有感相关推荐

  1. gdt描述_全局描述符表(GDT)局部描述符表(LDT)

    这三个表是在内存中由操作系统或系统程序员所建,并不是固化在哪里,所以从理论上是可以被读写的.这三个表都是描述符表.描述符表是由若干个描述符组成,每个描述符占用8个字节的内存空间,每个描述符表内最多可以 ...

  2. GDT,LDT,GDTR,LDTR 详解,包你理解透彻

    一.引入 保护模式下的段寄存器 由 16位的选择器 与 64位的段描述符寄存器 构成 段描述符寄存器: 存储段描述符 选择器:存储段描述符的索引 段寄存器 PS:原先实模式下的各个段寄存器作为保护模式 ...

  3. CPU实模式和保护模式、全局描述符表GDT、Linux内核中GDT和IDT的结构定义

    一 计算机实模式和保护模式 实模式 在实模式下,内存被限制为仅有1M字节(220 字节).有效的地址从00000到FFFFF (十六进制). 这些地址需要用20位的数来表示.一个20位的数不适合任何一 ...

  4. Windows保护模式学习笔记(一)—— 段寄存器GDT表

    Windows保护模式学习笔记(一)-- 段寄存器&GDT表 保护模式 参考书籍: 一.段寄存器 段寄存器的结构 段寄存器的读写 段寄存器的属性 1)探测Attribute: 2)探测Base ...

  5. x86保护模式——全局描述符表GDT详解

    1 - GDT作用 GDT全称Global Descriptor Table,是x86保护模式下的一个重要数据结构,在保护模式下,GDT在内存中有且只有一个.GDT的数据结构是一个描述符数组,每个描述 ...

  6. gdt描述_全局描述符表GDT

    写在前面 添油加醋系列第二弹--剖析GDT 话说C语言的话除了刷刷OJ外,就是用来实现操作系统这个大头了.C语言比C++少了很多很多臃肿的语法特性,写起来非常优美(至少写操作系统是这样的).虽说C++ ...

  7. linux内核gdt,第三天:Linux内核完全剖析之GDT+LDT+IDT

    GDTR: 保存全局描述符表的32位基址和16位表长度值 IDTR:中断描述符表的32位线性基址和16位表长度值 lDTR:由两部分组成, 当使用LLDT把含有LDT表段的选择符加载到LDTR时,LD ...

  8. GDT,LDT,GDTR,LDTR

    GDT,LDT,GDTR,LDTR 前言 全局描述符表GDT 局部描述符表LDT 中断描述符表IDT 段选择子 任务寄存器TR 实例 1:访问GDT 2:访问LDT 前言 所谓工作模式,是指CPU的寻 ...

  9. 段、GDT、调用门学习笔记

    保护模式 什么是保护模式 x86 CPU的3个模式:实模式.保护模式.虚拟8086模式. AMD64与Intel64 AMD在1999年的时候拓展了这套指令集,成为x86-64后改名叫AMD64,AM ...

最新文章

  1. 【STM32】硬件随机数程序示例
  2. loj #2305. 「NOI2017」游戏
  3. ExtJs学习笔记(21)-使用XTemplate结合WCF显示数据
  4. [RabbitMQ]MQ 的选择
  5. 现代软件工程 作业 文本文件中英语单词的频率
  6. 电压压力蕊片_陶瓷压力传感器工作原理、结构及分类
  7. 批量修改所选文件夹中所有文件的名称
  8. 远程桌面连接阿里云服务器
  9. 消消乐游戏原理(附部分代码)
  10. 立通信电杆——水泥杆
  11. 读书笔记 - 《门口的野蛮人》
  12. linux秘钥登录使用authorized_keys不生效
  13. 基于区域和基于边缘的图像分割
  14. cad相对坐标快捷键_cad角度快捷键(cad角度命令怎么输入)
  15. 从PDF直接复制粘贴过来可以吗?其他软件的数据怎么导入Excel?
  16. su 和 sudo su 的区别
  17. 用 Python 进行金融数据可视化
  18. 移植quectel的GPS模块
  19. 区块链应该打造国产操作系统
  20. View系列 (三) — Measure 流程详解

热门文章

  1. P4643-[国家集训队]阿狸和桃子的游戏【结论】
  2. P4345-[SHOI2015]超能粒子炮·改【Lucas定理,类欧】
  3. P5355-[Ynoi2017]由乃的玉米田【莫队,bitset,根号分治】
  4. 欢乐纪中某A组赛【2019.7.5】
  5. jzoj4671-World Tour【图论,bfs】
  6. codeforces1457 C. Bouncing Ball
  7. 使用Docker Swarm搭建分布式爬虫集群
  8. MySQL dayname()函数
  9. Spring Bean 定义继承
  10. Java制作VCARD