标签:退出 改变 寻址方式 就会 oba 引导 system 数据 操作
bootsect.s(引导扇区程序)做了件什么事?
将硬盘中的OS程序(setup.s)读入内存
今天看一下setup.s后又做了什么事。
为什么一开始操作系统的程序要用汇编来编写?因为我们要严格地控制程序在哪里执行。汇编能做到,而C语言要需要编译才可以,在哪里执行我们是控制不了的。
为什么要做这件事情(扩展,获取内存的大小)呢?
为了以后要管理内存,必须先知道内存的大小。
还要获得其他参数:如光标位置,显卡参数等等。
获得之后就会形成一个数据结构的表。以便后面来管理。
之后就将操作系统的全部代码移动到0地址处,固定在内存中。以后应用程序就放在操作系统之上啦!(这样也解释的通为什么4G的内存发现可用的内存不够4GB,因为一部分内存被操作系统占用啦)
如果把这门课的全部代码(摘自Linux0.11源码分析)全部看懂,你就已经直到了操作系统的基本样子。有余力再去阅读《Linux0.11源码分析》。
这样后,setup.s就完成基本工作了。
setup.s做的最后一件事是:
jmpi 0,8这条指令在我们课程中发挥着非常至关重要的作用。能理解它,可以说对操作系统的认识有了一定的层次。
jmpi 0,8 的含义是:把0赋给IP,把8赋给CS。
这样就跳到00080处了。但如果真的跳到80处就会死机。这条指令实际跳到了0地址处。
因为此时访存能力只有20位,最大只有1MB,那么现在的计算机访存能力已经达到了4GB,那么如何改变访存方式呢?
要从16位机切换到32位机的样子。(1M->4GB).
32位模式也叫做保护模式。必须从实模式切换到保护模式下工作。
所以setup.s最后的事情就是切换到保护模式下
16位模式和32位模式的本质区别是什么?CPU的解释程序不一样。
之前是CS;IP ,CS左移4位后加上IP。但是现在不能这样解释了。
要切换到另一条电路来执行。
cr0寄存器如果是0,就是为实模式,为1就是保护模式。
这两条指令执行完毕后,CPU就走另外一条电路了。
这条解释执行的电路要怎样解释执行呢?
CS这时变成了选择子(selector)
这时查找指令的地址的方式就变成了:CS的作用为选择表中的一个项,在这个项中取出基地址,再和IP偏移地址加在一起产生32位地址。
如果要想32位的寻址方式好使,那么就需要著名的gdt(global discription table)表
setup.s初始化gdt的部分:
切换到32位寻址方式后,CS和IP都变成了32位的寄存器。
此时中断函数也要去gdt表项里去查找。
其实是跳到了0地址去执行。
编写操作系统,除了编写操作系统的源代码以外,还要编写操作系统的控制代码,比如system是由一大堆子文件集合起来的,那么就需要你控制谁先执行。
这就是著名的makefile
学完了这个课程后,makefile必须会用!
像编辑器,直接用快捷键就能把源代码文件编译好,是因为内部帮你实现了makefile。
system是由许多子文件像bootsect,setup,head,init等组合而成,最后生成一个镜像文件Image。
最后LD,链接,生成了tools/system。
第一个模块是bootsect,接着是setup,接着是head,接着是main
head.s做了些什么事情?
又一次初始化了idt表和gdt表
刚才为啥要初始化gdt表?只是为了跳到jmpi 08这个地方去。所以临时建立gdt表。
这一次建立的表,是使操作系统真正开始工作。
还有一个要注意的是:现在的汇编代码和之前的不一样了。变成了32位的汇编代码。
操作系统特别复杂,使用了3种汇编语言:16位汇编,32位汇编,和内嵌汇编。
head.s(汇编)会跳转到main函数部分,main是一段C函数。
可以看到这是压栈操作,下图配和理解,压完main函数后,返回L6,L6将继续执行L6,这时就会死机。所以操作系统是永远不会死机的。
进入了main函数:
可以看出,main函数用于不会退出(因为没有返回L6的语句)。
可以看到,这里的函数大部分作用都是初始化。
这里只说一个,明白了它,其他的作用大概也就明白了
内存的初始化。
每4K进行一次初始化,初始化为0。4K称为一页,我们在内存管理的时候再详细说明。
end_mem就是你的机器的内存大小,这个参数是之前setup.s程序读取内存的时候获取的。
到此,系统启动基本完成。其实上就是干了两件事:1.把操作系统读入内存 2.初始化
标签:退出 改变 寻址方式 就会 oba 引导 system 数据 操作
原文地址:https://www.cnblogs.com/JasonPeng1/p/12110141.html