首页 > 其他分享 >chapter11------进入保护模式

chapter11------进入保护模式

时间:2024-08-13 11:06:04浏览次数:10  
标签:保护模式 mov 地址 描述符 chapter11 寄存器 ------ bx

全局描述符表(GDT)

这里要先说明下,保护模式下对内存段的访问是有限制的,简单来说就是你不能再随意的访问了,只能访问授权给你的,然后段的访问限制等等信息就记载在一个叫做全局描述表里

段描述符

段描述符存储了某个段的具体信息,就像我们每个人的档案一样,记录着我们的信息

然后段描述符占用 8个字节,以下是段描述符的结构,上面是高32位,下面是低32位

段描述符结构

可以看到分割比较奇怪,这可能是因为要兼容16位保护模式的缘故吧

总之,一个段描述符就是由32位的段基址、20位的段界限和12位的属性组成的

段描述符结构具体解析

  • 段基地址 : 32位的段起始地址,可以是 0~4GB 的任意地址,不过还是建议选取16字节对齐的地址
  • 段界限 : 20位的段界限是用来限制段的扩展范围的,感觉就像是段的长度、访问边界。访问内存的方法就是用段基地址加上偏移量
    • 对于向上扩展的段(代码段或数据段),偏移量从0开始递增,段界限决定了偏移量的最大值
    • 对于向下扩展的段(栈段),段界限决定了偏移量的最小值
  • 属性
    • G位 :1位,粒度(Granularity)位,用于解释段界限的含义,其实就是控制单位的大小,段界限是20位,也就是说段的扩展范围是 1~1M 个单位大小

      • G=0,段界限以 字节 为单位,所以段的扩展范围是 1B~1MB
      • G=1,段界限以 4KB 为单位,所以段的扩展范围是 4KB~4GB
    • S位 :1位,用于指定描述符的类型

      • S=0,表示是一个 系统段
      • S=1,表示是一个 代码段或者数据段(栈段是特殊的数据段)
    • DPL :2位,表示描述符的特权级,这里描述符的特权级用于指定 要访问该段所不许具有的最低特权级别

      • 4种特权级别,分别是0、1、2、3,0最高,3最低
    • P位 :1位,段存在位(Segment Present),用于指示描述符所对应的段是否存在与内存中

    • D/B位 :1位,用于指示默认的操作数大小 或者 默认的栈指针大小,该标志位对于不同的段有不同的效果

      • D位 : 对于代码段而言是D位,用于指示 指令中默认的偏移地址和操作数尺寸
        • D=0,16位
        • D=1,32位
      • B位 :对于栈段而言是B位,用于在进行隐式的栈操作时(比如push、pop、call),是使用 SP 寄存器还是 ESP 寄存器
        • B=0,使用 SP,且栈段的上部边界(SP的最大值)位 0xFFFF
        • B=1,使用 ESP,且栈段的上部边界(ESP的最大值)位 0xFFFFFFFF
    • L位 :1位,64位代码段标志

    • TYPE字段 :4位,用于指示描述符的子类型或者类别

      • 对于数据段来说,这4位是X、E、W、A
        • X表示是否可执行,X=0不可执行,X=1可执行
        • E指示段的扩展方向,E=0向上扩展,E=1向下扩展
        • W表示段是否可写,W=0不可写,W=1可写
        • A是已访问位,用于指示段最近是否被访问过
      • 对于数据段来说,这4位是X、C、R、A
        • C指示段是否为特权级依从的,这个不太明白
        • R表示段是否可读,R=0不可读,R=1可读
        • 其他一样

      type

    • AVL位 :是软件可使用的位,不太明白

描述符表

简单来说就是 段描述符的集合

描述符表分为 全局描述符表(GDT)局部描述符表(LDT)

全局描述符表寄存器GDTR

gdtr

GDTR是一个48位的寄存器,分为两部分,32位的线性地址和16位的边界

线性地址保存的是全局描述符表在内存中的起始线性地址
边界保存的是全局描述符表的边界(界限),在数值上等于表的大小(总字节数)减1

GDT的界限是16位,则,表最大是2^16字节,每个描述符占用8个字节,所以最多定义8192个描述符

