一、环境搭建
1 工作环境
- Ubuntu20.04
- vscode
2 使用到的工具和软件
- NASM – 一款基于x86架构的汇编与反汇编软件。它可以用来汇编16位(8086、80286等)、32位(IA-32)和64位(x86_64)的程序。(将.asm文件汇编成.bin等文件)
- Bochs – 一款基于x86硬件平台的开源模拟器。它可以模拟各种硬件的配置。(类似于VMware,用于模拟出一套x86架构硬件)
- bximage – 一款用于创建、转换和调整磁盘映像大小的工具。(用于创建一块存放操作系统的虚拟磁盘)
3 ubuntu下工具和软件的安装
sudo apt-get install nasm
sudo apt-get install bochs bochs-x
sudo apt-get install bximage
二、理论说明
1 执行过程
- 计算机上电的时候,CPU处于实模式下,cs:ip寄存器被强制初始化为
F000:FFF0
,对应到实际的物理地址为0xFFFF0
(BIOS的入口地址),此地址中的内容为一条跳转指令jmp far f000:e05b
(BIOS代码的真正所在处)。 - 此时,CPU的控制权交接到BIOS。BIOS进行的工作有:
①检测内存、显卡等外设信息;
②初始化相关硬件;
③在0x000~0x3FFF处,建立中断向量表;
④最后一项工作为校验启动盘的主引导扇区MBR
(0盘面0磁道1扇区)。
(如果该扇区的末尾两个字节分别为魔数0x55
和0xaa
,则BIOS认为该扇区确实为主引导扇区,便将该扇区内容加载到0x7c00
处,并跳转到此继续执行) - 至此,CPU控制权从BIOS交接到mbr中的主引导程序。主引导程序的功能为:
①从16位的实模式切换到32位的保护模式;
②将内核代码读入到内存
③跳转到os的入口点执行(将控制权交接给os)
二、boot程序的简单实现
本boot程序只是实现了在显示器中打印字符串功能来验证以上前两步过程的可行性,而模式的切换和控制权的交接,会在日后尝试实现。
1 虚拟磁盘的创建
#创建一块扇区大小为512字节、容量为16MB、名称为gnixOS.img的普通硬盘镜像
bximage -q -mode=create -hd=16 -imgmode=flat gnixOS.img
#生成成功后,会得到如下信息(配置bochsrc文件时会用到)
ata0-master: type=disk, path="gnixOS.img", mode=flat
2 boot汇编代码的编写
在vscode中创建boot.asm汇编文件
org 0x7c00 ;告诉编译器将0x7c00作为之后数据地址的起始地址
;显示器的清屏
mov ax, 3
int 0x10 ;清屏中断
;各寄存器的初始化
mov ax, cs
mov es, ax
mov ds, ax
mov ss, ax ;cs, es, ss ds段寄存器初始化为0
mov sp, 0x7c00 ;栈顶初始化为0x7c00
mov si, info
call print ;调用print子函数
jmp $
;-------------------------------------------------
;print子函数,通过0x10中断,在显示器中打印info字符
;-------------------------------------------------
print:
mov ah, 0x0e
.next:
mov al, [si]
cmp al, 0
jz .done
int 0x10
inc si
loop .next
.done:
ret
info: db "HELLO", 10 ,13, 0 ;hello\n\r,并将0作为结束字符
;----------------------------------------
;一个扇区的大小为512字节,填充1扇区的剩余字节
;----------------------------------------
times 510-($-$$) db 0 ;代码和魔数之间的字节用0填充
dw 0xaa55 ;最后两个字符为0x55 0xaa
3 将asm文件编译生成bin文件
nasm -f bin boot.asm -o boot.bin
4 将bin文件写入到硬盘镜像的第一个扇区中
dd if=boot.bin of=gnixOS.img bs=512 count=1 conv=notrunc
5 将bochs配置写到bochsrc文件中(相当于配置BIOS)
#修改bochsrc中的内容
display_library: x, options="gui_debug" #gui调试
boot: disk #从硬盘启动
ata0-master: type=disk, path="gnixOS.img", mode=flat #硬盘镜像的详情(bximage获得)
6 启动bochs
bochs -q
-> continue