《30天自制操作系统》——虚拟机使用

《30天自制操作系统》是一本学习操作系统的好教材,它教我们怎么从建立引导区开始,从零实现一个操作系统。但是,实现书中例子的时候,我们需要不断将我们写好的操作系统代码写入软盘并且还要不断重启电脑来试验我们的代码,大家一定感到很头疼吧。

与其不停的重启,不如使用模拟器,向大家推荐一款模拟器qemu,它是由Fabrice Bellard编写,功能非常强大。那么下面我就来教大家使用qemu运行书中自制操作系统的方法吧。

一、安装qemu

我使用的是苹果笔记本,苹果有一个非常好用的程序管理工具叫brew,安装brew需要在终端中输入

sudo ruby -e "$(curl -fsSLhttps://raw.github.com/mxcl/homebrew/go)"

或者

curl -LsSf http://github.com/mxcl/homebrew/tarball/master | sudo tar xvz -C/usr/local --strip 1

然后使用brew安装qemu

sudo brew install qemu --env=std --use-gcc

如果成功,就会在/usr/local/bin/中创建出许多以qemu开头的文件,其中qemu-img和qemu-system-i386是对我们来讲最重要的两个文件。

二、自制操作系统

为了方便读者,我把书中前三天内容的精髓汇总在一个程序中,其中包含FAT软盘格式、从软盘中读扇区和在屏幕中输出文字。程序如下:

; 程序名称ipl.nas

; hello-os

; TAB=8

ORG    0x7C00     ; 程序加载到内存地址0x7C00后

; 以下的记述用于标准FAT12格式的软盘

start:

JMP    entry

DB    "HELLOIPL"    ; 启动区名称(8字节)

DW    512        ; 扇区大小(512字节)

DB    1        ; 簇大小(1扇区)

DW    1        ; FAT起始位置

DB    2        ; FAT个数

DW    224        ; 根目录大小(224项)

DW    2880        ; 磁盘大小(2880扇区)

DB    0xf0        ; 磁盘种类

DW    9        ; FAT长度

DW    18        ; 每个磁道扇区数

DW    2        ; 磁头数

DD    0        ; 不使用分区

DD    2880        ; 重写一次磁盘大小

DB    0,0,0x29    ; 意义不明

DD    0xffffffff    ; 可能是卷标号码

DB    "HELLO-OS   "    ; 磁盘名称(11字节)

DB    "FAT12   "    ; 格式名称(8字节)

RESB    18        ; 空出18字节

entry:

MOV    AX,0        ; 初始化寄存器

MOV    SS,AX

MOV    SP,0x7c00

MOV    DS,AX

MOV    ES,AX

; 读磁盘

CYLS    EQU    10

MOV    AX,0x0820

MOV    ES,AX

MOV    CH,0        ; 柱面0

MOV    DH,0        ; 磁头0

MOV    CL,2        ; 扇区2

readloop:

MOV    SI,0        ; 记录失败次数

retry:

MOV    AH,0x02        ; 读盘

MOV    AL,1        ; 1个扇区

MOV    BX,0

MOV    DL,0x00        ; A驱动器

INT    0x13        ; 调用磁盘BIOS

JNC    next        ; 没出错跳转fin

ADD    SI,1

CMP    SI,5        ; 比较SI与5

JAE    error        ; SI >= 5时,跳转到error

MOV    AH,0x00

MOV    DL,0x00

INT    0x13        ; 重置驱动器

JMP    retry

next:

MOV    AX,ES

ADD    AX,0x0020    ; 把内存地址后移0x200

MOV    ES,AX        ; 因为没有ADD ES,0x20

ADD    CL,1

CMP    CL,18

JBE    readloop    ; 如果CL <= 18,跳转至readloop

MOV    CL,1

ADD    DH,1        ; 读磁盘另一面

CMP    DH,2

JB    readloop

MOV    DH,0

ADD    CH,1

CMP    CH,CYLS        ; 读CYLS个柱面

JB    readloop

; 输出helloworld

MOV    SI,msg

putloop:

MOV    AL,[SI]

ADD    SI,1        ; 给SI加1

CMP    AL,0

JE    fin

MOV    AH,0x0e        ; 显示一个文字

MOV    BX,15        ; 指定字符颜色

INT    0x10        ; 调用显卡BIOS

JMP    putloop

fin:

HLT

JMP    fin

error:

MOV    SI,errmsg

