由于最近无聊在家,把购买已久的<30天自制操作系统>给翻了出来(说实话很久没有看书了,有囤书的喜好,但是看书的习惯消失了...),打算把书上的代码给研究下。虽然是一个新书,但是由于进入中国的时候很晚了,加上作者采用的系统是win,所以研究过程中并没有那么顺利。所以为了把代码能运行在ubuntu上,也是费了一番功夫。
下面是一个裸机hello world的例子,其中$ 是当前位置 ,$$ 是段开始位置,$ - $$ 是当前位置在段内的偏移。
; hello-os ; TAB=4 ; 标准FAT12格式软盘专用的代码 Stand FAT12 format floppy code DB 0xeb, 0x4e, 0x90 DB "HELLOIPL" ; 启动扇区名称(8字节) DW 512 ; 每个扇区(sector)大小(必须512字节) DB 1 ; 簇(cluster)大小(必须为1个扇区) DW 1 ; FAT起始位置(一般为第一个扇区) DB 2 ; FAT个数(必须为2) DW 224 ; 根目录大小(一般为224项) DW 2880 ; 该磁盘大小(必须为2880扇区1440*1024/512) DB 0xf0 ; 磁盘类型(必须为0xf0) DW 9 ; FAT的长度(必??9扇区) DW 18 ; 一个磁道(track)有几个扇区(必须为18) DW 2 ; 磁头数(必??2) DD 0 ; 不使用分区,必须是0 DD 2880 ; 重写一次磁盘大小 DB 0,0,0x29 ; 意义不明(固定) DD 0xffffffff ; (可能是)卷标号码 DB "HELLO-OS " ; 磁盘的名称(必须为11字?,不足填空格) DB "FAT12 " ; 磁盘格式名称(必??8字?,不足填空格) RESB 18 ; 先空出18字节 ; 程序主体 DB 0xb8, 0x00, 0x00, 0x8e, 0xd0, 0xbc, 0x00, 0x7c DB 0x8e, 0xd8, 0x8e, 0xc0, 0xbe, 0x74, 0x7c, 0x8a DB 0x04, 0x83, 0xc6, 0x01, 0x3c, 0x00, 0x74, 0x09 DB 0xb4, 0x0e, 0xbb, 0x0f, 0x00, 0xcd, 0x10, 0xeb DB 0xee, 0xf4, 0xeb, 0xfd ; 信息显示部分 DB 0x0a, 0x0a ; 换行两次 DB "hello, world" DB 0x0a ; 换行 DB 0 RESB 0x1fe-($-$$) ; 填写0x00直到0x001fe DB 0x55, 0xaa ; 启动扇区以外部分输出 DB 0xf0, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00 RESB 4600 DB 0xf0, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00 RESB 1469432
使用的编译器nasm,使用dd工具制作了启动盘,制作启动软盘的命令是
dd if=/dev/zero of=emptydisk.img bs=512 count=2880 dd if=hello of=boot.img bs=512 count=1 dd if=emptydisk.img of=boot.img skip=1 seek=1 bs=512 count=2879
原理很简单,就是把hello二进制文件的512字节,写入到镜像的首部。