GDT可以位于内存中的任何地方,但它的安装是在实模式下进行的,所以通常定义在1MB以下,允许在进入保护模式后换个位置重新定义GDT

以下是GDTR和GDT的关系示意图
gdthegdtr

进入保护模式前的内存映像

mem

进入保护模式

安装存储器的段描述符

说人话,就是将我们定义的段的信息,也就是段描述符加载到内存中(分配给GDT的范围)

在进行下面的步骤前,还要设置下堆栈段

	; 设置堆栈段和栈指针
	mov ax, cs
	mov ss, ax
	mov sp, 0x7c00 							; 分界线,代码段向上增长,堆栈段向下增长
  • 将GDT的线性地址(物理地址)转换成逻辑地址和偏移地址
	; 计算GDT所在的逻辑段地址
	mov ax, [cs:gdt_base + 0x7c00] 			; 低16位
	mov dx, [cs:gdt_base + 0x7c00 + 0x02] 	        ; 高16位
	mov bx, 16
	div bx
	mov ds, ax 								; 令ds指向该段进行操作
	mov bx, dx 								; 段内起始偏移地址

简单来说就是将GDT的线性地址(32位)存进DX:AX,然后除以16,得到的商(AX)就是逻辑地址,余数(DX)就是偏移地址

  • 安装段描述符
	; 创建#0描述符,空描述符,这是处理器的要求
	mov dword [bx + 0x00], 0x00
	mov dword [bx + 0x04], 0x00

	; 创建#1描述符,保护模式下的代码段描述符
	mov dword [bx + 0x08], 0x7c0001ff
	mov dword [bx + 0x0c], 0x00409800

	; 创建#2描述符,保护模式下的数据段描述符(文本模式下的显示缓冲区)
	mov dword [bx + 0x10], 0x8000ffff
	mov dword [bx + 0x14], 0x0040920b

	; 创建#3描述符,保护模式下的堆栈段描述符
	mov dword [bx + 0x18], 0x00007a00
	mov dword [bx + 0x1c], 0x00408600

需要注意的是 处理器要求第一个描述符定义成空描述符,然后每个段描述符占用8个字节,写入的内容对照段描述符的结构图看吧

加载GDTR

  • 加载GDTR寄存器
	; 初始化描述符寄存器GDTR
	mov word [cs:gdt_size + 0x7c00], 31 	; 描述符表的界限(总字节数减1)

	lgdt [cs:gdt_size + 0x7c00]

打开A20地址线

	; 打开A20地址线
	in al, 0x92
	or al, 0000_0010B
	out 0x92, al

关中断

	; 关中断
	cli 	; 保护模式下中断机制尚未建立,应该禁止中断

设置cr0寄存器的PE位

	; 设置cr0寄存器的PE位
	mov eax, cr0
	or eax, 1
	mov cr0, eax 							; 设置PE位

CR0是32位的寄存器,包含了一系列用于控制处理器操作模式和运行状态的标志位。它的第一位是保护模式允许位---PE位,置1表示处理器进入保护模式

到这里就已经进入保护模式了

保护模式下的内存访问

保护模式下段寄存器存储的不在是简单的段地址了,而是稍微复杂的 段选择子

32位处理器的段寄存器

32
在32位下,传统的段寄存器存储的是段选择子,所以更应该叫 段选择器,然后配上一个 描述符高速缓存器 才是32位下的段寄存器

段选择子

selector
其实就是看从GDT中选择哪个段

  • 描述符索引:就是段描述符的索引号,第0个段、第1个段……
  • TI : 描述符表指示器,TI=0表示描述符在GDT中,TI=1表示描述符在LDT中
  • RPl :请求特权级

描述符加载到不可见的描述符高速缓存器中

首先知道描述符在表内的偏移地址是 索引号乘以8(每个段描述符占8个字节)
1

解析过程:

  1. 将段选择子加载到寄存器 DS 中
  2. 处理器将 DS 中的段选择子的索引部分乘以 8 然后加上寄存器 GDTR 中的 GDT的基地址,从而得到对应段描述符的起始地址
  3. 把得到的段描述符加载到描述符高速缓存器部分

保护模式下的内存访问

以下是一个简单的访问数据段的例子:
2

