Linux-0.01 的引导部分主要由两个源代码完成:boot.s 与 head.s 。boot.s 由 BIOS 加载执行,head.s 是 32 位的引导代码,在最后会调用 main() 函数,完成系统的引导。
boot.s 代码:
; ; boot.s ; ; boot.s is loaded at 0x7c00 by the bios-startup routines, and moves itself ; out of the way to address 0x90000, and jumps there. ; ; It then loads the system at 0x10000, using BIOS interrupts. Thereafter ; it disables all interrupts, moves the system down to 0x0000, changes ; to protected mode, and calls the start of system. System then must ; RE-initialize the protected mode in it's own tables, and enable ; interrupts as needed. ; ; 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 - in fact more would mean we'd have to move ; not just these start-up routines, but also do something about the cache- ; memory (block IO devices). The area left over in the lower 640 kB is meant ; for these. No other memory is assumed to be "physical", ie all memory ; over 1Mb is demand-paging. All addresses under 1Mb are guaranteed to match ; their physical addresses. ; ; NOTE1 abouve is no longer valid in it's entirety. cache-memory is allocated ; above the 1Mb mark as well as below. Otherwise it is mainly correct. ; ; NOTE 2! The boot disk type must be set at compile-time, by setting ; the following equ. Having the boot-up procedure hunt for the right ; disk type is severe brain-damage. ; The loader has been made as simple as possible (had to, to get it ; in 512 bytes with the code to move to protected mode), and continuos ; read errors will result in a unbreakable loop. Reboot by hand. It ; loads pretty fast by getting whole sectors at a time whenever possible. ; 1.44Mb disks: sectors = 18 ; 1.2Mb disks: ; sectors = 15 ; 720kB disks: ; sectors = 9 .globl begtext, begdata, begbss, endtext, enddata, endbss .text begtext: .data begdata: .bss begbss: .text BOOTSEG = 0x07c0;引导程序被加载到的地址 INITSEG = 0x9000;引导程序将自己移动到的目标地址 SYSSEG = 0x1000;系统核心被加载到的地址 ENDSEG = SYSSEG + SYSSIZE;系统代码的结束地址,其中 SYSSIZE 在 Makefile 中定义 entry start;程序入口标识 start: mov ax,#BOOTSEG;将引导程序被加载的地址移动到 AX 中 mov ds,ax;将数据段的基址设置为引导程序的起始地址 mov ax,#INITSEG;将上文提到的目标地址设置到 AX 中 mov es,ax;将 AX 中的值设置到 ES 中,使用基址加偏移的方式移动地址 mov cx,#256;将 CX 计数器的值设置为 256 sub si,si;清空 SI sub di,di;清空 DI rep;重复执行 movw 256 次,实际上是将 512K 的数据(引导程序自身)搬移到INITSEG 处 movw;搬移指令,数据寻址方式,源:DS:SI,目标:ES:DI jmpi go,INITSEG;jmpi 段间跳转指令,由于当前代码已经被复制到 INITSEG ,在不同的段。64K 一