ucore是清华大学操作系统课程的实验内核,也是一个开源项目,是不可多得的非常好的操作系统学习资源

https://github.com/chyyuu/ucore_lab.git, 各位同学可以使用git下载源码和文档。

本文我会对项目中的code/lab1/boot/bootasm.S文件进行完全注释。

 #include <asm.h>
asm.h头文件中包含了一些宏定义,用于定义gdt,gdt是保护模式使用的全局段描述符表,其中存储着段描述符。 # Start the CPU: switch to -bit protected mode, jump into C.
# The BIOS loads this code from the first sector of the hard disk into
# memory at physical address 0x7c00 and starts executing in real mode
# with %cs= %ip=7c00.
此段注释说明了要完成的目的:启动保护模式,转入C函数。
这里正好说了一下bootasm.S文件的作用。计算机加电后,由BIOS将bootasm.S生成的可执行代码从硬盘的第一个扇区复制到内存中的物理地址0x7c00处,并开始执行。
此时系统处于实模式。可用内存不多于1M。 .set PROT_MODE_CSEG, 0x8 # kernel code segment selector
.set PROT_MODE_DSEG, 0x10 # kernel data segment selector
这两个段选择子的作用其实是提供了gdt中代码段和数据段的索引,具体怎么用的下面用到的时候我们详细解释
.set CR0_PE_ON, 0x1 # protected mode enable flag
这个变量也在下面用到的时候解释 # start address should be :7c00, in real mode, the beginning address of the running bootloader
.globl start
start:
这两行代码相当于定义了C语言中的main函数,start就相当于main,BIOS调用程序时,从这里开始执行 .code16 # Assemble for -bit mode
因为以下代码是在实模式下执行,所以要告诉编译器使用16位模式编译。 cli # Disable interrupts
cld # String operations increment
关中断,设置字符串操作是递增方向。cld的作用是将direct flag标志位清零,it means that instructions that autoincrement the source index and destination index (like MOVS) will increase both of them。 # Set up the important data segment registers (DS, ES, SS).
xorw %ax, %ax # Segment number zero
ax寄存器就是eax寄存器的低十六位,使用xorw清零ax,效果相当于movw $0, %ax。 但是好像xorw性能好一些,google了一下没有得到好答案 movw %ax, %ds # -> Data Segment
movw %ax, %es # -> Extra Segment
movw %ax, %ss # -> Stack Segment
24
将段选择子清零

# Enable A20:
# For backwards compatibility with the earliest PCs, physical
# address line is tied low, so that addresses higher than
# 1MB wrap around to zero by default. This code undoes this.
准备工作就绪,下面开始动真格的了,激活A20地址位。先翻译注释:由于需要兼容早期pc,物理地址的第20位绑定为0,所以高于1MB的地址又回到了0x00000.
好了,激活A20后,就可以访问所有4G内存了,就可以使用保护模式了。 怎么激活呢,由于历史原因A20地址位由键盘控制器芯片8042管理。所以要给8042发命令激活A20
8042有两个IO端口:0x60和0x64, 激活流程位: 发送0xd1命令到0x64端口 --> 发送0xdf到0x60,done! seta20.:
inb $0x64, %al # Wait for not busy( input buffer empty).
testb $0x2, %al
jnz seta20.1
发送命令之前,要等待键盘输入缓冲区为空,这通过8042的状态寄存器的第2bit来观察,而状态寄存器的值可以读0x64端口得到。
上面的指令的意思就是,如果状态寄存器的第2位为1,就跳到seta20.1符号处执行,知道第2位为0,代表缓冲区为空 movb $0xd1, %al # 0xd1 -> port 0x64
outb %al, $0x64 # 0xd1 means: write data to 's P2 port
发送0xd1到0x64端口 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 bit) to

