《ucore lab1 exercise3》实验报告
资源
题目:分析bootloader进入保护模式的过程
BIOS将通过读取硬盘主引导扇区到内存,并转跳到对应内存中的位置执行bootloader。请分析bootloader是如何完成从实模式进入保护模式的。
提示:需要阅读小节“保护模式和分段机制”和lab1/boot/bootasm.S源码,了解如何从实模式
切换到保护模式,需要了解:
- 为何开启A20,以及如何开启A20
- 如何初始化GDT表
- 如何使能和进入保护模式
解答
正如提示所言,bootloader从实模式切换到保护模式,需要做以下事情:
- 开启A20门
- 在内存中建立GDT表并初始化
- 设置cr0寄存器的PE位为1,表示从实模式切换到保护模式
下面针对每一项具体展开描述。
开启A20门
为何开启A20门?
一开始时A20地址线控制是被屏蔽的(总为0) ,直到系统软件通过一定的IO操作去打开它(参看bootasm.S) 。很显然,在实模式下要访问高端内存区,这个开关必须打开,在保护模式下,由于使用32位地址线,如果A20恒等于0,那么系统只能访问奇数兆的内存,即只能访问0--1M、2-3M、4-5M......,这样无法有效访问所有可用内存。所以在保护模式下,这个开关也必须打开。
如何开启A20?
打开A20 Gate的具体步骤大致如下:
- 等待8042 Input buffer为空
- 发送Write 8042 Output Port (P2) 命令到8042 Input buffer
- 等待8042 Input buffer为空
- 将8042 Output Port(P2) 对应字节的第2位置1,然后写入8042 Input buffer
打开A20 Gate的功能是在boot/bootasm.S中实现的,下面结合相关代码来分析:代码分为seta20.1和seta20.2两部分,其中seta20.1是往端口0x64写数据0xd1,告诉CPU我要往8042芯片的P2端口写数据;seta20.2是往端口0x60写数据0xdf,从而将8042芯片的P2端口设置为1. 两段代码都需要先读0x64端口的第2位,确保输入缓冲区为空后再进行后续写操作。
seta20.1:
inb $0x64, %al # Wait for not busy(8042 input buffer empty).
testb $0x2, %al
jnz seta20.1
movb $0xd1, %al # 0xd1 -> port 0x64
outb %al, $0x64 # 0xd1 means: write data to 8042's P2 port
seta20.2:
inb $0x64, %al # Wait for not busy(8042 input buffer empty).
testb $0x2, %al
jnz seta20.2
movb $0xdf, %al # 0xdf -> port 0x60
outb %al, $0x60 # 0xdf = 11011111, means set P2's A20 bit(the 1 bit) to 1
初始化GDT表
- boot/bootasm.S中的
lgdt gdtdesc把全局描述符表的大小和起始地址共8个字节加载到全局描述符表寄存器GDTR中。从代码中可以看到全局描述符表的大小为0x17 + 1 = 0x18,也就是24字节。由于全局描述符表每项大小为8字节,因此一共有3项,而第一项是空白项,所以全局描述符表中只有两个有效的段描述符,分别对应代码段和数据段。
gdtdesc:
.word 0x17 # sizeof(gdt) - 1
.long gdt # address gdt
- 下面的代码给出了全局描述符表的具体内容。共有3项,每项8字节。第1项是空白项,内容为全0. 后面2项分别是代码段和数据段的描述符,它们的base都设置为0,limit都设置为0xffffff,也就是长度均为4G. 代码段设置了可读和可执行权限,数据段设置了可写权限。(疑问:为什么数据段不设置可读权限?)
// Bootstrap GDT
.p2align 2 # force 4 byte alignment
gdt:
SEG_NULLASM # null seg
SEG_ASM(STA_X|STA_R, 0x0, 0xffffffff) # code seg for bootloader and kernel
SEG_ASM(STA_W, 0x0, 0xffffffff) # data seg for bootloader and kernel
- SEG_ASM的定义如下
#define SEG_ASM(type,base,lim) \
.word (((lim) >> 12) & 0xffff), ((base) & 0xffff); \
.byte (((base) >> 16) & 0xff), (0x90 | (type)), \
(0xC0 | (((lim) >> 28) & 0xf)), (((base) >> 24) & 0xff)
如何使能和进入保护模式
将cr0寄存器的PE位(cr0寄存器的最低位)设置为1,便使能和进入保护模式了。代码如下所示:
movl %cr0, %eax
orl $CR0_PE_ON, %eax
movl %eax, %cr0
《ucore lab1 exercise3》实验报告的更多相关文章
- [操作系统实验lab3]实验报告
[感受] 这次操作系统实验感觉还是比较难的,除了因为助教老师笔误引发的2个错误外,还有一些关键性的理解的地方感觉还没有很到位,这些天一直在不断地消化.理解Lab3里的内容,到现在感觉比Lab2里面所蕴 ...
- Ucore lab1实验报告
练习一 Makefile 1.1 OS镜像文件ucore.img 是如何一步步生成的? + cc kern/init/init.c + cc kern/libs/readline.c + cc ker ...
- ucore操作系统学习(三) ucore lab3虚拟内存管理分析
1. ucore lab3介绍 虚拟内存介绍 在目前的硬件体系结构中,程序要想在计算机中运行,必须先加载至物理主存中.在支持多道程序运行的系统上,我们想要让包括操作系统内核在内的各种程序能并发的执行, ...
- 《ucore lab3》实验报告
资源 ucore在线实验指导书 我的ucore实验代码 练习1:给未被映射的地址映射上物理页 题目 完成do_pgfault(mm/vmm.c)函数,给未被映射的地址映射上物理页.设置访问权限的时候需 ...
- 《ucore lab1 exercise5》实验报告
资源 ucore在线实验指导书 我的ucore实验代码 题目:实现函数调用堆栈跟踪函数 我们需要在lab1中完成kdebug.c中函数print_stackframe的实现,可以通过函数print_s ...
- 《ucore lab8》实验报告
资源 ucore在线实验指导书 我的ucore实验代码 练习1: 完成读文件操作的实现(需要编码) 题目 首先了解打开文件的处理流程,然后参考本实验后续的文件读写操作的过程分析,编写在sfs_inod ...
- 《ucore lab7》实验报告
资源 ucore在线实验指导书 我的ucore实验代码 练习1: 理解内核级信号量的实现和基于内核级信号量的哲学家就餐问题(不需要编码) 题目 完成练习0后,建议大家比较一下(可用meld等文件dif ...
- 《ucore lab6》实验报告
资源 ucore在线实验指导书 我的ucore实验代码 练习1: 使用 Round Robin 调度算法(不需要编码) 题目 完成练习0后,建议大家比较一下(可用kdiff3等文件比较软件) 个人完成 ...
- 《ucore lab5》实验报告
资源 ucore在线实验指导书 我的ucore实验代码 练习1: 加载应用程序并执行(需要编码) 题目 do_execv函数调用load_icode(位于kern/process/proc.c中) 来 ...
- 《ucore lab4》实验报告
资源 ucore在线实验指导书 我的ucore实验代码 练习1:分配并初始化一个进程控制块 题目 alloc_proc函数(位于kern/process/proc.c中) 负责分配并返回一个新的str ...
随机推荐
- 第12章、乐活人生的ABCDE
目录 第12章.乐活人生的ABCDE 什么时候该乐观 让自己乐观的ABC 确认ABC 你的ABC记录 反驳和转移注意 转移注意 反驳 保持距离 学习与自己争辩 证据 其他可能性 暗示 用处 你的反驳记 ...
- 特征工程学习01-sklearn单机特征工程
特征工程学习01-sklearn单机特征工程 小书匠 kindle 0.数据的导入 from sklearn.datasets import load_iris #导入IRIS数据集 iris= ...
- spark常见错误【持续更新】
错误1.错误: 找不到或无法加载主类 idea.scala代码 idea 导入的scala工程,编写代码后报该错误. 原因:\src\main\scala 包路径下没有将scala这个包设置成Sour ...
- luogu P4168 蒲公英+ 分块学习笔记
传送门 题目描述 在乡下的小路旁种着许多蒲公英,而我们的问题正是与这些蒲公英有关. 为了简化起见,我们把所有的蒲公英看成一个长度为n的序列\((a_1,a_2..a_n)\),其中 \(a_i\)为一 ...
- linux下安装apache和php和mysql
我的系统环境时ubuntu 18.04.3,为了ROS: 首先:安装下面一堆软件包: sudo apt install nginx nginx-doc fcgiwrap sudo apt instal ...
- Java生成不重复的随机数组的方法
一.JAVA中生成随机数的方式 1.在j2se中使用Math.random()令系统随机选取一个01之间的double类型小数,将其乘以一个数,比如25,就能得到一个025范围内的随机数,这个在j2m ...
- jquery 性能优化高级技巧
有时为了书写方便,忽视了程序执行中给客户端带来的压力.导致在低端浏览器的运行缓慢. 1>通过CDN引用jquery,能减少网站加载时间.http://apps.bdimg.com/libs/jq ...
- openstack 基镜像展开过程
- 【k8s部署kong一】kong k8s 安装 以及可视化管理界面
官方安装:https://getkong.org/install/kubernetes/ 扩展讲解:https://blog.fleeto.us/post/intro-kong/ 提示:本文是在k8s ...
- VSCode 设置 Tab 空格
Windows 点击左下角的 Setting 按钮 输入 tabSize 进行查找