声明:本文为学习Codeproject文章的个人总结性文章,
原文:http://www.codeproject.com/Articles/664165/Writing-a-boot-loader-in-Assembly-and-C-Part
本人开发环境:
操作系统:Ubuntu 32位(64位的会有pushl等指令的不能执行等问题,最好为32位)
工具:as ld dd bochs
语言:at&t 16位汇编
计算机启动运行于real mode,ROM会读取硬盘(或其他介质,如软盘)的CHS模式的0柱面,0磁道,1扇区的的数据到内存0x7c00处,然后到此处执行。所以bootloader就是一段代码,将这段代码写入0柱面,0磁道,1扇区中。
好了,原理简单介绍完毕。
我的当前用户目录是/home/chao/,所以我要在~/Documents/目录下来写代码和进行其他的操作。
创建test.S文件
1 .code16 2 .text 3 .global _start; 4 _start: 5 6 movb $'X' , %al 7 movb $0x0e, %ah 8 int $0x10 9 10 . = _start + 510 11 .byte 0x55 12 .byte 0xaa
解释一下代码的意义。
1 movb $'X' , %al 2 movb $0x0e, %ah 3 int $0x10
这是call BIOS interpret,调用号为0x10,查阅资料得知,0x10是Video Service,根据AH中的参数来调用不同的程序,这里AH中是0x0e,功能为Write Character in TTY Mode,也就是向终端写入字符,写入的字符从AL中获取,也就是字符X。
1 . = _start + 510 2 .byte 0x55 3 .byte 0xaa
因为一个有效的启动扇区最后的两个字节内容必须是0x55,0xaa(这是延续下来的,如果不是这两个字节内容,那么这个启动扇区会被认为是无效的,不能启动,所以这两个字节我把它称为验证字节),所以会有地2,3行内容,至于. = _start + 510,这里的 . 代表当前位置,也就是说,把当前位置设置为从代码开始增加510 bytes的位置,因为一个扇区大小为512 bytes(以前也有别的大小,但是后来512成为主流),所以两个字节的大小留给验证字节。
至此,我们的demo bootloader代码就写好了,下面进行汇编,链接。
- as test.S -o test.o
- ld –Ttext 0x7c00 --oformat=binary test.o –o test.bin
-Ttext 0x7c00 告诉linker你想把代码加载到内存0x7c00处(至于为什么是这个地方,可以百度,很有意思),我们生成的是test.bin,也就是二进制文件,可以直接执行。
好了,程序有了,还需要把它写入存储介质的启动扇区,那我们就来创建一个。
- dd if=/dev/zero of=floppy.img bs=512 count=2880
- dd if=test.bin of=floppy.img
我们创建了一个512 bytes的img文件,然后把我们的程序写入。
现在/home/chao/Documents/目录下面应该是这个样子的
好了,启动设备已经就绪,我们还需要测试下它行不行,那就用到bochs了,它是一个虚拟机软件,
安装命令:
sudo apt-get install bochs bochs-sdl
有的地方说安装bochs-x,但是会出现问题,保险起见还是用bochs-sdl.
现在我们为bochs写一个配置文件
在/home/chao/Documents/目录下创建bochsrc.txt
1 megs: 32 2 #romimage: file=/usr/share/bochs/BIOS-bochs-latest, address=0xf0000 3 #vgaromimage: /usr/share/bochs/VGABIOS-lgpl-latest 4 floppya: 1_44=floppy.img, status=inserted 5 boot: a 6 log: bochsout.txt 7 mouse: enabled=0 8 display_library: sdl
注意:2,3行中的路径可能不同,根据自己的系统查找BIOS-bochs-latest和VGABIOS-lgpl-latest(也可能是其它的而不是VGA,根据自己的情况设置)。
为了方便,可以创建一个build.sh脚本
1 as test.S -o test.o 2 ld -Ttext 0x7c00 --oformat=binary test.o -o test.bin 3 dd if=/dev/zero of=floppy.img bs=512 count=2880 4 dd if=test.bin of=floppy.img
如果把创建img文件的步骤放入脚本中,那么/home/chao/Documents/目录下现在有3个文件
打开终端,切换到此目录,执行build.sh,然后所需要的文件都有了
然后执行命令
bochs
可以看到在bochs中显示字符 X
至此,一个demo bootloader就写完了。
这段代码并没有干什么事情,只是解释了如何在计算机启动时执行我们的代码,真正的bootloader会加载内核程序(或者加载其他的程序,通过其他的程序来加载内核)。