要做一个能在裸机上跑的系统,一个简单的boot loader或者是支持grub之类的是必须的。目前并没有把babyos装到实体机上、支持多系统等的打算,所以还是自己写boot loader。
PC上电后,80x86 CPU自动进入实模式,并从0xFFFF0开始自动执行,这个地址是ROM-BIOS中的地址。BIOS会执行一些检测及初始化中断向量表等,之后它将启动设备第一个扇区512字节读入内存0x7c00,并跳转过去开始执行。这一段是硬件自动完成的,给出的这几个地址也是硬件决定的,跟boot loader无关,跟内核也无关。而一旦跳转到0x7c00处开始执行,就是自己写的代码在工作了。
因为硬件自动加载到内存的数据只有512自己,所以一般操作系统需要自己把自己加载到内存中去,这就是boot loader干的事情。
在boot阶段,开始时处于16位实模式,内存的使用也非常自由。但是自由的同时需要做好规划,比如当还需要用到BIOS中断的时候,不要破坏掉BIOS所占的内存区域。BIOS的内存分布如上图所示。
# the main function
main:
xorw %ax, %ax
movw %ax, %ds
movw %ax, %es
movw %ax, %ss
movw $STACK_BOOT, %sp
call clear_screen
call set_video_mode
call get_memory_info
call load_kernel
call copy_gdt_and_video_info
call begin_protected_mode
1:
jmp 1b
babyos2的boot主要做了下面几件事情:
1.清屛,主要功能是清除掉虚拟机启动时自动打印的一些信息
2.设置显示模式,虽然这次决定不再只做一些花哨的显示相关的东西,但终究没舍得放弃1024*768的显示模式,毕竟比单纯的字符模式有趣的多。这个函数将会设置VBE 模式为0x118,即1024*768,24位的显示模式。
3.获取内存信息,这个暂时不在这里说,后面再描述。
4.加载内核。这是最主要的功能之一,把内核加载到一个临时的地方,因为一旦跳转到保护模式,实模式的BIOS中断就不能或者不容易使用了。因为babyos2从硬盘启动,这个函数主要功能是读硬盘。
5.将gdt和显示模式,及内存相关的一些信息拷贝到一个安全的地址。
6.进入保护模式。
1.clear_screen
# function to clear the screen
clear_screen:
movb $0x06, %ah
movb $0x00, %al # roll up all rows, clear the screen
movb $0x00, %ch # row of left top corner
movb $0x00, %cl # col of left top corner
movb $0x18, %dh # row of right bottom corner
movb $0x4f, %dl # col of right bottom corner
movb $0x07, %bh # property of roll up rows
int $0x10
ret
清屛函数使用BIOS 0x10号中断,ah=0x06,al=0x00表示上滚所有行,即清屛。
2.set_video_mode
# function to set video mode
set_video_mode:
xorw %ax, %ax
movw %ax, %ds
movw %ax, %es
movw $0x800, %di # buffer
# check vbe
movw $0x4f00, %ax
in