Jasper Ji

开口不在舌头上

0%

如何写一个操作系统

缘起

如何写一个操作系统,大概刚开始写程序一年多,我就思考这个问题,其实那些年很多想法都不错,至少感想,可惜能力跟不上想法。当时也不知道什么渠道看到的,2010年末的时候从亚马逊中国买了一本《Orange’S 一个操作系统实现》,那会主要应该是汇编语言的问题,没有跨过第三章,为此买了本王爽的《汇编语言·第三版》,依旧记得去乾陵一日游大巴上,我努力的读着,可惜作为一个刚接触脚本语言的人来说,汇编语言太难了,中间需要跨越的东西太多了。后来工作瞎忙之类,也就没有再继续,也不知道什么时候,我居然把这两本书都给卖了。

今年突然间又想,我应该尝试写一个简单的操作系统,多年的工作以及自学,使得我对编程有了一个相对完整的认识(后来证实实际我根本不懂真的如何用汇编编程,只是文字上的一知半解),这个想法似乎不像当年那么不靠谱。但该如何下手呢?刚开始我只想能跑一个Hello wrold的例子也可以,网上找了下最多的居然是我当年卖掉的那本《Orange’S 一个操作系统实现》书中的例子,书已经绝版了,于是就从孔夫子旧书网上买了一本,又买了王爽的《汇编语言》,现在已经升级到第四版了。

最简单的OS

来自《Orange’S 一个操作系统实现》一书。

运行环境:Ubuntu 20.04.2 LTS

boot.asm代码

	org 07c00h			; 告诉编译器程序加载到7c00处
	mov ax, cs
	mov ds, ax
	mov es, ax
	call DispStr			; 调用显示字符串例程
	jmp $			; 无限循环
DispStr:
	mov ax, BootMessage
	mov bp, ax			; ES:BP = 串地址
	mov cx, 16			; CX = 串长度
	mov ax, 01301h		; AH = 13,  AL = 01h
	mov bx, 000ch		; 页号为0(BH = 0) 黑底红字(BL = 0Ch,高亮)
	mov dl, 0
	int 10h			; 10h 号中断
	ret
BootMessage:		db	"Hello, OS world!"
times 	510-($-$$)	db	0	; 填充剩下的空间,使生成的二进制代码恰好为512字节
dw 	0xaa55				; 结束标志

《Orange’S 一个操作系统实现》一书使用NASM汇编,王爽老师的《汇编语言》是MASM,但二者差别不大。专门讲NASM,有一本2003年中国铁道出版社出版的《汇编语言程序设计》,作者是林邦杰、陈明,此书是引进的台湾版,不过因为时间久远,已经买不到纸质书籍了,网上电子版,但找不到光盘内容,书中有些作者封装的调用都在光盘里面,所以不是很推荐。

NSAM版本:2.14.02

nasm boot.asm -o boot.bin # 编译

编译完成后,我们需要将boot.bin拷贝到软盘里面。书中使用的bximage来创建软盘。

bximage # 执行完成后会生成一个a.img的文件

拷贝文件到软盘

dd if=boot.bin of=a.img bs=512 count=1 conv=notrunc

书中使用Bochs模拟器,需要在当前目录下创建bochsrc文本文件,内容如下:

megs:32

romimage:file=$BXSHARE/BIOS-bochs-latest
vgaromimage:file=$BXSHARE/VGABIOS-lgpl-latest

floppya: 1_44=a.img, status=inserted


boot:floppy

log:bochsout.txt

mouse:enabled=0

#keyboard: keymap=$BXSHARE/keymaps/x11-pc-de.map

display_library:sdl2

网上书中光盘里面的bochsrc配置文件运行有问题,我这个是修改过的,启动Bochs

bochs -f bochsrc # 或者bochs,会直接在当前目录下寻找配置

这里需要注意的是启动后,需要按c后才在屏幕上显示Hello, OS world!的界面。 关于Bochs本身确实有很多需要学习的地方。

注意事项

times 	510-($-$$)	db	0	; 填充剩下的空间,使生成的二进制代码恰好为512字节
dw 	0xaa55				; 结束标志

特意说下这段代码,代码结尾必须为aa55,这个是结束标志。另外代码必须小于512kb的大小,后来我因为代码的问题,填充剩余空间出现了问题,导致大小超过了512,Bochs运行时提示Message: No bootable device. bochs,因为只会在第一扇区寻找数据,而结束标志实际上已经不在第一扇区了。

汇编和CPU

似乎可以继续一路向前了,可惜看了头三章后,我发现了些问题。首先我对NASM汇编的东西几乎是一片空白,书的前几章几乎离不开汇编语言了,而看的非常吃力。另一个是我对PC的体系缺乏细节的了解,虽然之前也有了解但实操的过程中遇到的问题更具体。

NASM的书籍不多,《汇编语言.基于Linux环境.第三版》是一本从体系的角度来讲解NASM的书籍,一方面学习了NASM,也让我重新思考从8086到80386的一些变化,好几个点很有启发。王爽老师的《汇编语言》,也是一本非常不错的参考书,汇编语言在形式上与高级语言还是有着巨大差异,一开始我把心思放在那些寄存器之类上了,而忽略了一个编程语言应该是能够写点东西出来这事上。《汇编语言》这书很好的带我进入如何写点东西的正轨上。

8086方面的书籍,8086总设计师莫尔斯写的《8086初阶-体系结构、系统设计和程序设计入门》。王爽老师《汇编语言》也主要是讲8086的汇编的。80386的书籍不多,80386的设计师写的《Programing the 80386》一书,非常不错。中文版是93年出版的《保护方式下80386及其编程》一书,虽然没有备注是翻译,但我跟英文版对照后,确认就是翻译自《Programing the 80386》,主要是学习保护模式。

这里需要注意的是实模式与保护模式的差别,很多时候一开始如果研究的是8086的,往往需要转换下思维,最好的书籍依旧是《保护方式下80386及其编程》一书,于渊的《Orange’S 一个操作系统实现》细节上还是有点模糊。

总结

最终操作系统并没有完整的实验下去,主要是因为最难的部分也是最容易忽略的如何在特定架构上如何开始,把这一步迈过去后,基本上跟大多操作系统讲的差不多了,主要部分就是使用C语言来实现。

虽然实验已经过去了几个月了,最近一直在看Java并发的东西,发现实际写过点操作系统还是很有帮助的,比如更能从CPU的角度来思考。