bootsect.s 预备——Linux-0.11 剖析笔记(一)

boot 目录下文件介绍

boot 目录中一共有三个文件,都是用汇编语言写的,如下图(图来自赵炯的书)

在这里插入图片描述

我是在 https://mirrors.edge.kernel.org/pub/linux/kernel/Historic/old-versions/ 下载的 Linux-0.11 的源码。

再提供一个下载地址:http://oldlinux.org/Linux.old/

打开 boot 文件夹,和上图对比一下。

在这里插入图片描述
修改日期差了 8 个小时,应该是不同时区导致的。

这 3 个文件虽然都是汇编程序,但却使用了两种语法格式。 bootsect.s 和 setup.s 是实模式下运行的 16 位代码程序,使用类似于 Intel 汇编语法,并需要使用 Intel 8086 汇编编译器(as86)和连接器(ld86),这一点在 Makefile 里面有体现:

...

AS86	=as86 -0 -a
LD86	=ld86 -0

...

boot/setup: boot/setup.s
	$(AS86) -o boot/setup.o boot/setup.s
	$(LD86) -s -o boot/setup boot/setup.o

boot/bootsect:	boot/bootsect.s
	$(AS86) -o boot/bootsect.o boot/bootsect.s
	$(LD86) -s -o boot/bootsect boot/bootsect.o

而 head.s,则使用 AT&T 汇编格式, 运行在保护模式下,需要用 GNU 的 gas 进行编译、gld 进行链接。Makefile 里面有体现:

AS	=gas
LD	=gld

Linus 当时使用两种汇编编译器的主要原因在于对于 Intel x86 处理器系列来讲,那时的 GNU 编译器仅支持 i386 及以后的 CPU,如果不用特殊方法,就无法编译出在实模式下运行的程序。

直到 1994 年以后发布的 GNU as 汇编器才开始支持编译 16 位代码(使用 .code16 伪指令)。

16 位代码是什么意思

有人会问,这里的 16 位代码到底是什么意思?实模式和保护模式有何区别?

最早的 8086 处理器,寄存器和数据线都是 16 位,地址线是 20 位,可以寻址 1MB 的内存。16 位的寄存器如何表示 20 位的物理地址呢?

答案是 :物理地址 = 段基址<<4 + 段内偏移

段基址和段内偏移都是 16 位的,16 位的段基址左移 4 位,再加上段内偏移,就构成了 20 位的物理地址。

后来,有了 80286,它的寄存器和数据线也是 16 位,地址线变成了 24 位。在寻址上,开创了新方法。寻址时,段寄存器保存的值不再是段基址,而是段选择子(selector),其中高 13 位指向描述符表(descriptor table)的条目;低 2 位则定义了请求权限,从 0 到 3;剩下的 1 位表示是使用全局描述符表(GDT)还是局部描述符表(LDT)。描述符表的条目为 8 字节长,其中包括 24 位的段起始物理地址,这个 24 位段起始物理地址再加上 16 位的段内偏移,就构成了访问内存的物理地址。为了和 8086 那种寻址模式区别开,就把原先的称为“实模式”,现在的这种称作“保护模式”。当然,为了兼容,80286 及以后的处理器是支持实模式的。

我认为,16 位代码是指在实模式下工作的代码,在这种模式下,寄存器和数据线都是 16 位,于是称为 16 位代码。

你有没有想过这样一个问题——计算机是怎么开始执行我们写的指令的?这就需要了解计算机的启动过程。

计算机启动过程

对于 32 位的 x86 处理器,加电后,处于实模式,段寄存器 CS 的内容是 0xF000,IP 寄存器的内容为 0xFFF0,按照实模式地址的合成方法,得到的地址就是 0xFFFF0;另外,在刚启动的时候,处理器会将地址线 A20~A31 强制为高电平,所以,32 根地址线发出的物理地址就是 0xFFFF_FFF0,这个地址存放的就是 BIOS 的第一条指令。

在 Bochs 上调试的时候,可以看到第一条指令是:

jmpf 0xf000:e05b  