解析步骤:这个例子就是要访问 DS:0x00 这个地址(没有加段超越前缀默认是DS)

  1. [0x00] 给出偏移地址是 0x00,且没有段超越前缀,则默认是使用 DS 段寄存器
  2. 将 DS 寄存器中的描述符高速缓冲器提供的 段的基地址 加上偏移地址就得到了物理地址

访问其他段也是一样的,我们不用再访问GDT中的描述符,直接用段寄存器描述符高速缓存器提供的线性基地址加上偏移地址就能得到物理地址了

清空流水线并串行化处理器

  • 清空流水线就是将流水线中指令清空,因为这些指令是在实模式下编译执行的,是16位的,在32位保护模式下,由于对操作数和默认地址大小的解释不同,可能会出错,所以要清空流水线
  • 串行化处理器其实就是清理掉乱序执行得到的中间结果,然后重新按指令的自然顺序执行

说了挺多,我也没太明白这些是啥意思,总之,解决方案就是 使用远转移指令jmp或者元过程调用指令call,跳到保护模式下的代码段执行就好了

保护模式mbr的源代码

	; 设置堆栈段和栈指针
	mov ax, cs
	mov ss, ax
	mov sp, 0x7c00 					; 分界线,代码段向上增长,堆栈段向下增长

	; 清屏
	push ax

        mov ah,0x06
        mov al,0

        mov ch,0      ;(0,0)
        mov cl,0
        mov dh,24     ;(24,79)
        mov dl,79
        mov bh,0x07   ;黑底白字
        int 0x10

	pop ax

	; 计算GDT所在的逻辑段地址
	mov ax, [cs:gdt_base + 0x7c00] 			; 低16位
	mov dx, [cs:gdt_base + 0x7c00 + 0x02] 	        ; 高16位
	mov bx, 16
	div bx
	mov ds, ax 					; 令ds指向该段进行操作
	mov bx, dx 					; 段内起始偏移地址

	; 创建#0描述符,空描述符,这是处理器的要求
	mov dword [bx + 0x00], 0x00
	mov dword [bx + 0x04], 0x00

	; 创建#1描述符,保护模式下的代码段描述符
	mov dword [bx + 0x08], 0x7c0001ff
	mov dword [bx + 0x0c], 0x00409800

	; 创建#2描述符,保护模式下的数据段描述符(文本模式下的显示缓冲区)
	mov dword [bx + 0x10], 0x8000ffff
	mov dword [bx + 0x14], 0x0040920b

	; 创建#3描述符,保护模式下的堆栈段描述符
	mov dword [bx + 0x18], 0x00007a00
	mov dword [bx + 0x1c], 0x00408600

	; 初始化描述符寄存器GDTR
	mov word [cs:gdt_size + 0x7c00], 31 	        ; 描述符表的界限(总字节数减1)

	lgdt [cs:gdt_size + 0x7c00]

	; 进入保护模式的前置条件
	; 打开A20地址线
	in al, 0x92
	or al, 0000_0010B
	out 0x92, al

	; 关中断
	cli 						; 保护模式下中断机制尚未建立,应该禁止中断

	; 设置cr0寄存器的PE位
	mov eax, cr0
	or eax, 1
	mov cr0, eax 					; 设置PE位

	; 进入保护模式
	jmp dword 0x0008:flush 			        ; 16位的描述符选择子:32位偏移
							; 清流水线并串行化处理器

	[bits 32]

flush:
	mov cx, 00000000000_10_000B 			; 加载数据段选择子(0x10, 索引为2)
	mov ds, cx

	;以下在屏幕上显示"Protect mode OK."
	mov byte [0x00],'P'
	mov byte [0x02],'r'
	mov byte [0x04],'o'
	mov byte [0x06],'t'
	mov byte [0x08],'e'
	mov byte [0x0a],'c'
	mov byte [0x0c],'t'
	mov byte [0x0e],' '
	mov byte [0x10],'m'
	mov byte [0x12],'o'
	mov byte [0x14],'d'
	mov byte [0x16],'e'
	mov byte [0x18],' '
	mov byte [0x1a],'O'
	mov byte [0x1c],'K'

ghalt:
	hlt 						; 已禁止中断,将不会被唤醒

