一 前言
前面已经准备好开发环境,并且写了一个简单的引导程序。从本节开始,就要真正的开发操作系统了。
本节代码位于:github
1.1 系统启动流程
这里重新描述一下系统的启动流程:
- PC电源打开,CPU 将自动进入实模式
- 加载BIOS程序并执行
- BIOS进行一些硬件检测配置
- BIOS将可启动设备的第一个扇区(磁盘引导扇区,512 字节)读入内存绝对地址 0x7C00 处,并跳转到这个地方开始引导启动机器运行。
我们的程序从前面第四步开始介入,主要分为三块,功能如下:
| 程序 | 功能 | 磁盘 | 内存 |
|---|---|---|---|
| boot | 引导代码,512 字节。负责读取磁盘加载setup、system | 第一个扇区(引导扇区) | 0x7C00 |
| setup | 获取系统硬件信息,进入保护模式,复制system内存到0x100000 | 扇区2~扇区9 | 0x9000 |
| system | 真正的系统内核 | 扇区10以后 | 0x100000 |
1.2 内存分布
BIOS的内存分布:
0x00000 ~ 0x003FF: 中断向量表(1024B)
0x00400 ~ 0x004FF: bios数据区(256B)
0x00500 ~ 0x07BFF: 自由内存区 30kb
0x07C00 ~ 0x07DFF: 引导程序加载区(512B)
0x07E00 ~ 0x9FFFF: 自由内存区 608k
0xA0000 ~ 0xAFFFF: EGA/VGA/XGA/XVGA图形视频缓冲区(64KB)彩色显示适配器
本系统自由内存区的分配:
0x7E00 ~ 0x8FFF 硬件信息、启动信息
0x9000 ~ 0x9FFF setup
0x10000 ~ 0x9FFFF system
我们的boot肯定是加载到0x7C00处,然后它会继续读取磁盘的2~9扇区(共8个扇区,4KB)并放到内存的0x9000处,读取system放到内存的0x10000处。最后跳转到0x9000处,开始执行setup。
setup会通过BIOS中断读取一些系统硬件信息,进入保护模式,同时将system从0x10000处拷贝到0x100000 (1MB)处,然后跳转到0x100000处开始执行system
接下来将逐步实现boot和header。
二 虚拟硬盘
2.1 创建硬盘
执行bximage命令创建一个虚拟硬盘:

这里将创建一个20MB的虚拟硬盘,文件名为c.img
将最下面那句话copy到bochsrc.os文件中。
三 boot引导
3.1 boot.h
#ifndef _BOOT_H
#define _BOOT_H
// setup的段地址
#define DEF_SETUPSEG 0x900
// system段地址
#define DEF_SYSSEG 0x1000
// system的大小
#define DEF_SYSSIZE 0x10000
#endif
3.2 boot.S
在上一节boot.s的基础上增加了setup和system的加载
#include "boot.h"
BOOTSEG = 0x07C0 /* 引导程序加载的位置*/
.code16
.text
jmpl $BOOTSEG, $_start
.global _start
_start:
// 初始化寄存器
movw %cs, %ax
movw %ax, %ds
movw %ax, %es
movw %ax, %ss
movw $0x7c00, %sp
// 清屏
movw $0x0700, %bx
movw $0x0600, %ax
movw $0x184f, %dx
int $0x10
showMsg:
// 调用0x10中断显示字符串
movw $27, %cx
movw $0x7, %bx
movw $0, %dx
movw $msg1, %bp
movw $0x1301, %ax
int $0x10
read_setup:
movb $0x42, %ah
movb $0x80, %dl
movw $setup_packet, %si
int $0x13
read_system:
movb $0x42, %ah
movb $0x80, %dl
movw $system_packet, %si
int $0x13
// 跳转到setup
jmpl $DEF_SETUPSEG, $0
msg1:
.ascii "Hello, Boot is starting\r\n"
setup_packet:
.word 0x10 /* struct's size */
.word 8 /* 读多少个 sectors */
.word 0, DEF_SETUPSEG /* buffer address */
.quad 1 /* 从哪个 sector 开始读 */
system_packet:
.word 0x10 /* struct's size */
.word DEF_SYSSIZE/512 /* 读多少个 sectors */
.word 0,DEF_SYSSEG /* buffer address */
.quad 9 /* 从哪个 sector 开始读 */
.org 510
boot_flag: .word 0xAA55
四 setup和system
本节只为验证新的boot以及程序结构,所以setup和system里面只有一个死循环:
.global _start
_start:
jmp _start
我将在后面的章节中慢慢完善这两个程序。
五 运行
编写Makefile,开始运行:
all: img
boot.o: boot.S boot.h
boot: boot.o
ld -Ttext 0 -s --oformat binary -o $@ $<
setup: setup.o
ld -Ttext 0 -s --oformat binary -o $@ $<
system: system.o
ld -Ttext 0 -s --oformat binary -o $@ $<
img:boot setup system
dd if=boot of=c.img count=1 conv=notrunc seek=0
dd if=setup of=c.img count=1 conv=notrunc seek=1
dd if=system of=c.img count=1 conv=notrunc seek=9
run: boot bochsrc.os
bochs -f bochsrc.os
clean:
rm boot setup system *.o *.s
%.s: %.S
gcc -E $< -o $@
执行make & make run
运行效果如下图所示:

9876

被折叠的 条评论
为什么被折叠?



