01 ! boot.s 程序
02 ! 首先利用BIOS中断把内核代码(head代码)加载到内存0x10000处,然后移动到内存0处。
03 ! 最后进入保护模式,并跳转到内存0(head代码)开始处继续运行。
04 BOOTSEG = 0x07c0 ! 引导扇区(本程序)被BIOS加载到内存0x7c00处。
05 SYSSEG = 0x1000 ! 内核(head)先加载到0x10000处,然后移动到0x0处。
06 SYSLEN = 17 ! 内核占用的最大磁盘扇区数。
07 entry start
08 start:
09jmpi go,#BOOTSEG ! 段间跳转至0x7c0:go处。当本程序刚运行时所有段寄存器值
10 go: mov ax,cs ! 均为0。该跳转语句会把CS寄存器加载为0x7c0(原为0)。
11mov ds,ax ! 让DS和SS都指向0x7c0段。
12mov ss,ax
13mov sp,#0x400 ! 设置临时栈指针。其值需大于程序末端并有一定空间即可。
14
15 ! 加载内核代码到内存0x10000开始处。
16 load_system:
17mov dx,#0x0000 ! 利用BIOS中断int 0x13功能2从启动盘读取head代码。
18mov cx,#0x0002 ! DH - 磁头号;DL - 驱动器号;CH - 10位磁道号低8位;
19mov ax,#SYSSEG ! CL - 位7、6是磁道号高2位,位5~0起始扇区号(从1计)。
20mov es,ax ! ES:BX - 读入缓冲区位置(0x1000:0x0000)。
21xor bx,bx ! AH - 读扇区功能号;AL - 需读的扇区数(17)。
22mov ax,#0x200+SYSLEN
23int 0x13
24jnc ok_load ! 若没有发生错误则跳转继续运行,否则死循环。
25 die: jmp die
26
27 ! 把内核代码移动到内存0开始处。共移动8KB(内核长度不超过8KB)。
28 ok_load:
29cli ! 关中断。
30mov ax, #SYSSEG ! 移动开始位置DS:SI = 0x1000:0;目的位置ES:DI=0:0。
31mov ds, ax
32xor ax, ax
33mov es, ax
34mov cx, #0x1000 ! 设置共移动4K次,每次移动一个字(word)。
35sub si,si
36sub di,di
37rep movw ! 执行重复移动指令。
38 ! 加载IDT和GDT基地址寄存器IDTR和GDTR。
39mov ax, #BOOTSEG
40mov ds, ax ! 让DS重新指向0x7c0段。
41lidt idt_48 ! 加载IDTR。6字节操作数:2字节表长度,4字节线性基地址。
42lgdt gdt_48 ! 加载GDTR。6字节操作数:2字节表长度,4字节线性基地址。
43
44 ! 设置控制寄存器CR0(即机器状态字),进入保护模式。段
选择符值8对应GDT表中第2个段描述符。
45mov ax,#0x0001 ! 在CR0中设置保护模式标志PE(位0)。
46lmsw ax ! 然后跳转至段选择符值指定的段中,偏移0处。
47jmpi 0,8 ! 注意此时段值已是段选择符。该段的线性基地址是0。
48
49 ! 下面是全局描述符表GDT的内容。其中包含3个段描述符。第1
个不用,另2个是代码和数据段描述符。
50 gdt: .word0,0,0,0 ! 段描述符0,不用。每个描述符项占8字节。
51
52.word0x07FF ! 段描述符1。8Mb - 段限长值=2047 (2048*4096=8MB)。
53.word0x0000 ! 段基地址=0x00000。
54.word0x9A00 ! 是代码段,可读/执行。
55.word0x00C0 ! 段属性颗粒度=4KB,80386。
56
57.word0x07FF ! 段描述符2。8Mb - 段限长值=2047 (2048*4096=8MB)。
58.word0x0000 ! 段基地址=0x00000。
59.word0x9200 ! 是数据段,可读写。
60.word0x00C0 ! 段属性颗粒度=4KB,80386。
61 ! 下面分别是LIDT和LGDT指令的6字节操作数。
62 idt_48: .word0 ! IDT表长度是0。
63.word0,0 ! IDT表的线性基地址也是0。
64 gdt_48: .word0x7ff ! GDT表长度是2KB,可容纳256个描述符项。
65.word0x7c00+gdt,0 ! GDT表的线性基地址在0x7c0段的偏移gdt处。
66 .org 510
67.word0xAA55 ! 引导扇区有效标志。必须处于引导扇区最后2字节处。
一开始总觉得是个减号,后来发现是一个注释号而已。意思是说段限长是8M,表示为2047.