;---------------------------------------------------------------

	gdt_size 		 dw 0
	gdt_base 		 dd 0x00007e00 		; GDT的物理地址

	times 510-($-$$)         db 0
				 db 0x55, 0xaa 		; 结束标志

标签:保护模式,mov,地址,描述符,chapter11,寄存器,------,bx
From: https://www.cnblogs.com/winter-z/p/18355738

相关文章

  • Adobe Animate Createjs H5
    AdobeAnimateCC是AdobeFlash的继任者,提供了更现代的动画和互动功能。它允许用户创建动画,并导出到HTML5Canvas、WebGL或SVG格式。CreateJS是一个强大的JavaScript库,可以与AdobeAnimateCC一起使用,帮助开发人员在Web上实现动画和互动功能。对于没有Flash基础的......
  • TextIn文档树引擎,助力RAG知识库问答检索召回能力提升
    ​TextIn团队的文档解析测评工具MarkdownTester在Github发布后,我们陆续与大家探讨了目前业内对PDF解析工作的评判标准与我们各项测评指标的设计原理,包括段落、表格、公式、阅读顺序等维度。今天,我们将介绍另一项重要指标,也是业内面对的一项普遍性难点:标题识别,以及它如何......
  • “mouseover”和“mouseleave”的事件侦听器
    “mouseover”和“mouseleave”的事件侦听器“mouseover”和“mouseleave”是两个常用的事件侦听器,用于处理鼠标在网页上移入和移出元素的操作。“mouseover”事件:当鼠标指针移入一个元素时触发。可以通过添加“mouseover”事件侦听器来执行相应的操作,例如改变元素的样式、显示......
  • 易基因:儿童和成人实体瘤共有微小差异甲基化区域(mDMR)的全面分析 | 表观研究
    大家好,这里是专注表观组学十余年,领跑多组学科研服务的易基因。癌症是美国1~14岁儿童第二大常见死因,每年约有11000例新发病例和1200例死亡病例。与成人癌症相比,儿童肿瘤通常突变负荷较低。然而儿童肿瘤的表观基因组发生显著变化,尤其具有广泛的DNA甲基化变化。儿童肿瘤的罕见性对开......
  • vue2实现轮播图
    1.在components路径下新建文件Carousel.vue,在Carousel.vue文件中创建一个Vue组件实现轮播图的功能<button@click="prev"class="carousel-controlprev">‹<button@click="next"class="carousel-controlnext">›<spanv-for=&qu......
  • 【BUUCTF】Easy Java
    【BUUCTF】EasyJava题目来源收录于:BUUCTFRoarCTF2019题目描述经典登录框不过SQL注入、目录扫描都没有发现题解点击页面的help跳转到/Download路径下,但是并没有得到其他信息。这里我们改变请求方式为POST即可下载文件help.docx但是打开help.docx并没有得到有......
  • 基于Dango+微信小程序的广西东盟旅游资源信息管理系统+80003(免费领源码)可做计算机毕业
    django广西-东盟旅游资源信息管理系统小程序摘 要在社会快速发展和人们生活水平提高的影响下,旅游产业蓬勃发展,旅游形式也变得多样化,使旅游资源信息的管理变得比过去更加困难。依照这一现实为基础,设计一个快捷而又方便的基于小程序的旅游资源信息管理系统是一项十分重要并且......
  • c++ 字符串转 整形
    目前有两种string 转整形的方式std::atoi(constchar*);std::stoi(conststd::string);atoi()是c语言风格,而stoi()是c++11标准库中新增的函数两者的区别在atoi()的参数是constchar*,所以我们必须将字符串的类型从string转换为constchar类型才能够转换为int。str......
  • 单击关闭按钮关闭模型弹出来的详细信息窗口
    一、效果展示二、html内容:三、JS内容:1.0 model.js2.0 tag.js3.0 index.js备注:......
  • DzzOffice文件上传处理错误信息说明
    UPLOAD_ERR_OKValue:0;Thereisnoerror,thefileuploadedwithsuccess.其值为0,没有错误发生,文件上传成功。UPLOAD_ERR_INI_SIZEValue:1;Theuploadedfileexceedstheupload_max_filesizedirectiveinphp.ini.其值为1,上传的文件超过了php.ini中upload_max_fi......