简介
相信计算机专业的人都学过操作系统相关的知识,也有很多人安装过操作系统,那么我们在学习相关理论知识的时候,有没有真正动手实践过怎么让机器启动就加载我们的代码并将cpu指令进入内核呢。小子不才,根据网上资料踩坑之后成功运行了操作系统版hello world,下面是一篇踩坑指南
环境介绍
macbook pro m1芯片的机器(该配置无视)
parallels desktop (虚拟机软件)破解(https://qiujunya.com/article/2020/9/9/103.html)
安装 ubuntu 20.04.2 ARM64虚拟机 (内置安装)
安装bochs(一款模拟操作系统硬件,cpu的软件)免费
sudo apt update
sudo apt install build-essential libx11-dev xorg-dev libgtk2.0-dev
wget https://sourceforge.net/projects/bochs/files/bochs/2.7/bochs-2.7.tar.gz
tar zxvf bochs-2.7.tar.gz
cd bochs-2.7/
./configure --with-x11 --with-wx --enable-debugger --enable-disasm --enable-all-optimizations --enable-readline --enable-long-phy-address --enable-ltdl-install --enable-idle-hack --enable-plugins --enable-a20-pin --enable-x86-64 --enable-smp --enable-cpu-level=6 --enable-large-ramfile --enable-repeat-speedups --enable-fast-function-calls --enable-large-ramfile --enable-handlers-chaining --enable-trace-linking --enable-configurable-msrs --enable-show-ips --enable-cpp --enable-debugger-gui --enable-iodebug --enable-logging --enable-assert-checks --enable-fpu --enable-vmx=2 --enable-svm --enable-3dnow --enable-alignment-check --enable-monitor-mwait --enable-avx --enable-evex --enable-x86-debugger --enable-pci --enable-usb --enable-voodoo #如果这些参数有报错,可以去掉一些,然后使用make clean && make uninstall重装
make
sudo make install
#./configure后面的参数便是打开调试功能的开关
安装nasm汇编编译器
apt install nasm
nasm -v #查看是否安装成功
操作系统启动过程
BIOS阶段
计算机在按下开机键后,首先运行的是BIOS程序,BIOS首先进行加电自检,完成对系统的全面检查。确保核心组件如CPU、主板、内存、串并口、磁盘等正常运行。这一检测经常被称为post或power on selftest。
完成加电自检后,BIOS所做的第二项工作就是设备初始化。
然后,BIOS将根据用户所指定的引导次序,按照顺序选择引导设备。在选择了合适的引导设备后,BIOS会把引导设备第一个数据块载入内存,并把执行权移交给它。
引导程序加载阶段
第一个数据块所记载的是主引导记录(MBR),共512个字节。包括:引导加载程序(Boot Loader)(前446个字节,如GRUB等)、磁盘分区表(DPT,Disk Partition Table)、分区有效性标志(55AA)。引导加载程序负责加载启动硬盘分区中的操作系统。
Linux系统中的引导程序有以下3个作用:
- 编写合适的内核命令行
- 装载合适的初始虚拟磁盘(简称initrd)
- 装载合适的linux内核并移交控制权给它。
引导程序在设计上通常包括两个阶段:
第一阶段,第一阶段的引导程序通常很小,适合存放在MBR中(因为只有446个字节)。第一阶段引导程序的任务是:定位、装载并把控制权传递给第二个阶段的引导程序,这个程序在文件系统中是看不到的;
第二阶段,第二阶段的引导程序通常就是引导程序自身,它在启动时就运行了某种形式的应用程序,能够读取有关默认设置的配置信息。第二阶段引导程序通常是文件系统中可以识别的二进制文件。
内核运行阶段
Linux内核文件都是以压缩格式存放的,在上一步骤成功完成后,Linux内核被加载至内存中,内核文件首先完成自解压,并在ramdisk文件的帮助下,内核拥有了访问磁盘及文件系统等基本设备的驱动程序。随后内核在完成探测可识别的硬件设备并加载相应驱动,以只读方式加载根文件系统等操作后,内核就可以启动位于磁盘上的第一个应用程序init,进而完成系统的初始化。
编写boot loader汇编程序
BIOS由Bochs虚拟机提供,我们接下来写的就是这个512字节的引导扇区(MBR)的汇编代码。目前它并不用加载操作系统,我们只让它在屏幕上打印出经典的“hello world”即可。
汇编代码
org 0x07c00
mov ax,cs
mov ds,ax
mov es,ax
mov ax,Message
mov bp,ax
mov cx, 13
mov ax,0x1301
mov bx,0x0002
mov dh,0
mov dl,0
int 0x10
jmp $
Message:
db "Hello, world!"
times 510-($-$$) db 0
dw 0xaa55
代码和数据是按汇编程序的编写顺序依次连续存放到内存的,即上面的程序在0x7c00处开始存放的是org 0x07c00的机器指令,在512字节最后放的是0xaa55数据。
BIOS程序在把引导程序加载到内存时,同时还创建了中断系统,在物理内存的前1KB空间初始化中断向量表,在物理内存最后256KB物理地址空间内保存中断处理程序。cpu运行完BIOS后,物理内存的布局如下:
image.png
.
具体代码的含义可以自学汇编语法,此处我也是刚入门
制作虚拟硬盘
# 新建bochs项目目录,随意取名
mkdir bochs_project
# 将上面的代码保存到 bochs_project目录 HelloWorld.asm
# 使用汇编编译器nasm将该代码编译为可执行文件
nasm boot.asm -o boot.bin
# 然后在本层目录中创建一个大小为1MB的硬盘镜像文件b.img的命令如下:
dd if=/dev/zero of=b.img bs=512 count=2048
#dd是文件拷贝命令,其中:
#if=/dev/zero:表示拷贝的源文件的路径,"/dev/zero"是一个特殊的文件,可以提供n个0(n的值等于bs和count参数的积)
#of=b.img:表示拷贝的目标文件路径。若不存在,则创建该文件bs=512:表示大小,单位为B
#count=2048:表示拷贝的文件的块的数量。
# 由bs和count参数可知,硬盘镜像文件的大小为:2048*512B=1MB,硬盘镜像文件制作好后,将可执行文件boot.bin拷贝到硬盘镜像文件b.img(硬盘)的引导扇区的命令如下:
dd if=boot.bin of=b.img bs=512 seek=0 conv=notrunc
#其中:
#seek=0:表示把可执行文件boot.bin拷贝到硬盘镜像文件b.img的引导扇区(扇区号为0)。
#conv=notrunc:表示不改变目标文件的大小,若没有该选项,则硬盘镜像文件b.img的大小会由1MB变为可执行文件boot.bin的大小512B。
这样一个写入了引导程序的“硬盘”就制作好了。
bochs使用
"硬盘”制作好后,要想启动bochs还需要一个配置文件——bochsrc.bxrc。为什么需要配置文件呢?因为你需要告诉bochs你希望的虚拟机是什么样的,比如,内存多大,使用哪个硬盘启动等等。在下载bochs的源码包中有一个.bochsrc,就是官方提供的配置文件示例,我们可以根据这个更改。
cp ../bochs-2.7/.bochsrc bochsrc.bxrc
# 拷贝过来后,编辑这个文件 找到以下的参数进行修改
romimage: file=/usr/local/share/bochs/BIOS-bochs-latest
vgaromimage: file=/usr/local/share/bochs/VGABIOS-lgpl-latest
ata0-master: type-disk, path="b.img"
megs: 16
cpu: count=1
boot: disk
其中:
- romimage:指定bochs运行过程中使用的ROM-BIOS的路径。
- vgaromimage:指定bochs运行过程中使用的VGA的ROM-BIOS的路径。
- ata0-master:指定硬盘镜像文件b.img的路径。
- megs:指定物理内存的大小,单位为MB。
- cpu:指定cpu的个数,1个。这个参数我们只需要count,其他的都可以删掉
- boot:指定启动方式,从硬盘启动。
改完这些还是会报错Bochs is not compiled with lowlevel sound support.
找到 sound配置,将那个配置删除,一般在900多行
编辑完成后保存
现在一切准备就绪,启动bochs的命令如下:
bochs -q -f bochsrc.bxrc
#其中:
#-q: 跳过bochs启动后的配置界面。
#-f : bochsrc.bxrc:指定配置文件的路径。
#如果不指定路径,那么Bochs将按照如下顺序在当前目录中寻找配置文件:
运行bochs后会在终端出现bochs调试命令行,等待我们输入调试命令,这里输入c继续执行
image.png
可以看到在虚拟机中我们的引导程序已成功运行,在屏幕上打印出了hello world。
image.png
网友评论