到此,A20激活完成。
# Switch from real to protected mode, using a bootstrap GDT
# and segment translation that makes virtual addresses
# identical to physical addresses, so that the
# effective memory map does not change during the switch.
转入保护模式,这里需要指定一个临时的GDT,来翻译逻辑地址。这里使用的GDT通过gdtdesc段定义,它翻译得到的物理地址和虚拟地址相同,所以转换过程中内存映射不会改变 lgdt gdtdesc
载入gdt
movl %cr0, %eax
orl $CR0_PE_ON, %eax
movl %eax, %cr0
打开保护模式标志位,相当于按下了保护模式的开关。cr0寄存器的第0位就是这个开关,通过CR0_PE_ON或cr0寄存器,将第0位置1 # Jump to next instruction, but in -bit code segment.
# Switches processor into -bit mode.
ljmp $PROT_MODE_CSEG, $protcseg
57
由于上面的代码已经打开了保护模式了,所以这里要使用逻辑地址,而不是之前实模式的地址了。
这里用到了PROT_MODE_CSEG, 他的值是0x8。根据段选择子的格式定义,0x8就翻译成:
        INDEX         TI CPL
     0000 0000 0000 1 00 0
INDEX代表GDT中的索引,TI代表使用GDTR中的GDT, CPL代表处于特权级。
PROT_MODE_CSEG选择子选择了GDT中的第1个段描述符。这里使用的gdt就是变量gdt,下面可以看到gdt的第1个段描述符的基地址是0x0000,所以经过映射后和转换前的内存映射的物理地址一样。
 
.code32 # Assemble for -bit mode
protcseg:
# Set up the protected-mode data segment registers
movw $PROT_MODE_DSEG, %ax # Our data segment selector
movw %ax, %ds # -> DS: Data Segment
movw %ax, %es # -> ES: Extra Segment
movw %ax, %fs # -> FS
movw %ax, %gs # -> GS
movw %ax, %ss # -> SS: Stack Segment

重新初始化各个段寄存器。
# Set up the stack pointer and call into C. The stack region is from --start(0x7c00)
movl $0x0, %ebp
movl $start, %esp
call bootmain
栈顶设定在start处,也就是地址0x7c00处,call函数将返回地址入栈,将控制权交给bootmain # If bootmain returns (it shouldn't), loop.
spin:
jmp spin # 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 gdtdesc:
.word 0x17 # sizeof(gdt) - 1
.long gdt # address gdt

