(Windows用户可以选择在虚拟机中安装Ubuntu)Bochs像上帝一样随时可以让时间停止钻到计算机内部查看这个虚拟电脑的一切信息这正是开发操作系统所需要的 https://blog.csdn.net/weixin_51760563/article/details/119713850?spm=1001.2101.3001.6650.13&utm_medium=distribute.pc_relevant.none-task-blog-2%7Edefault%7EOPENSEARCH%7ERate-13-119713850-blog-128755066.235%5Ev28%5Epc_relevant_default_base1&depth_1-utm_source=distribute.pc_relevant.none-task-blog-2%7Edefault%7EOPENSEARCH%7ERate-13-119713850-blog-128755066.235%5Ev28%5Epc_relevant_default_base1&utm_relevant_index=14# 本系列文章将一步步实现一个简单的操作系统。实验环境是在Linux系统下通过Bochs虚拟机运行我们自己写的操作系统。 一、实验环境搭建1. Ubuntu的安装,Windows用户可以选择在虚拟机中安装Ubuntu,具体安装教程可自行搜索。2. Bochs虚拟机的安装在学习编写操作系统的过程中,我们需要一个虚拟机来模拟出一个虚拟的计算机硬件环境,比如cpu、内存、硬盘等,并且能够运行并且调试我们写的代码。Bochs很好的提供了以上所有功能,在它面前我们就像上帝一样随时可以让时间停止,”钻“到计算机内部,查看这个虚拟电脑的一切信息,这正是开发操作系统所需要的。 Ubuntu下我们可以直接运行以下命令以源码方式安装Bochs(注意我们之所以选择以源码方式安装,是因为通过apt install安装的Bochs是没有调试功能的) $ sudo apt update $ sudo apt install build-essential libx11-dev xorg-dev libgtk2.0-dev $ wget https:///projects/bochs/files/bochs/2.7/bochs-2.7.tar.gz $ tar zxvf bochs-2.7.tar.gz $ cd bochs-2.7/ $ ./configure --enable-debugger --enable-disasm --enable-debugger-gui $ make $ sudo make install
到此实验环境搭建完毕。 二、简单的引导扇区汇编代码先简单讲一下计算机的启动流程,详细启动过程可参考我的另一篇博客 操作系统启动过程 按下开机键后,计算机首先会运行BIOS中的代码,BIOS在进行硬件检查和初始化后,会按照设置好的启动顺序(我们在使用U盘安装系统时,经常要进入BIOS设置这个启动顺序),依次寻找启动设备(比如硬盘、U盘等)。然后将第一个可用的启动设备的第一个扇区载入内存0x7c00处,并把执行权限交给它。 启动设备的第一个扇区我们称之为引导扇区(MBR),共512个字节,必须以数值0x55及0xaa结尾。包括三部分内容:引导加载程序(Boot Loader)(前446个字节,如GRUB等)、磁盘分区表(DPT,Disk Partition Table)、分区有效性标志(55AA)。其中的引导加载程序负责加载启动硬盘分区中的操作系统。 在BIOS向引导程序移交执行权之前,BIOS会对处理器进行初始化,这其中就包括处理器的代码段寄存器CS和指令指针寄存器IP。当BIOS跳转至引导程序时,CS和IP的值分别为0x0000和0x7c00。此时的处理器处于实模式下,物理地址必须经过CS寄存器和IP寄存器转换才能得到。转换公式为:物理地址=CS<<4+IP,也就是物理地址0x7c00处。 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后,物理内存的布局如下: 本程序就是调用0x10号中断,在屏幕上打印字符串。在调用0x10号中断处理程序往显示器的屏幕上打印字符串时,所有的参数都是通过cpu中的寄存器传递的,各参数的含义如下:
代码解析: 第1行,告诉编译器程序加载到内存的0x7c00处。 第2~4行,统一数据段寄存器DS和附加段寄存器ES的值和代码段寄存器CS一致,即不论数据段还是代码段,段起始地址都是0x7c00。 第5~6行,将字符串"Hello, world!"的首地址传递给寄存器bp。注意任何不被方括号 第7行,将字符串的长度传递给寄存器cx 第8~11行,字符串属性设置 第12行,调用0x10号中断处理程序,在屏幕上显示字符串 第13行,使cpu进入死循环
第15、17行,分别以字节和字的形式存放的数据 第16行,表示将0这个字节重复510-($-$$)遍,也就是在剩下的空间不停填充0,直到第510个字节为止。这样加上结束标志0xaa55占用的两个字节,恰好是512个字节。 在运行代码之前我们需要将其转换成计算机能读懂的机器指令形式,这就需要编译器。我们编译c代码使用GCC,编译汇编程序使用nasm编译器。 把上面的代码保存成 $ nasm boot.asm -o boot.bin 三、虚拟硬盘的制作下面我们将制作一个虚拟硬盘并将已经生成的可执行文件boot.bin放到虚拟硬盘的第一个磁盘块(引导扇区MBR)中。Bochs虚拟机将使用这块“硬盘”引导启动。 首先选择合适的地方创建一个工程目录 $ mkdir projectest $ cd projectest 将可执行文件boot.bin拷贝到该工程目录中 然后在本层目录中创建一个大小为1MB的硬盘镜像文件b.img的命令如下: $ dd if=/dev/zero of=b.img bs=512 count=2048 dd是文件拷贝命令,其中:
由bs和count参数可知,硬盘镜像文件的大小为:2048*512B=1MB,硬盘镜像文件制作好后,将可执行文件boot.bin拷贝到硬盘镜像文件b.img(硬盘)的引导扇区的命令如下: $ dd if=boot.bin of=b.img bs=512 seek=0 conv=notrunc 其中:
这样一个写入了引导程序的“硬盘”就制作好了。 四、Bochs的使用1. 启动Bochs"硬盘”制作好后,要想启动bochs还需要一个配置文件——bochsrc.bxrc。为什么需要配置文件呢?因为你需要告诉bochs你希望的虚拟机是什么样的,比如,内存多大,使用哪个硬盘启动等等。在下载bochs的源码包中有一个 下面是本实验用到的bochs配置文件代码 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 其中:
将上面的代码保存为bochsrc.bxrc,也存到工程目录下。 现在一切准备就绪,启动bochs的命令如下: $ bochs -q -f bochsrc.bxrc 其中:
运行bochs后会在终端出现bochs调试命令行,等待我们输入调试命令,这里输入 2. Bochs调试
|
|