上电后,BIOS 需要做的工作有很多,比如
1)初始化各种主板芯片组
2)初始化键盘控制器
3)初始化中断向量 ,中断服务例程.
4)初始化 VGA BIOS 控制器
5)显示 BIOS 的版本和公司名称
6)扫描软驱和各种介质容量
7)读取 CMOS 的启动顺序配置,并检测启动装置是否正常
8)调用 INT 19h

对于汇编语言的学习,需要了解最后两个步骤,(7)和(8)做的工作是:

BIOS 按照启动顺序,选择排在第一位的储存设备,读取该设备的第一个扇区(大小是 512B)到内存 0x7c00(物理地址)处,然后检查这 512 个字节的最后两个字节是不是 0x55 和 0xAA,如果是则表明这个设备可以用于启动,这个扇区就是主引导扇区;如果不是,则继续尝试启动顺序中的下一个设备。

如果确实是可以启动的设备,则用一个华丽的 JMP 指令跳到 0x0000:0x7c00 处执行。

jmp 0x0000:0x7c00

Linux 0.11 启动过程

在这里插入图片描述

如图所示,可以分为几个阶段:

  1. 如上文所述,PC 上电后,BIOS 做了很多工作,最后选择排在第一位的储存设备,读取该设备的第一个扇区(大小是 512B,对应的代码就是 bootsect.s)到内存 0x7c00(物理地址)处,并跳转到这个地方;
  2. 当 bootsect.s 被执行时,就会把自己移动到内存绝对地址 0x90000 处;
  3. bootsect.s 把启动设备中接下来的 4 个扇区(对应代码 setup.s)读入到内存 0x90200 处,而内核的其他部分( system 模块)则被 读入到从内存地址 0x10000 处,然后跳转到 setup.s 去执行;
  4. setup.s 程序把 system 模块移动到物理内存起始位置处,这样 system 模块中代码的地址也即等于实际的物理地址,便于对内核代码和数据进行操作

另外,网上还有一张图,也很好。

在这里插入图片描述

因为当时 system 模块的长度不会超过 512KB,所以 bootsect.s 把 system 模块读入到从内存地址 0x10000 处并不会覆盖自己。

有人会问,bootsect.s 为什么不把 system 模块直接加载到物理地址 0x0000 处,而是先加载到 0x10000,再通过 setup.s 把 system 模块移动到物理内存起始位置处,这是何苦呢?

这是因为 setup.s 代码执行的时候,需要用到 ROM BIOS 中的中断调用来获取机器的一些参数,例如显卡模式、硬盘参数表等,而 BIOS 中断向量表存放在物理内存开始处,大小为 1KB。必须等使用完 BIOS 中断调用后,才能“过河拆桥”。


参考资料

【1】《Linux 内核完剖析》,赵炯,械工业出版社(ISBN:9787111180326)

【2】维基百科「 Intel 80286 」词条

  • 3
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
以内核源代码为基础,介绍了完整的linux内核实现原理 ·选择早期linux内核进行介绍,排除了目前内核中复杂而庞大的实现细节 ·整个内核代码仅有14000行 ·提供可运行相关内核的完整实验系统 本书对早期的linux操作系统内核(v0.11)全部源代码文件进行了详细的注释和说明,旨在让读者能够在短时间内对linux的工作机理获得全面而深刻的理解,为进一步学习和研究linux系统打下坚实的基础。书中首先介绍了linux系统的发展历史,着重说明了各个内核版本之间的重要区别,给出了选择0.11版作为研究对象的原因;然后依据内核源代码的组织结构对所有代码进行了详细注释。在注释的同时,还介绍了读者应该了解的相关知识,并给出了相关的硬件信息。本书还介绍了内核源代码的组织结构及相互关系。 本书适合作为计算机专业学生学习操作系统课程的实践教材和参考书,也适合linux操作系统爱好者自学,还可供具有一定基础的技术人员作为嵌入式开发应用的参考书。 *************************************************************** 请注意: 下载完,评论的同时,请点击评论框上方的五角星(共5个五角星),这样你的被扣的积分就可以返还了。 如果只评论,不点击小五角星,积分不会返还。 一定要先下载完,再评论。如果先评论后下载,或者在下载的过程中评论,积分同样不会返还。 *************************************************************** 更多linux、ARM和C语言资源请参考: http://blog.csdn.net/arkofnoach/archive/2010/10/23/5960560.aspx
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值