目录
- 第一部分
- 第二部分
- 第三部分
- 该源文件功能分为三部分:
- (1)源文件开始部分是通过各种中断指令, 初始化计算机的组成硬件,获得硬件的参数,然后保存到段空间0X9000。该空间原来是保存加载到内存的引导扇区内容。执行到此刻,引导程序已经执行完毕,所以覆盖引导程序没有问题。
- (2)将加载到内存0X1000:0X0000地址的 系统核心模块System,通过串传送指令movsw移动到内存0X0000:0X0000。也就是整体向前移动64KB的空间。
- (3) 将CPU从实模式切换到保护模式,然后用保护模式的跳转方式,跳转到正确的位置(就是0地址,执行System模块)。
第一部分
这部分就是通过各种BIOS中断获取组成计算机硬件的参数。参数包括:光标的位置、内存的大小、屏幕显示的参数、硬盘的参数等。都保存在段空间0X9000处。学过《汇编语言》都能看懂,就不细说了。
第二部分
将加载到内存0X1000:0X0000处的系统核心模块System,移动到0地址(0X0000:0X0000)处。刚开始看这段代码时,我很费解。为什么在引导程序bootsect.s不直接把磁盘中的System模块加载到0地址处,非要现在到setup.s中再来移动呢? 看完整个代码我懂了。
每次开机,启动操作系统时,都要获取硬件的参数(setup.s的第一部分),获取参数是通过中断,处理中断的中断例程是BIOS提供的,中断类型码和中断例程的映射要通过中断向量表。而实模式下的中断向量表默认保存在内存0地址处。如果bootsect.s直接把System模块加载到0地址处,就覆盖了中断向量表。
那么现在的setup.s的第一部分就无法获得硬件参数。因为就是通过“int 中断类型码”执行BIOS提供的中断例程来获取硬件参数。所以bootsect.s中只能先加载到0X1000:0X0000处,然后setup.s再移动到0X0000:0X0000处。
之所以在setup.s的第二部分可以覆盖掉中断向量表,是因为后面的第三部分就是切换到保护模式了。保护模式下的中断是通过查IDT(中断描述符表)实现的。
第三部分
进入保护模式后访问的空间就不止1M了,所以要打开A20地址线。然后还要初始化可编程中断控制器8259A。这两段内容对硬件端口的操作复杂、繁琐,没有deepseek我根本看不懂。感谢deepseek,没有它,我肯定没信心阅读Linux源码了。
将CPU从实模式切换到保护模式,只需将CR0寄存器的PE位置1就可以了。切换到保护模式后,我们就要通过Call指令跳转到0地址处的System模块。保护模式下的CS中保存的不是段地址,而是段选择子。通过段选择子查找GDT得到段描述符,段描述符中的基址加上偏移地址就是最终的地址。所以我们要 构造一个简单的GDT表,然后通过LGDT指令把GDT的地址、界限加载到GDTR寄存器。如果你懂CPU的保护模式,这段很简单。看不懂,只能先去看看保护模式的资料,再来看。保护模式不是一两句话能说清的。操作系统修炼指南–保护模式