哈工大李治军OS——L2,L3
哈工大李治军OS——L2,L3
哈工大李治军OS——L2,L3
哈工大李治军OS——L2,L3
固化:0xFFFF0是刚上电时唯一有代码的区域(寻指执行)
1个扇区512个字节,0磁道0扇区:OS的引导扇区

哈工大李治军OS——L2,L3

L2

哈工大李治军OS——L2,L3

汇编可以严格控制,不像C语言还要进行编译不受人控制。

计算机工作原理:取指执行,BIOS只会从0磁道0扇区读,若该处不为bootsect,则乱套

bootsect.s表示是汇编代码,用于编译bootsect

汇编文件之后会编译为机器指令,可以实现完整控制

地址:cs段地址+ip段内偏移地址,cs<<4+ip

cs ip都是16位寄存器

sub 相减

ds与si接成一个地址,左移四位,7c0——>7c00,es与di

rep movw:重复移动cx个字,256个字即512字节,ds为源地址,es目标地址,相当于将BIOS读进来的bootsect.s从7c00移到90000,腾出空间

哈工大李治军OS——L2,L3
jmp:直接跳转

???????jmpi:间接跳转,go赋给ip,INITSEG(9000)赋给cs,ip与cs合为一个地址,go是个标号(地址),(汇编完成后)go是指从代码起始处(start)开始经过了多少偏移,go指令在什么位置。比如go=300,cs+300=90300,bootsect.s挪到了90300处,

int 0x13 BIOS中断,cl开始扇区(从哪开始读,cx的第一拔位02,bootsect占了第一个扇区,所以从第二个扇区开始读),al所读扇区数量(ax的高八位作为ah,第八位为al)。es:bx表示内存地址,es(段基址)由ax给出,ax由cs给出,bx为200,即90200(200表示512个字节)

哈工大李治军OS——L2,L3
int 0x10 BIOS中断,在屏幕上(光标位置)显示字符(bp表示要显示的字符在内存中的地址,cx表示输出字符的长度),打出logo(Loading system。。。)后还要将剩余 模块读入:call read it(int 0x13中断)

哈工大李治军OS——L2,L3
bootsect所做工作:调用13号中断将setup.s读入内存,调用10号中断打出logo,然后又调用13号中断读入把OS后面的System读进来

bootsect工作完成就要将控制权交给下一个程序setup.s,如何交:跳转jmpi,修改pc,cs,ip。(ip置为0,cs置为SETUPSEG,cs<<4+ip,setup之前放在90200,则cs=9020)

L3

哈工大李治军OS——L2,L3
回顾:OS装在硬盘上,只有将代码放在内存才能取指执行,所以上电后第一步是将OS从磁盘载入到内存(由引导扇区完成bootsect.s)。

int 0x15BIOS中断:获得物理内存大小,#0x88作为参数,获取出的值放在ax,ax又赋给[2]([2]是间接寻址),默认寄存器指向9000,9000<<+2得90002,此处存了扩展内存大小。(为什么要做?对计算机进行信息采集以便管理,初始化,setup)

???????di,si减成0,要移动cx的长度,ax=0,ax赋给es,ds是9000,ds与si,es与di配合,将从90000开始的地方OS的所有代码移动到0地址处(es=0,段寄存器=0,左移四位=0,偏移=0)

setup挪动OS将其放在0地址处,之后不再改变,获取硬件参数为管理硬件做准备,后面的地址就放应用程序,然后setup执行jmpi 0,8切换到保护模式。之前bootsect挪一下就是为给这次挪动腾空间(OS太长)。

书:linux0.1

哈工大李治军OS——L2,L3
进入保护模式(32位寻址方式):jmpi 0,8

如果按照以前的0赋给ip,8赋给cs,cs<<4+ip的寻址模式(16位左移最多达到20位,只有1M,太小,现在要4G,32位机来实现),得到80,而应该跳转到的地方是0,因此寻址方式改变。

16位与32位的实质区别是cpu的解释程序不同。

cr0寄存器的最后一位如果是0则是16位模式,也叫实模式,如果是1则是保护模式。把1置给ax(ax最后一位是1),则cr0的最后一位是1,cpu就要走另一条解释执行指令的电路。

哈工大李治军OS——L2,L3
如何实现保护模式:依靠gdt(是硬件,执行快)