errloop:

MOV    AL,[SI]

ADD    SI,1        ; 给SI加1

CMP    AL,0

JE    fin

MOV    AH,0x0e        ; 显示一个文字

MOV    BX,15        ; 指定字符颜色

INT    0x10        ; 调用显卡BIOS

JMP    errloop

msg:

DB    0x0a, 0x0a    ; 换行2次

DB    "hello, world"

DB    0x0a        ; 换行

DB    0

errmsg:

DB    0x0a, 0x0a    ; 换行2次

DB    "disk error"

DB    0x0a        ; 换行

DB    0

marker:

RESB    0x1fe-(marker-start)

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

看过前三章的读者理解上面的程序应该不难。

另外fat启动扇区格式要安照http://www.ntfs.com/fat-partition-sector.htm,所以假如你发现在汇编后的机器码中由于JMP entry的机器代码长度(需占前三个字节)有变导致与fat格式不符合(需从第四字节即地址为0x03开始),那么你要回到程序中在JMP
entry后使用DB手工添加占位字节。

三、汇编

我使用mac自带的nasm汇编器。查看能过汇编成哪些类型的机器代码可以输入

nasm -hf

我们需要把代码汇编成bin格式,这也是nasm的默认格式。因为在我们的代码中全部都是intel的16位汇编指令,而mac的cpu使用的也是intel芯片,所以汇编后的代码x86和x64都可以执行。

nasm -f bin ipl.nas -o ipl.bin -l ipl.lst

-f后面跟输出格式,-o后面是输出文件,-l后面是list文件,其内容是汇编语言和机器语言的对照表。

你可以用xxd查看二进制文件的内容:

xxd ipl.bin | less

以及:

file ipl.bin # 显示为:DOS floppy 1440k, x86 hard disk boot sector

qemu-img info ipl.bin # 其对应的qemu镜像类型为raw

四、虚拟机

在终端中输入:

qemu-system-i386 -fda ipl.bin -boot a

其中

-fda/-fdb 指定软盘

-hda/-hdb/-hdc/-hdd 指定硬盘

-cdrom 指定光盘

-boot 指定从哪个设备启动

a(软盘),c(硬盘),d(光盘),n(网络)

因为ipl.bin是软盘格式且为启动盘,我们使用-fda ipl.bin -boot a

运行结果如下:

五、制作u盘磁盘镜像

我们当然也能把ipl.bin写入u盘然后从u盘启动,此时u盘其实就相当于一个软盘。

当插入u盘后,我的/dev中多了一个disk2。

sudo diskutil unmountDisk /dev/disk2

sudo dd if=ipl.bin of=/dev/disk2 # 将软盘镜像写入u盘中

写好后重新插拔一次u盘

sudo diskutil unmountDisk /dev/disk2

sudo qemu-system-i386 -fda /dev/disk2 -boot a

运行结果同上。

时间: 2024-11-07 10:26:29

《30天自制操作系统》——虚拟机使用的相关文章

《30天自制操作系统》读书笔记(2)hello, world

让系统跑起来 要写一个操作系统,我们首先要有一个储存系统的介质,原版书似乎是06年出版的,可惜那时候没有电脑,没想到作者用的还是软盘,现在的电脑谁有软驱?不得已我使用一张128M的SD卡来代替,而事实上你用的是U盘还是软盘对我们的操作系统没有影响,缺点是你的U盘刷入系统后容量只能是1440 MB,即当年流行的3.5英寸软盘的大小,当然不用担心,再格式化一次(用DiskGeniu),就可以恢复. 我做事情的话,总是怕自己的努力的结果白费了,害怕辛辛苦苦看完这本书但是发现做出来的东西现在根本没法用,

《30天自制操作系统》笔记(01)——hello bitzhuwei’s OS!

<30天自制操作系统>笔记(01)--hello bitzhuwei's OS! 最初的OS代码 1 ; hello-os 2 ; TAB=4 3 4 ORG 0x7c00 ; 指明程序的装载地址 5 6 ; 以下这段是标准FAT32格式软盘专用的代码 7 8 JMP entry 9 DB 0x90 10 DB "HELLOIPL" ; freeparam 启动区的名称可以是任意的字符串(8字节) 11 DW 512 ; 每个扇区(sector)的大小(必须为512字节)

《30天自制操作系统》笔记(03)——使用Vmware

