打开电源,计算机执行的第一句指令是什么?
(1) x86PC刚开机时CPU处于实模式;
(2) 开机时, CS=0xFFFF, IP=0x0000;
(3) 寻址0xFFFF0(ROM BIOS映射区);
(4) 检查RAM, 键盘, 显示器, 软硬磁盘;
(5) 将软盘0面0道1扇区(主引导扇区, 对应操作系统第一段代码,即主引导程序.Linux 0.11源码对应文件为boot/bootsect.s)读入0x7c00处;
(6) 设置cs=0x07c0, ip=0x0000.

bootsect.s
bootsect.s (1个扇区)把自身从0x7c000处搬到0x90000处,再把setup.s(4个扇区)搬到0x90200处,然后调用0x13号中断在屏幕上打印“Loading system…”,再把system模块加载到0x10000处。之后确定根文件系统的设备号,若没指定,则根据所保存的引导盘的每磁道扇区数判定盘的类型(是1.44M A盘吗?)并保存其设备号于root_dev。最后139行跳转到setup.s执行。






140行~227行代码用来加载system模块,由于采用比较原始的CHS模式读取软盘比较复杂,不再细看,暂且当成一个黑箱吧,日后若研究细节再做分析。


setup.s
代码105行之前,利用 ROM BIOS 中断例程获取系统参数(如光标位置、内存大小等),并写入 0x900000-x901FF 处(覆盖原来的 bootsect.s 区域)。然后把 system 模块从 0x10000-0x8ffff (当时认为 system 模块不会超过512K)搬到 0x0000 处(0x00000-0x003ff 的256个中断号的中断向量表被覆盖,之后再用int就不再是查0x00000处的中断向量表了,而是查IDT)。然后开启 A20 地址线并设置 8259A 中断控制芯片,再设置 CR0 的 PE 位,进入 32 位保护模式,转到 system 模块的第一个代码 head.s 执行。









执行191行之后,跳到0x00000000。那么该处对应哪个代码文件呢?
Makefile
要让操作系统正常运行,必须通过Makefile控制各个代码文件加载顺序、如何组合等工作。Makefile是make工具的配置文件,相当于批处理文件,在含有Makefile的当前目录里执行make命令,就会根据Makefile中的信息对源代码进行编译、链接等工作。
根据Makefile的配置要求,0x00000000处就是system模块的head.s,下面要进入head.s执行。

head.s
本程序重新设置GDT和IDT,并做一些校验工作(如A20地址线是否启动等),然后设置并开启分页(分页相关的内容在内存管理再说),然后跳入main函数执行。







源代码(个人适当增加注释)
bootsect.s
!
! SYS_SIZE is the number of clicks (16 bytes) to be loaded.
! 0x3000 is 0x30000 bytes = 196kB, more than enough for current
! versions of linux
!
SYSSIZE = 0x3000
!
! bootsect.s (C) 1991 Linus Torvalds
!
! bootsect.s is loaded at 0x7c00 by the bios-startup routines, and moves
! iself out of the way to address 0x90000, and jumps there.
!
! It

本文详细解析了计算机开机启动的首条指令执行流程,从实模式到保护模式的转换,以及Linux操作系统如何从主引导扇区加载至内存并初始化系统。通过分析BIOS中断、硬件检测、内存管理及中断向量表的设置,揭示了Linux内核的启动机制。
最低0.47元/天 解锁文章
2533

被折叠的 条评论
为什么被折叠?



