欢迎来到尧图网

客户服务 关于我们

您的位置:首页 > 健康 > 养生 > Linux0.11引导启动程序:简略过程

Linux0.11引导启动程序:简略过程

2025/4/29 16:40:49 来源:https://blog.csdn.net/qq_44742941/article/details/147597557  浏览:    关键词:Linux0.11引导启动程序:简略过程
引言
  • 目标:是重写boot文件夹下面的引导文件,加入一些个人信息。
  • 语法:由于使用两个语法风格的汇编需要两个汇编器,有些麻烦,直接全都用GNUas(gas)进行编译。使用AT&T 语法的汇编语言程序。
  • 接下来先拜读同济大学赵炯博士的《Linux内核0.11完全注释(修正版V3.0)》(以后简称《注释》)的第6章,做一些笔记。
  • boot 目录文件:包含 bootsect.s、setup.s、head.s 三个汇编文件。

  • bootsect.ssetup.s:实模式 16 位代码,Linux0.11使用Intel语法,用as86ld86编译。

    原因是

    • 早期 GNU as 不支持实模式 16 位代码
    • 直到 1994 年以后发布的 GNU as 汇编器才开始支持编译 16 位代码的.code16 伪指令。
  • head.s:保护模式 32 位代码,用GNUas(AT&T 语法)编译。

  • 内核 2.4.X 起,bootsect.s 和 setup.s 才完全用 as 编译。

总体功能

先总体说明一下 Linux 操作系统启动部分的主要执行流程。

image-20250428174022399

  • 启动初始ROM BIOS:PC 开机,80x86 CPU 进入实模式,从地址 0xFFFF0(ROM - BIOS)执行代码。BIOS 执行系统检测,在物理地址 0 初始化中断向量,将启动设备(软驱或硬盘)的第一个扇区(512 字节,磁盘引导扇区)bootsect.s读入内存 0x7C00 处并跳转执行。
启动初始化
PC 开机
▼
80x86 CPU 进入实模式
▼
从地址 0xFFFF0(ROM - BIOS)执行代码
▼
BIOS 执行系统检测:检测对象:对 CPU、内存、硬盘、显卡、键盘等主要硬件组件进行检查,确认其是否存在故障或能否正常连接。
▼
在物理地址 0 初始化中断向量:0x400字节1kb的中断向量表
▼
将启动设备(软驱或硬盘)的第一个扇区(512 字节,磁盘引导扇区)bootsect.s读入内存0x7C00(31KB)处
▼
跳转至内存 0x7C00 处执行

这里提到了扇区和对应的代码文件,先说明一下其对应关系:

image-20250428223634666

  • Linux 0.11 内核在 1.44MB 磁盘上所占扇区的分布情况。1.44MB 磁盘共有 2880 个扇区,一个扇区512字节
  • 引导程序代码bootsect占用第 1 个扇区
  • setup模块占用随后的 4 个扇区
  • Linux 0.11 内核 system 模块大约占随后的 240 个扇区。
  • 还剩下 2630 多个扇区未被使用。这些剩余的未用空间可被利用来存放一个基本的根文件系统,从而可以创建出使用单张磁盘就能让系统运转起来的集成盘来。
  • bootsect.s:它将由上一步BIOS读入到内存绝对地址 0x7C00(31KB)

    • 当它被执行时就会把自己移动到内存绝对地址0x90000(576KB)处,本身是一个扇区大小512字节,所以尾部就是0x90200

    • 把代码(boot/setup.s),四个扇区大小2k,读入到bootsect的尾部,内存 0x90200

    • 内核的其他部分(system 模块)则被读入到从内存地址 0x10000(64KB)开始处:为什么是 0x10000(64KB)

      因为当时 system 模块的长度不会超过 0x80000 字节大小(即 512KB),是为了不覆盖到bootsectsetup

image-20250428223719852

  • setup.s:是一个操作系统加载程序,下面解释这个文件做了什么事情

    • 首先、前文说BIOS在物理地址0的地方有个1k的中断向量表,这里先利用ROM BIOS 中断读取机器系统数据,放到0x90000覆盖掉了 bootsect 程序

      image-20250428223905946

    • 然后、将 system 模块从0x10000-0x8ffff(当时认为内核系统模块 system 的长度不会超过512KB)整块向下移动到内存绝对地址 0x00000 处。为什么一开始bootsect不直接放到物理地址0处呢?

      因为 setup 代码开始还需要利用 ROM BIOS 中的中断调用来获取机器的一些参数(例如显示卡模式、硬盘参数表等)。

      BIOS 初始化时会在物理内存开始处放置一个大小为0x400 字节(1KB)的中断向量表,因此需要在使用完 BIOS 的中断调用后才能将这个区域覆盖掉。

  • 最后进入 32 位保护模式运行,并跳转到head.s运行。下面这些操作都是为了进入保护模式做准备

    • 寄存器加载:加载中断描述符表寄存器(idtr)和全局描述符表寄存器(gdtr)。

      进入保护模式,寻址方式发生改变,需要段选择符、段描述符,这里进行最初的设置,后面在head.s里面会进行进一步设置。

    • A20 地址线:开启 A20 地址线。

      80386 有 32 根地址线,可寻址 (2^{32} = 4 GB) 的内存空间。

      A20 地址线(地址总线的第 20 位,从 0 开始计数)与 80386 的关系如下:

      • 实模式兼容性:80386 的实模式为兼容 8086/8088 设计。若 A20 关闭,访问超过 (1MB)(0x100000)的地址时,会像 8086 一样 “回绕”(如 0x100000 映射到 0x000000),因为此时第 20 位地址无效(始终为 0),模拟旧处理器的地址模式。
      • 保护模式内存访问:在保护模式下,A20 开启是访问 (1MB) 以上全部内存的前提。若 A20 关闭,内存访问会被限制在 (0-1MB-1)、2MB-(3MB-1)) 等奇偶分段,无法连续寻址;A20 开启后,32 根地址线可完全发挥作用,实现 (4GB) 地址空间的连续访问。

      简而言之,A20 地址线控制着 80386 对 (1MB) 以上内存的访问方式,是实模式兼容旧架构与保护模式充分利用内存的关键控制项。

    • 中断重设:重新设置中断控制芯片 8259A,将硬件中断号设为 0x20 - 0x2f

    • 设置 CPU 控制寄存器 CR0,进入保护模式。

    • 当这个setup程序完成的时候,系统模块 system 被移动到物理地址 0x0000 开始处,BIOS的中断向量表被system覆盖了。上面一个bootsect程序也已经被机器的系统数据覆盖了

    image-20250428223527881

  • head.s:Head.s 代码的主要作用是初步初始化中断描述符表中的 256 项门描述符,检查 A20 地址线是否已经打开,测试系统是否含有数学协处理器。然后初始化内存页目录表,为内存的分页管理作好准备工作。最后跳转到 system 模块中的初始化程序 init/main.c 中继续执行。

    • 其中值得关注的是:分页机制设置一级页表和二级页表时,是从物理地址0开始的也就是把自身程序给覆盖了。

    那么最后,执行完head.s后,已经正式完成了内存页目录和页表的设置,并重新设置了内核实际使用的中断描述符表 idt 和全局描述符表 gdt。另外还为软盘驱动程序开辟了 1KB 字节的缓冲区。

    image-20250428223441993

接下来具体写一下这三个文件

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com

热搜词