详细解析
1. 定义常量与段地址
SYSSIZE
: 定义了系统需要加载的字节数量(16字节的倍数),当前设置为0x30000字节(196kB)。SETUPLEN
: 设置需要加载的setup扇区数量,这里设为4个扇区。BOOTSEG
,INITSEG
,SETUPSEG
,SYSSEG
,ENDSEG
: 分别定义了原始引导扇区、初始化段、setup段、系统加载段和结束段的地址。
2. 段定义
begtext
,begdata
,begbss
,endtext
,enddata
,endbss
: 定义了代码段、数据段和未初始化数据段的起始和结束位置。
3. 主程序流程
- 初始化: 将
BOOTSEG
的内容复制到INITSEG
,并跳转到新位置继续执行。 - 栈设置: 初始化堆栈指针到
0x9ff00
。 - 加载setup: 使用BIOS中断
0x13
从磁盘读取SETUPLEN
个扇区到SETUPSEG
。 - 获取磁盘参数: 调用BIOS中断
0x13
获取磁盘信息,如每磁道的扇区数。 - 打印信息: 显示“Loading system …”的消息。
- 系统加载: 调用
read_it
子程序将系统加载到SYSSEG
。 - 关闭磁盘电机: 调用
kill_motor
确保进入内核时磁盘电机关闭。 - 选择根设备: 根据磁盘参数确定根设备,若未定义,则根据磁盘类型选择默认设备。
- 跳转至setup: 最终跳转到
SETUPSEG
处的setup程序。
4. 子程序
read_it
: 负责系统加载,确保不跨越64KB边界,尽可能快速加载整个磁道。read_track
: 读取磁道的子程序,处理读取错误并尝试重新读取。kill_motor
: 关闭磁盘驱动器电机,确保系统状态已知。
5. 结构与变量
sectors
: 存储每磁道的扇区数。msg1
: 显示的加载信息字符串。root_dev
: 根设备标识符,默认为0x306(第一硬盘的第六分区)。
6. 组织结构
- 文件以
.org 508
结束,指示编译器文件应放置在512字节引导扇区的特定偏移量上。
!
! 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 then loads 'setup' directly after itself (0x90200), and the system
! at 0x10000, using BIOS interrupts.
!
! NOTE! currently system is at most 8*65536 bytes long. This should be no
! problem, even in the future. I want to keep it simple. This 512 kB
! kernel size should be enough, especially as this doesn't contain the
! buffer cache as in minix
!
! The loader has been made as simple as possible, and continuos
! read errors will result in a unbreakable loop. Reboot by hand. It
! loads pret