清华大学教学内核ucore学习系列(1) bootloader的更多相关文章

  1. Android学习系列(38)--Android源码下载和编译

    前面多篇文章介绍到如何下载和编译Android或者CM源码,不过一直都是放在<拓展系列>里.随着学习的深入,android源码是非常有参考和学习价值,强烈推荐大家都去下载,编译,学习,所以 ...

  2. 【深度学习系列2】Mariana DNN多GPU数据并行框架

    [深度学习系列2]Mariana DNN多GPU数据并行框架  本文是腾讯深度学习系列文章的第二篇,聚焦于腾讯深度学习平台Mariana中深度神经网络DNN的多GPU数据并行框架.   深度神经网络( ...

  3. Git学习系列之Windows上安装Git详细步骤(图文详解)

    前言 最初,Git是用于Linux下的内核代码管理.因为其非常好用,目前,已经被成功移植到Mac和Windows操作系统下. 鉴于大部分使用者使用的是Windows操作系统,故,这里详细讲解Windo ...

  4. 02LaTeX学习系列之---TeX环境的搭建

    目录 02Latex的下载与安装及其编译IDE 目录 前言 (一)Tex Live的下载 1. Tex Live官方下载网站: (二)TeXStudio 1.TeXStudio官网下载 2.TeXSt ...

  5. Redis总结(五)缓存雪崩和缓存穿透等问题 Web API系列(三)统一异常处理 C#总结(一)AutoResetEvent的使用介绍(用AutoResetEvent实现同步) C#总结(二)事件Event 介绍总结 C#总结(三)DataGridView增加全选列 Web API系列(二)接口安全和参数校验 RabbitMQ学习系列(六): RabbitMQ 高可用集群

    Redis总结(五)缓存雪崩和缓存穿透等问题   前面讲过一些redis 缓存的使用和数据持久化.感兴趣的朋友可以看看之前的文章,http://www.cnblogs.com/zhangweizhon ...

  6. Docker学习系列(一):windows下安装docker(转载)

    本文目录如下: windows按照docker的基本要求 具体安装步骤 开始使用 安装远程连接工具连接docker 安装中遇到的问题 Docker的更新 Docker中的jupyter windows ...

  7. 图机器学习(GML)&图神经网络(GNN)原理和代码实现(前置学习系列二)

    项目链接:https://aistudio.baidu.com/aistudio/projectdetail/4990947?contributionType=1 欢迎fork欢迎三连!文章篇幅有限, ...

  8. 分布式学习系列【dubbo入门实践】

    分布式学习系列[dubbo入门实践] dubbo架构 组成部分:provider,consumer,registry,monitor: provider,consumer注册,订阅类似于消息队列的注册 ...

  9. Entity Framework Code First学习系列目录

    Entity Framework Code First学习系列说明:开发环境为Visual Studio 2010 + Entity Framework 5.0+MS SQL Server 2012, ...

随机推荐

  1. 品Spring:对@Autowired和@Value注解的处理方法

    在Spring中能够完成依赖注入的注解有JavaSE提供的@Resource注解,就是上一篇文章介绍的. 还有JavaEE提供的@javax.inject.Inject注解,这个用的很少,因为一般都不 ...

  2. ELK 学习笔记之 elasticsearch Bulk操作

    Bulk操作: Bulk操作用于批量插入数据: 请求体格式: 编辑一个文件:(插入2个新的文档) curl -XPOST 'http://192.168.1.151:9200/library/book ...

  3. maven web项目下mybatis generator的使用

    idea中新建maven web项目,完善java,resources目录: pom.xml中添加jdbc依赖,mybatis generator的依赖和插件: <dependencies> ...

  4. Airport Express UVA - 11374

    In a small city called Iokh, a train service, Airport-Express, takes residents to the airport more q ...

  5. 本人亲测-SSM整合后的基础包(供新手学习使用,可在本基础上进行二次开发)

    本案例是在eclipse上进行开发的,解压后直接添加到eclipse即可.还需要自己配置maven环境.链接:https://pan.baidu.com/s/1siuvhCJASuZG_jqY5utP ...

  6. 本人亲测-百度富文本编辑器(无bug版本)

    再此我想说明一点,好多教程都是转载别人的,而且也不注明从哪里转载的.每次搜点资料的时候总是跟网上刷小视频的感觉一样.有些人就直接把别人的东西粘贴过来了,一点改动都没有. 废话不多说,直接上教程. (百 ...

  7. MySQL基础(四)常用函数

    转载自 http://blog.csdn.net/evankaka MySQL数据库中提供了很丰富的函数.MySQL函数包括数学函数.字符串函数.日期和时间函数.条件判断函数.系统信息函数.加密函数. ...

  8. 蓝牙TWS耳机IBRT的原理初分析

    最近在倒腾TWS对耳的一些东西,看到一些源码,发现一个新概念,IBRT没有搞清楚,抱着吾将上下而求索的态度,详细看了一些代码,查了一些资料,还是发现了不少有价值的信息的.至少,我突然感觉自己懂了一些什 ...

  9. springboot依赖的一些配置:spring-boot-dependencies、spring-boot-starter-parent、io.spring.platform

    springboot里会引入很多springboot starter依赖,这些依赖的版本号统一管理,springboot有几种方案可以选择. 一.spring-boot-dependencies 有两 ...

  10. “零基础”如何快速掌握web前端核心技术?

    前端开发要学的知识内容涉及的会很宽泛,虽然说主要是HTML.CSS和JavaScript这些基础知识点,今天想强调一下,学前端开发除了要学这些基础知识外,学员还要在这之上进行延伸和深入的去学,而且互联 ...