此时cs称为选择子,存的是表的下标(表项索引),这里的表就是gdt表(global describe table全局描述表),段的基址放在表项中,通过cs查到表项(通过硬件来查表),将表项中的基址取出与ip偏移相加。

哈工大李治军OS——L2,L3

哈工大李治军OS——L2,L3setup要初始化表(下三行,4个word,每个16位,共64位 0-8-bit),配合 lgdt gdt 48指令,就启动了32位模式(cs和ip都是32位的,所以可以访问4G空间,寻找pc地址)

setup.s功能:获取硬件参数为管理硬件做准备,挪动OS将其放在0地址处之后不再改变,后面的地址就放应用程序,启动保护模式,启用高级指令jmpi 0,8(32位的汇编指令)跳到0地址处。

同样的,中断处理函数也变了,由IDT表,int n(10,18…)就是去找表项,找到中断处理函数的入口地址。

然后跳到system模块。

顺序:BIOS读bootsect,bootsect读setup,bootsect读system,setup跳到后面部分而且要跳到第一部分。只有代码严格按这样排列才能顺利执行。

哈工大李治军OS——L2,L3
因此要编写OS的控制代码Makefile。

通常将OS通过Makefile编译出来的样子称为Image(OS镜像),将Image放在0磁道0扇区,然后就实现上述功能(打印字符,初始化…)Makefile是树状结构,即Image依赖于boot/bootsect boot/setup tools/system tools/build tools… (bootsect依赖于bootsect.s,setup依赖于setup.s)相似于树的结构(后根,父依赖于子),只有这些依赖的模块(如驱动程序DRIVERS,内存管理…)都有了之后通过链接指令将他们链接成一个模块。system的第一个部分是head.s(顾名思义)。有了head.s,有了system模块,有了setup,bootsect,用build将三者合为一,产生Image。

jmpi 0,8就是跳到head.s去执行。

哈工大李治军OS——L2,L3
head.s做了什么:初始idt,gdt(setup做gdt表只是为了执行jmpi指令,临时做的,而此处是正式做),开启20号地址线(访问4G内存)

由于改为32位,mov参数赋值顺序(前赋给后)与16位(后赋给前)相反,且改为%eax而非ax, 只能执行32位汇编代码。

哈工大李治军OS——L2,L3
内嵌汇编:在.c文件中有些指令要严格按照人的想法执行,就必须要用内嵌汇编。

哈工大李治军OS——L2,L3
当head.s执行完后要跳到mean.c去执行。(由汇编函数跳到c函数)c函数最终都要转为汇编语言才能执行。???????????函数调用靠栈

如C执行func(p1,p2,p3):相当于A{ C…B{D…}E…}。传递三个参数。首先将三个参数压栈,按顺序进栈(从后往前),然后将func后面语句的返回地址(E)压到最下面,然后jmp到func函数(B函数)去执行。func执行完后编译执行ret指令(作用:func执行完后就要跳回到C中func函数后面的语句去执行,即返回地址(E),已经放在栈里,就要从栈中弹出一个返回地址去执行)。

pushl:压栈

遇到ret,弹出来main,跳到main执行,0,0,0是main的参数(main的参数:envp,argc,argv),L6(返回地址)在main返回的时候返回,L6是jmp L6,死循环,所以main是一个永远不会返回的函数。

哈工大李治军OS——L2,L3
init:初始化

哈工大李治军OS——L2,L3
mem_init:内存初始化,即初始化一个数组mem_map。end_mem>>=12:往下减,右移12位,即除以2^{12},即每次减4K,这4K置为0,每4K作为一片,这就是页。用这样一个表格表示内存中哪些地方用了(!=0)哪些没用(=0)。表长由end_mem(表示内存大小)决定,而end_mem是作为参数传进来的,从哪传过来?(90002,通过setup读入内存的参数)

前面那些使用了的地方(100,100…)是放置OS。

总结
OS启动:1.将OS读入内存 2.初始化

为什么要读入:读入了才能进行取指执行,发挥功能

为什么要初始化:OS管理硬件,就要先了解它的数据结构。

相关文章:

  • 2022-12-23
  • 2021-07-25
  • 2022-12-23
  • 2021-10-12
  • 2021-04-22
  • 2021-04-12
  • 2021-06-08
  • 2021-07-15
猜你喜欢
  • 2021-10-30
  • 2021-06-06
  • 2021-09-05
  • 2022-12-23
  • 2021-10-19
  • 2021-11-05
  • 2021-08-24
相关资源
相似解决方案