pmtest3源码解析:使用LDT
来源:互联网 发布:淘宝网老年棉拖鞋 编辑:程序博客网 时间:2024/06/14 15:44
摘要:在本节中,我们将添加一个LDT段,在段中打印一个字符L,从而学习如何利用程序的LDT段。程序的执行流程随之也会发生变化,我们将分析代码和分析代码结构。
我们来理一下程序的执行流程:
初始在实模式下,初始化GDT段描述符,做好进入保护模式的准备工作,经过一个长跳转,进入
保护模式32b代码段,加载相关段选择子,打印相关字符串信息,加载ldtr,进入局部任务codeA段
局部任务段codeA:打印字符,跳转到GDT中的code16段;
code16段:初始化相关寄存器,然后重新跳回实模式(通过jmp0)
1)一个段往往是为了完成特定的功能(存储数据或者执行代码):比如说,初始的实模式下的段,就是为了进入保护模式,那么就需要设置GDT、CR0、关中断、打开A20、跳转等。进入保护模式下32b的代码段之后,需要打印字符串信息和跳转到LDT中的段,所以需要设置相应的段寄存器....等等,只有从宏观上理解了程序的执行流程,才能写出代码。代码段是逻辑的主体,数据段主要完成数据结构的定义等。
2)另外,要注意的是,很多东西都是通过寄存器的设置来实现的:访问GDT之前要设置GDTR,同理有ss、ds、cs、sp、ldtr等。
一、概要分析:
在pmtest2的基础上,我们增加一个段LDT和一个LDT中的一个段codeA。需要注意的是,LDT存在的前提是GDT,因为LDT本身是一个段中,需要由GDT中的信息,得到基地址。另外,这个场景,给出了段选择子,我们如何去索引描述符呢?思考以后,我们知道,我们需要判断但选择子属于GDT还是LDT中的段——这个需要通过选择子的第二位来判断。我们来理一下程序的执行流程:
初始在实模式下,初始化GDT段描述符,做好进入保护模式的准备工作,经过一个长跳转,进入
保护模式32b代码段,加载相关段选择子,打印相关字符串信息,加载ldtr,进入局部任务codeA段
局部任务段codeA:打印字符,跳转到GDT中的code16段;
code16段:初始化相关寄存器,然后重新跳回实模式(通过jmp0)
二、代码解惑
注意,selector部分是不暂用GDT的存储空间的,所以计算GDT的时候,不包括selector部分。另外,汇编与一些高级语言相比,之所以在程序上难以理解,主要是因为它的结构化不是很强,也没有什么模块的概念,完全是计算的最底层,通过顺序,判断,跳转三条基本的指令来完成相应的功能。这就导致,程序之间的耦合性比较大,调用函数输入和输出不是很明显,所以会比较困难。另外,有很多处理器架构和汇编本身的语法问题,也给理解带来了额外的困难。为了理解代码,我们需要有如下的意识:1)一个段往往是为了完成特定的功能(存储数据或者执行代码):比如说,初始的实模式下的段,就是为了进入保护模式,那么就需要设置GDT、CR0、关中断、打开A20、跳转等。进入保护模式下32b的代码段之后,需要打印字符串信息和跳转到LDT中的段,所以需要设置相应的段寄存器....等等,只有从宏观上理解了程序的执行流程,才能写出代码。代码段是逻辑的主体,数据段主要完成数据结构的定义等。
2)另外,要注意的是,很多东西都是通过寄存器的设置来实现的:访问GDT之前要设置GDTR,同理有ss、ds、cs、sp、ldtr等。
- 代码如下:
- ; ==========================================
- ; pmtest3.asm
- ; 编译方法:nasm pmtest3.asm -o pmtest3.com
- ; ==========================================
- %include "pm.inc" ; 常量, 宏, 以及一些说明
- org 0100h
- jmp LABEL_BEGIN
- [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 ; 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 结束
- GdtLen equ $ - LABEL_GDT ; GDT长度
- GdtPtr dw GdtLen - 1 ; GDT界限
- dd 0 ; GDT基地址
- ; GDT 选择子
- SelectorNormal equ LABEL_DESC_NORMAL - LABEL_GDT
- SelectorCode32 equ LABEL_DESC_CODE32 - LABEL_GDT
- SelectorCode16 equ LABEL_DESC_CODE16 - LABEL_GDT
- SelectorData equ LABEL_DESC_DATA - LABEL_GDT
- SelectorStack equ LABEL_DESC_STACK - LABEL_GDT
- SelectorLDT equ LABEL_DESC_LDT - LABEL_GDT
- SelectorVideo equ LABEL_DESC_VIDEO - LABEL_GDT
- ; END of [SECTION .gdt]
- [SECTION .data1] ; 数据段
- ALIGN 32
- [BITS 32]
- LABEL_DATA:
- SPValueInRealMode dw 0
- ; 字符串
- PMMessage: db "In Protect Mode now. ^-^", 0 ; 进入保护模式后显示此字符串
- OffsetPMMessage equ PMMessage - $$
- StrTest: db "ABCDEFGHIJKLMNOPQRSTUVWXYZ", 0
- OffsetStrTest equ StrTest - $$
- DataLen equ $ - LABEL_DATA
- ; END of [SECTION .data1]
- ; 全局堆栈段
- [SECTION .gs]
- ALIGN 32
- [BITS 32]
- LABEL_STACK:
- times 512 db 0
- TopOfStack equ $ - LABEL_STACK - 1
- ; END of [SECTION .gs]
- [SECTION .s16]
- [BITS 16]
- LABEL_BEGIN:
- mov ax, cs
- mov ds, ax
- mov es, ax
- mov ss, ax
- mov sp, 0100h
- mov [LABEL_GO_BACK_TO_REAL+3], ax
- mov [SPValueInRealMode], sp
- ; 初始化 16 位代码段描述符
- mov ax, cs
- movzx eax, ax
- shl eax, 4
- add eax, LABEL_SEG_CODE16
- mov word [LABEL_DESC_CODE16 + 2], ax
- shr eax, 16
- mov byte [LABEL_DESC_CODE16 + 4], al
- mov byte [LABEL_DESC_CODE16 + 7], ah
- ; 初始化 32 位代码段描述符
- xor eax, eax
- mov ax, cs
- shl eax, 4
- add eax, LABEL_SEG_CODE32
- mov word [LABEL_DESC_CODE32 + 2], ax
- shr eax, 16
- mov byte [LABEL_DESC_CODE32 + 4], al
- mov byte [LABEL_DESC_CODE32 + 7], ah
- ; 初始化数据段描述符
- xor eax, eax
- mov ax, ds
- shl eax, 4
- add eax, LABEL_DATA
- mov word [LABEL_DESC_DATA + 2], ax
- shr eax, 16
- mov byte [LABEL_DESC_DATA + 4], al
- mov byte [LABEL_DESC_DATA + 7], ah
- ; 初始化堆栈段描述符
- xor eax, eax
- mov ax, ds
- shl eax, 4
- add eax, LABEL_STACK
- mov word [LABEL_DESC_STACK + 2], ax
- shr eax, 16
- mov byte [LABEL_DESC_STACK + 4], al
- mov byte [LABEL_DESC_STACK + 7], ah
- ; 初始化 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 基地址
- ; 加载 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 处
- ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
- LABEL_REAL_ENTRY: ; 从保护模式跳回到实模式就到了这里
- mov ax, cs
- mov ds, ax
- mov es, ax
- mov ss, ax
- mov sp, [SPValueInRealMode]
- in al, 92h ; ┓
- and al, 11111101b ; ┣ 关闭 A20 地址线
- out 92h, al ; ┛
- sti ; 开中断
- mov ax, 4c00h ; ┓
- int 21h ; ┛回到 DOS
- ; END of [SECTION .s16]
- [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
- ; 下面显示一个字符串
- mov ah, 0Ch ; 0000: 黑底 1100: 红字
- xor esi, esi
- xor edi, edi
- mov esi, OffsetPMMessage ; 源数据偏移
- mov edi, (80 * 10 + 0) * 2 ; 目的数据偏移。屏幕第 10 行, 第 0 列。
- cld
- .1:
- lodsb
- test al, al
- jz .2
- mov [gs:edi], ax
- add edi, 2
- jmp .1
- .2: ; 显示完毕
- call DispReturn
- ; Load LDT
- mov ax, SelectorLDT
- lldt ax
- jmp SelectorLDTCodeA:0 ; 跳入局部任务
- ; ------------------------------------------------------------------------
- DispReturn:
- push eax
- push ebx
- mov eax, edi
- mov bl, 160
- div bl
- and eax, 0FFh
- inc eax
- mov bl, 160
- mul bl
- mov edi, eax
- pop ebx
- pop eax
- ret
- ; DispReturn 结束---------------------------------------------------------
- SegCode32Len equ $ - LABEL_SEG_CODE32
- ; END of [SECTION .s32]
- ; 16 位代码段. 由 32 位代码段跳入, 跳出后到实模式
- [SECTION .s16code]
- ALIGN 32
- [BITS 16]
- LABEL_SEG_CODE16:
- ; 跳回实模式:
- mov ax, SelectorNormal
- mov ds, ax
- mov es, ax
- mov fs, ax
- mov gs, ax
- mov ss, ax
- mov eax, cr0
- and al, 11111110b
- mov cr0, eax
- LABEL_GO_BACK_TO_REAL:
- jmp 0:LABEL_REAL_ENTRY ; 段地址会在程序开始处被设置成正确的值
- Code16Len equ $ - LABEL_SEG_CODE16
- ; END of [SECTION .s16code]
- ; 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 位代码段)
- [SECTION .la]
- ALIGN 32
- [BITS 32]
- LABEL_CODE_A:
- mov ax, SelectorVideo
- mov gs, ax ; 视频段选择子(目的)
- mov edi, (80 * 12 + 0) * 2 ; 屏幕第 10 行, 第 0 列。
- mov ah, 0Ch ; 0000: 黑底 1100: 红字
- mov al, 'L'
- mov [gs:edi], ax
- ; 准备经由16位代码段跳回实模式
- jmp SelectorCode16:0
- CodeALen equ $ - LABEL_CODE_A
- ; END of [SECTION .la]
0 0
- pmtest3源码解析:使用LDT
- <自己动手写操作系统>第三章——pmtest3源码解析:使用LDT
- 文本比较pmtest3 4(ldt gate)
- 关于LDT的使用
- LDT
- LDT
- pmtest3.asm
- 代码实现LDT的使用
- 保护模式下ldt使用
- 保护模式下ldt使用
- HandlerThread使用&源码解析
- LuaSocket在Windows LDT环境中的使用
- GDT LDT 的使用 虚存管理
- AsyncTask使用及源码解析
- EventBus使用与源码解析
- SharedPreferences源码解析及使用
- AsyncTask使用与源码解析
- ImageLoader使用及源码解析
- EMSA简介及其使用方法
- 解释型语言和编译型语言的区别
- jquery 格式化日期显示
- android 7.0 多窗口及新特性demo
- Android中HttpURLConnection使用get方式向服务器提交json字符串
- pmtest3源码解析:使用LDT
- PHP匿点源码之变量赋值与引用
- 频宽、带宽和频带关系
- 分支管理
- 设置APP支持阿拉伯(RTL 从右向左)语言
- JTable 不能正确显示标题总结
- Transform的坐标变换注意事项
- api中的GET和POST的区别
- LeetCode1 Two Sum