mit-6.828 boot/boot.S 源码阅读
- boot/boot.S
-
该文件的目的:
- start CPU, switch to 32-bit protected mode(启动CPU 并且最终转到32-bit 保护模式)
- BIOS loads code from first sector of the hard disk into memory at physical addr 07xc00
- executing in real mode (%cs=0, %ip=7c00)
-
步骤:
- 初始化重要的segment registers,全部初始化为0
- 16位指令下,屏蔽中断,初始化段寄存器
- 开启A20 gate,停止取模运算,将高位的空间也可访问
- 利用bootstrap GDT转换到protected mode
- 跳转到32-bit模式下的下一个指令
- 然后在32-bit 保护模式下,设置保护模式的寄存器
- 设置stack pointer 然后调用main.c执行main.c里面的bootmain函数
-
关于开启A20 gate的代码部分解析:
11 # Enable A20:
12 # For backwards compatibility with the earliest PCs, physical
13 # address line 20 is tied low, so that addresses higher than
14 # 1MB wrap around to zero by default. This code undoes this.
15 seta20.1:
16 inb $0x64,%al # Wait for not busy
17 testb $0x2,%al
18 jnz seta20.1
19 movb $0xd1,%al # 0xd1 -> port 0x64
20 outb %al,$0x64
21 seta20.2:
22 inb $0x64,%al # Wait for not busy
23 testb $0x2,%al
24 jnz seta20.2
25 movb $0xdf,%al # 0xdf -> port 0x60
26 outb %al,$0x60
这部分指令就是在准备把CPU的工作模式从实模式转换为保护模式。我们可以看到其中的指令包括inb,outb这样的IO端口命令。所以这些指令都是在对外部设备进行操作。根据下面的链接:
http://bochs.sourceforge.net/techspec/PORTS.LST
我们可以查看到,0x64端口属于键盘控制器804x,名称是控制器读取状态寄存器。下面是它各个位的含义。
所以16~18号指令是在不断的检测bit1。bit1的值代表输入缓冲区是否满了,也就是说CPU传送给控制器的数据,控制器是否已经取走了,如果CPU想向控制器传送新的数据的话,必须先保证这一位为0。所以这三条指令会一直等待这一位变为0,才能继续向后运行。
当0x64端口准备好读入数据后,现在就可以写入数据了,所以19~20这两条指令是把0xd1这条数据写入到0x64端口中。当向0x64端口写入数据时,则代表向键盘控制器804x发送指令。这个指令将会被送给0x60端口。
通过图中可见,D1指令代表下一次写入0x60端口的数据将被写入给804x控制器的输出端口。可以理解为下一个写入0x60端口的数据是一个控制指令。
然后21~24号指令又开始再次等待,等待刚刚写入的指令D1,是否已经被读取了。
如果指令被读取了,25~26号指令会向控制器输入新的指令,0xdf。通过查询我们看到0xDF指令的含义如下
这个指令的含义可以从图中看到,使能A20线,代表可以进入保护模式了。
注:部分资料来自网络