<30天自制操作系统>笔记(03)--使用Vmware 进度回顾 在上一篇,实现了用IPL加载OS程序到内存,然后JMP到OS程序这一功能:并且总结出下一步的OS开发结构.但是遇到了真机测试和U盘启动的一些问题.本篇就来解决之. 遇到的问题 物理机测试 简单来说,把软盘(U盘)做成启动盘后,自然想要用来启动物理机器.毕竟这才是真正的测试.(用QEMU总没多大的成就感)但物理机测试的麻烦在于太慢了,每次都要关掉Windows,重启,测试,然后再重启Windows.而且还没办法截图. 而用Vmwa

《30天自制操作系统》笔记(02)——导入C语言

<30天自制操作系统>笔记(02)--导入C语言 进度回顾 在上一篇,记录了计算机开机时加载IPL程序(initial program loader,一个nas汇编程序)的情况,包括IPL代码(helloos.nas).编译生成helloos.img文件.用虚拟机QEMU加载helloos.img.制作U盘启动盘和用物理机加载helloos.img. 计算机启动时会自动加载和执行IPL程序,但IPL程序只能占用512字节.若直接用IPL写OS,空间不够用.所以IPL程序一般用于将真正的OS程序

《30天自制操作系统》读书笔记(1)读前感

做一个自己的操作系统, 在我看来一直是不可以思议的,而且奇妙的,像是吉他手亲手打造一把自己的吉他? 似乎这个比喻不太恰当, 但是,感觉是一样的. <30天自制操作系统> 为日本的川和秀实先生所著, 有人说他是 "<XX天学会XXX>之类的书中为数不多的几本好书之一." 这本书的优点非常明显,通俗生趣,甚至于有点啰嗦:而且作者无私地提供了源代码而且允许你以任何方式使用,也提供了编译的所有工具,所有东西都是"开箱即用",不容易出问题. 作为后生我

《30天自制操作系统》笔记(13)——总结

<30天自制操作系统>笔记(13)——总结 进度回顾 上一篇介绍了操作系统实现多任务的方法.操作系统利用CPU的far模式的JMP指令.寄存器TR.GDT.TSS和PIT中断这些功能实现了多任务,可见CPU在设计时就考虑到了计算机要具有多任务处理的能力.也就是说,CPU.PIC等硬件支持什么功能,操作系统才能实现什么功能. 至此全书已经读了一半.我发现后半部分读不下去,也没必要再读了.本篇就对所有的笔记做一总结,至此<30天自制操作系统>这本书就暂且不读了. 所学所感 我们可以把C

《30天自制操作系统》学习笔记-第1天

为了加深对操作系统的理解,我决定照着<30天自制操作系统>这本书实践一下.项目的github链接是https://github.com/YatesXu/YatesOSASK/ 关于十六进制编辑器 第一个问题就是书中给的十六进制编辑器是日文的,在我的电脑上打开之后是一片乱码,于是我比较之后选用了这个十六进制编辑器wxMEdit,链接是https://wxmedit.github.io/. 另外,visual studio也可以,但是express版不能用,所以还是选用免费开源的软件吧(笑) (伪

《30天自制操作系统》——从引导区到磁盘

上一篇讲了如何使用虚拟机运行我们写好的操作系统,但上一篇的操作系统其实仅仅存在于引导扇区中,接下来我们将看到程序如何从引导扇区跳到其他位置. 引导区内容的装载位置为0x00007c00-0x00007dff,规定该位置的人是当年开发IBM-PC的工程师们.0x7e00-0x9fbff是操作系统可以随便使用的内存位置.按照<30天自制操作系统>中所讲,我们把前10个磁道的数据都读入内存,内存位置从0x8000开始.因此磁盘镜像文件中,位于地址x的字符加载到内存的位置就为0x8000+x.现在设我

30天自制操作系统之第12天 定时器

定时器的中断处理程序要保证高效率,需要进行一些优化,这里介绍优化的方法.对于一个操作系统来说,会有多个定时器,假设该操作系统维护了500个定时器,当每一次定时中断发生时(这里我们设定1秒发生100次中断),调用中断处理程序,中断处理程序会对这500个定时器进行if判断,看哪些正在被使用,这样1秒内,就会有500X100=10000次if判断,而中断处理程序最讲究节省时间.实际上,我们不必每发生一次定时中断就去对这500个定时器进行判断.因为假设我们使用了500个定时器中的10个,而10个定时器中