注:以下大部分内容摘自linux内核编程入门篇和linux内核完全注释
对于linux的整个体系结构有了一定的了解,看了每个目录的文件整体概要,那么就
可以开始看内核的源码了,首先那便是引导启动了。
关于磁道,扇区等信息
在这有必要讲一下磁道和扇区等。
1、扇区:不是扇形的,即不是两个半径之间的区域,而是个四边形:两个半径为两边,两个大小同心圆作为两外两边。
2、磁道 :磁道不是线性的,而是个区域,有两个大小同心圆组成
3、 柱面:不是面而是号码相同的多个磁道组成的柱体
4、 磁头数:因为磁盘的双面存储性,使得计算时用磁头数而没有用盘片数
可以说:扇区是硬盘分割的最小单位。
存储容量=磁头数*磁道(柱面)数*每道扇区数*每扇区字节数
_______________________________|----- 磁道的总字节数--------|
________________|-------磁盘一个盘面的总字节数----------------|
__________|----- 磁盘容量(磁头数个盘面)--------------------|
关于8086寄存器
汇编代码是基于8086的,所以先了解了这些寄存器,然后再看代码会更好些。
1、数据寄存器,一般称之为通用寄存器组
8086 有8个8位数据寄存器,
这些8位寄存器可分别组成16位寄存器:
AH&AL=AX:累加寄存器,常用于运算;
BH&BL=BX:基址寄存器,常用于地址索引;
CH&CL=CX:计数寄存器,常用于计数;
DH&DL=DX:数据寄存器,常用于数据传递。
2、地址寄存器/段地址寄存器
为了运用所有的内存空间,8086设定了四个段寄存器,专门用来保存段地址:
CS(Code Segment):代码段寄存器;
DS(Data Segment):数据段寄存器;
SS(Stack Segment):堆栈段寄存器;
ES(Extra Segment):附加段寄存器。
当一个程序要执行时,就要决定程序代码、数据和堆栈各要用到内存的哪些位置,通过设定段寄存器CS,DS,SS来指向这些起始位置。
通常是将DS固定,而根据需要修改CS。所以,程序可以在可寻址空间小于64K的情况下被写成任意大小。所以,程序和其数据组合起来的大小,限制在DS 所指的64K内,这就是COM文件不得大于64K的原因。
3:特殊功能的寄存器
IP(Instruction Pointer):指令指针寄存器,与CS配合使用,可跟踪程序的执行过程;
SP(Stack Pointer):堆栈指针,与SS配合使用,可指向目前的堆栈位置。
BP(Base Pointer):基址指针寄存器,可用作SS的一个相对基址位置;
SI(Source Index):源变址寄存器可用来存放相对于DS段之源变址指针;
DI(Destination Index):目的变址寄存器,可用来存放相对于 ES 段之目的变址指针。
还有一个标志寄存器FR(FlagRegister)有以下九个有意义的标志:
OF: 溢出标志位OF用于反映有符号数加减运算所得结果是否溢出。如果运算结果超过当前运算位数所能表示的范围,则称为溢出,OF的值被置为1,否则,OF的值被清为0.
DF: 方向标志DF位用来决定在串操作指令执行时有关指针寄存器发生调整的方向。
IF: 中断允许标志IF位用来决定CPU是否响应CPU外部的可屏蔽中断发出的中断请求。但不管该标志为何值,CPU都必须响应CPU外部的不可屏蔽中断所发出的中断请求,以及CPU内部产生的中断请求。具体规定如下:
(1)、当IF=1时,CPU可以响应CPU外部的可屏蔽中断发出的中断请求;
(2)、当IF=0时,CPU不响应CPU外部的可屏蔽中断发出的中断请求。
TF: 状态控制标志位是用来控制CPU操作的,它们要通过专门的指令才能使之发生改变
SF: 符号标志SF用来反映运算结果的符号位,它与运算结果的最高位相同。在微机系统中,有符号数采用补码表示法,所以,SF也就反映运算结果的正负号。运算结果为正数时,SF的值为0,否则其值为1。
ZF: 零标志ZF用来反映运算结果是否为0。如果运算结果为0,则其值为1,否则其值为0。在判断运算结果是否为0时,可使用此标志位。
AF: 下列情况下,辅助进位标志AF的值被置为1,否则其值为0:
(1)、在字操作时,发生低字节向高字节进位或借位时;
(2)、在字节操作时,发生低4位向高4位进位或借位时。
PF: 奇偶标志PF用于反映运算结果中“1”的个数的奇偶性。如果“1”的个数为偶数,则PF的值为1,否则其值为0。
CF: 进位标志CF主要用来反映运算是否产生进位或借位。如果运算结果的最高位产生了一个进位或借位,那么,其值为1,否则其值为0。)
关于BIOS启动过程
1、 对计算机硬件执行一系列的测试,用来监测现在都有什么设备以及这些设备是否正常工作。这个阶段通常称为POST(Power-on self-test,上电自检)。这个阶段中,会显示一些信息,例如BIOS版本号。
2、 初始化硬件设备。这个阶段在现代基于PCI的体系结构中相当重要,因为它可以保证所有的硬件设备操作不会引起IRQ线与I/O端口的冲突。在本阶段的最后,会显示系统中所有安装的所有PCI设备的一个列表。
3、 搜索一个操作系统来启动。实际上,根据BIOS的设置,这个过程可能要试图访问系统中软盘、硬盘和CD-ROM的第一个扇区(引导扇区)。
4、 只要找到一个有效的设备,就把第一个扇区的内容拷贝到RAM中从物理地址0x00007c00开始的位置,然后跳转到这个地址处,开始执行刚才装载进来的代码。
下面看下BIOS的中断,具体功能太多了,等调用了可以去查看。
00h 被零除
01h 单步
02h 不可屏中断(NMI)
03h 断点
04h 溢出
05h 屏幕打印
06--07h 保留
________________________________________
08h 日时钟中断
09h 键盘中断
0Ah 保留/8259A从片中断
0Bh 串行口2中断
0Ch 串行口1中断
0Dh 硬盘(XT)/并行口2中断
0Eh 软盘中断
0Fh 打印机/并行口1中断
________________________________________
10h 视频显示I/O
11h 设备配置检测
12h 内存容量检测
13h 磁盘I/O
14h 串行通信I/O
15h 盒带(PC)/多功能
16h 键盘I/O
17h 打印机I/O
18h ROM-BASIC
19h 自举程序
1Ah 时钟I/O
1Bh Ctrl-Break中止
1Ch 时钟控制
1Dh 视频初始化参数表
1Eh 软盘参数表
1Fh 图形显示扩展字符表
________________________________________
20h 程序终止退出
21h 系统功能调用
22h 程序结束地址
23h Ctrl-C处理
24h 严重错误处理
25h 磁盘扇区读
26h 磁盘扇区写
27h 程序终止驻留
28h 键盘空闲处理
29h 快速字符输出
2Ah 保留
________________________________________
2B--2Dh 保留
2Eh 命令执行处理
2Fh 多路中断,共享
________________________________________
30--31h 远转移至INT 21h入口
32--3Fh 保留
________________________________________
40h 软盘I/O
41h 硬盘机1基数表
42--45h 保留
46h 保留
47--5Bh 保留
5Ch 硬盘机2基数表
5D--6Fh 保留
________________________________________
70h 实时钟中断
71h 改向0Ah号中断
72h 保留给IRQA
73h 保留给IRQB
74h 保留给IRQC
75h 协处理器中断
76h 硬盘中断
77h 保留给IRQF
________________________________________
78--7Fh 保留
________________________________________
80--F0h BASIC使用区
________________________________________
F1--FFh 保留
关于bootsect.s
bootsect.s代码是磁盘引导块程序,驻留在磁盘中的第一个扇区中(引导扇区,0磁道(柱面),0磁头,第1扇区)。在我们的电脑上电后。。。。。
1、首先ROM BIOS自检,引导扇区由BIOS加载到内存0x7c00处(如果是嵌入式设备的话,一般都是上电后,由bootloader中加载内核代码到内存的);
2、然后将自己移动到内存0x90000处,该程序主要作用是首先将setup模块从磁盘加载到内存紧接着bootsect的后面位置(0x90200)。
3、然后利用BIOS中断0x13取磁盘参数表中当前启动引导盘的参数,接着在屏幕上显示“loadingsystem..”字符串。
4、再将system模块从磁盘上加载到内存0x10000开始的地方。随后确定根文件系统的设备号,若没有指定,则根据所保存的引导盘的每磁道扇区数判别出盘的类型和种类并保存到其设备号于root_dev(引导块的0x508地址处)。
5、最后长跳转到setup程序开始处(0x90200)执行setup程序。
而在多系统引导的时候,我们经常看到的grub,就类似替代了bootsect的功能使命。
关于setup.s
Setup程序的作用主要是利用ROM BIOS中断读取机器系统数据,并将这些数据保存到0x90000开始的位置,其读取并保留的参数如下表所示:
1、 setup程序将system模块0x10000--0x8fffff整块向下移动到内存绝对地址0x00000处。
2、 加载中断描述符表寄存器(idtr)和全局描述表寄存器(gdtr)。
3、 开启A20地址线
4、 重新设置两个中断控制芯片8259A,将硬件中断号重新设置为0x20—0x2f
5、 设置CPU的控制寄存器CR0(机器状态字),进入32位保护模式运行
6、 跳转到位于system模块最前面部分的head.s程序继续运行。
关于head.s
head.s程序编译后,被连接成system模块的最前面部分。从这里开始内核完全都是在保护模式下运行了。功能如下:
1、加载各个数据段寄存器,重新设置中断描述符表,共256项,并使各个表项均指向一个只报错误的哑中断程序。
2、重新设置全局描述符表。
3、使用物理地址0与1M开始处的内容相比较,检测A20地址线是否开启。
4、测试PC机是否含有数字协处理器芯片,并在控制器CR0中设置相应的标志位。
5、设置管理内存的分页处理机制,将页目录表放在绝对物理地址0开始处,紧随后面放置共可寻址16MB内存的4个页表,并分别设置它们的表项。
6、利用返回指令将预先放置在堆栈中的/init/main.c程序的入口地址弹出,去运行main()程序。