linux0.11启动 setup.s head.s

目录

setup.s

获取硬件信息

移代码

进入保护模式

为什么20位寻址可以存储1MB个存储单元地址?

保护模式也就是32位模式

保护模式下的地址翻译

system

head.s

三种汇编

c和汇编的函数调用

 设置页表后执行main函数

main.c

mem_init


setup.s

参考https://blog.csdn.net/yuanfen5200/article/details/88254564

bootsect.s执行后,开始执行setup.s。   setup.s有三个作用

获取硬件信息

操作系统要获取内存、显卡、光标等硬件信息,然后用对应数据结构去管理硬件,这就是setup的作用。

int 0x15 中断对应的程序作用:读取扩展内存大小(x86默认内存只有1M,剩下的4G 8G都是扩展内存),把内存大小放到[2] ,即ds:[2],实际上是 0x9000:[2],(在bootsect.s中已经知道ds的值是0x9000)。

移代码

do_move,ds:si  es:di  rep movsw 又开始配合,把在内存ds:si  0x9000的代码 移到了 0x0000。

之前在bootsect中曾把0x7000代码移到0x9000,移动的作用:课程意思之前的移动 就是为了 现在移到0x0000,可能是内容太长,如果之前不移动到0x9000,会覆盖0x7000的程序。

进入保护模式

为什么20位寻址可以存储1MB个存储单元地址?

内存即存储器的存储单元 一个单元能放8bit数据。

其实,20位二进制寻址1M存储空间,实际可以看做20根地址线接入存储器,那么每根线出现的数不是0就是1也就是二进制。
比如A0号线到A19依次出现的是:00000000000000000001 ,那么这20根地址线经翻译到存储器就是要找1#的存储器地址存储的内容,在1#存储器存的就是一个8位的字节。

这样8*2^20就是1M ,即20位地址总线能处理1M的数据

保护模式也就是32位模式

原先的CS IP寻址方式,只能寻20位地址,即1M数据,太少了。要转为32位模式。

setup调用的最后程序,改变了保护模式。

cr0 寄存器,如果最后一位PE是1就是启动保护模式,0就是16位模式。

mov cr0 ,ax  ,ax本身是0x0001, 这样让cr0最低位变为1.

jmpi 0,8 就开始了解释执行电路,不再是之前的寻址方式。

setup.s的最后代码就是(mov cr0 ,ax  jmpi 0,8 )

保护模式下的地址翻译

保护模式cs ip不再是cs左移cs4位+ip(实模式)。

cs值为gdt表中的选择子。从表中拿到值再+ip。如上图。

 勾选的代码会创建初始化gdt表。表的结果如下

从右往左,从下往上。第一层的段基址是15到0, 第一层第一项是7到0(值为07FF),第二项是15到8(0000)。

所以jmpi 0,8  cs=8 会去找第一层第二项 0x0000+ip =0x0000,前面把system的代码放到了0x0000,所以就开始执行system,setup的三个工作就完成了。

system

 通过makefile可以生成镜像image。 image依赖于bootsect setup system build,通过命令 

就能生成镜像,再把这个镜像存放到0磁道0扇区处,就可以启动了,把前面学的过程开始执行一直导启动操作系统。

而tools/system又依赖于head.o  main.o 等等,通过命令

就能生成 tool/system,所以要看system要从head看起。

head.s

​​​​​​​ 

首先 call setup_idt gdt,初始化gdt idt 表,之前setup初始化过一次gdt,是为了在保护模式下跳转到system执行,但之前的表已经使用完毕,system要用就重新初始化。

三种汇编

head.s汇编写法不一样了。

bootsect用的是16位汇编,进入保护模式用32位汇编,写C时,可能要控制具体内存,就得用内嵌汇编,三种语法有区别,用到了再去看

c和汇编的函数调用

c语言在a函数中调用b函数,这么写 a(){  b(); }.

但原理是要调用的b函数 的参数分别压栈、返回地址(返回到a的某处)压栈

 设置页表后执行main函数

head.s 有一段执行 after_page_tables,

push压栈,前面三个0是参数,L6是返回地址,压栈后执行 设置页表方法,设置完 ret就会执行main函数,再看L6 处的代码是jmp L6 又跳到L6,是个无限循环,即正常情况main函数不应该返回,应该一直执行。

main.c

 

main里是各初始化函数,内存初始化、中断、键盘初始化等

mem_init

 mem_map是个数组,元素为0就是没有被使用过。 初始化就是把除操作系统占用的内存都标记为0.

右移12跟页存储有关,还不太清楚。

总结,bootsect把操作系统从磁盘读到内存, secup读硬件信息、移动操作系统、进入保护模式,head.s进入main.c 初始化各数据结构,用于以后操作系统管理

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值