操作系统内核Hack:(一)实验环境搭建
操作系统内核Hack:(一)实验环境搭建
三四年前,心血来潮,入手《Orange’s:一个操作系统的实现》学习操作系统内核,还配套买了王爽的《汇编语言(第二版)》和《80X86汇编语言程序设计教程》,虽然Orang’s只看了不到三分之一,但当时还是很认真的,练习也做了不少。唯一遗憾的就是没有留下文字记录,导致现在忘得差不多一干二净了,后悔不已!如今想再捡起来,弥补当时的懒惰,虽然困难重重,但这么优秀的国产书怎么能看完就算了呢!而且当年还是在Windows下练习的,现在终于用上了原汁原味的Linux。再也不用在虚拟机鼓捣了,更应该重新品味一番!
1.开发工具安装
1.1 编译器:NASM和GCC
操作系统内核的引导部分是要用汇编语言来写的,但后面大部分都是用C语言,所以编译器方面我们需要NASM和GCC。
cdai@cdai ~ $ sudo apt-get install build-essential nasm
1.2 编辑器:SublimeText
Sublime Text提供了NASM插件,通过Package Control直接就能安装,很方便。虽然没有什么智能提示,但是有关键字染色还是不错的!
1.3 构建:Make
构建工具方面,当然是用GNU Make。具体内容先不做详述,等到需要时再系统学习一下。
1.4 模拟器:Bochs
Linux当然选择Bochs,此外还要安装bximage来生成映像文件。
cdai@cdai ~ $ sudo apt-get install bochs bximage
要注意的是,像上面那样通过apt安装的确方便,但是却没有调试功能,所以一般建议通过Bochs源码安装,打开调试功能。如果出现错误请参考第四部分“Bochs常见问题”和网上资料。
cdai@cdai ~/Software $ tar xzvf bochs-2.4.6.tar.gz
cdai@cdai ~/Software $ cd bochs-2.4.6
cdai@cdai ~/Software/bochs-2.4.6 $ ./configure --enable-debugger --enable-disasm
cdai@cdai ~/Software/bochs-2.4.6 $ make
cdai@cdai ~/Software/bochs-2.4.6 $ sudo make install
2.操作系统实验
2.1 Hello, OS!
这是我们的第一个汇编程序,只有20多行很短,但是“五脏俱全”。因为涉及到汇编语言的基础知识,所以先不做解释。待整理完汇编语言的一篇文章之后,再简单解释一下这个NASM汇编程序的含义。
org 07c00h
mov ax, cs
mov ds, ax
mov es, ax
call DispStr
jmp $
DispStr:
mov ax, BootMessage
mov bp, ax
mov cx, 16
mov ax, 01301h
mov bx, 000ch
mov dl, 0
int 10h
ret
BootMessage: db "Hello, OS world!"
times 510-($-$$) db 0
dw 0xaa55
2.2 编译汇编程序
用NASM编译我们写好的汇编代码。因为汇编语言是机器语言的“助记符”,与二进制代码几乎是一一对应的,所以可以看到编译出的二进制文件boot.bin正好就是我们想要的512字节。
cdai@cdai ~/Workspace/syspace/1-assembly/orange's $ nasm boot.asm -o boot.bin
cdai@cdai ~/Workspace/syspace/1-assembly/orange's $ ls -l
total 16
-rw-r--r-- 1 cdai cdai 266 Sep 12 09:58 boot.asm
-rw-r--r-- 1 cdai cdai 512 Sep 12 08:50 boot.bin
2.3 创建虚拟软盘
安装Bochs时我们还安装了一个叫bximage的软件,它可以帮我们生成一个虚拟软盘或硬盘。
cdai@cdai ~/Workspace/syspace/1-assembly/orange's $ bximage
========================================================================
bximage
Disk Image Creation Tool for Bochs
$Id: bximage.c,v 1.34 2009/04/14 09:45:22 sshwarts Exp $
========================================================================
Do you want to create a floppy disk image or a hard disk image?
Please type hd or fd. [hd] fd
Choose the size of floppy disk image to create, in megabytes.
Please type 0.16, 0.18, 0.32, 0.36, 0.72, 1.2, 1.44, 1.68, 1.72, or 2.88.
[1.44]
I will create a floppy image with
cyl=80
heads=2
sectors per track=18
total sectors=2880
total bytes=1474560
What should I name the image?
[a.img]
Writing: [] Done.
I wrote 1474560 bytes to a.img.
The following line should appear in your bochsrc:
floppya: image="a.img", status=inserted
于是在当前目录我们就得到了一个a.img,大小是1440K,可以将它想象成在Windows中经常碰到的ISO镜像文件。
cdai@cdai ~/Workspace/syspace/1-assembly/orange's $ ls -l --block-size=k
total 20K
-rw-r--r-- 1 cdai cdai 1440K Sep 12 09:57 a.img
-rw-r--r-- 1 cdai cdai 1K Sep 12 09:58 boot.asm
-rw-r--r-- 1 cdai cdai 1K Sep 12 08:50 boot.bin
2.4 烧录程序
有了虚拟软盘,我们就可以将刚才编译好的汇编程序“烧录”到软盘中了。注意:一定要加conv=notrunc参数,因为a.img比boot.bin大得多,如果不加这个参数则a.img会按照boot.bin的大小被截断。
cdai@cdai ~/Workspace/syspace/1-assembly/orange's $ dd if=boot.bin of=a.img bs=512 count=1 conv=notrunc
1+0 records in
1+0 records out
512 bytes (512 B) copied, 0.000741281 s, 691 kB/s
2.5 配置Bochs
现在还不能急着启动我们的操作系统,因为我们还没告诉Bochs我们的虚拟机是什么样子,比如内存多大、软盘/硬盘映像文件在哪等等。所以我们需要在当前文件夹下创建一个bochsrc配置文件。
###########################################################
# Configuration file for Bochs
###########################################################
# how much memory the emulated machine will have
megs: 32
# filename of ROM images
romimage: /usr/share/bochs/BIOS-bochs-latest
vgaromimage: /usr/share/vgabios/vgabios.bin
# what disk images will be used
floppya: 1_44=a.img, status=inserted
# choose the boot disk
boot: floppy
# where do we send log messages
log: bochsout.txt
# disable the mouse
mouse: enabled=0
# enable key mapping, using US layout as default
keyboard_mapping: enabled=1, map=/usr/share/bochs/keymaps/x11-pc-us.map
2.6 启动Bochs
一切准备就绪,执行bochs -f bochsrc就可以启动我们的操作系统了!如果发现Bochs出错崩溃了,看一下提示的错误信息,参照本文第四部分的“Bochs常见问题”寻找解决办法。如果没有包含在其中,就上网搜索一下,关于Bochs常见问题的资料还是挺多的。
具有调试功能的Bochs启动时不会立即执行我们的操作系统,而是出现选项,给了我们加断点和调试的机会。这里我们直接选6开始模拟,然后输出”c”回车继续执行。
========================================================================
Bochs x86 Emulator 2.4.6
Build from CVS snapshot, on February 22, 2011
Compiled at Sep 12 2015, 12:05:24
========================================================================
00000000000i[ ] reading configuration from bochsrc
------------------------------
Bochs Configuration: Main Menu
------------------------------
This is the Bochs Configuration Interface, where you can describe the
machine that you want to simulate. Bochs has already searched for a
configuration file (typically called bochsrc.txt) and loaded it if it
could be found. When you are satisfied with the configuration, go
ahead and start the simulation.
You can also start bochs with the -q option to skip these menus.
1. Restore factory default configuration
2. Read options from...
3. Edit options
4. Save options to...
5. Restore the Bochs state from...
6. Begin simulation
7. Quit now
Please choose one: [6]
00000000000i[ ] installing x module as the Bochs GUI
00000000000i[ ] using log file bochsout.txt
Next at t=0
(0) [0x00000000fffffff0] f000:fff0 (unk. ctxt): jmp far f000:e05b ; ea5be000f0
<bochs:1> c
最终我们能看到下面这样的画面:
Hello, OS world!�ios (PCI) current-cvs 19 Sep 2012
This VGA/VBE Bios is released under the GNU LGPL
Please visit :
. http://bochs.sourceforge.net
. http://www.nongnu.org/vgabios
Bochs VBE Display Adapter enabled
Bochs BIOS - build: 06/08/13
$Revision: 1.257 $ $Date: 2011/01/26 09:52:02 $
Options: apmbios pcibios pnpbios eltorito rombios32
Press F12 for boot menu.
Booting from Floppy...
3.实验环境升级
通过上面的例子,可以总结一下未来我们开发的一般步骤:
- 用Sublime Text编辑代码
- 用Make调用GCC/NASM编译并写入映像文件
- 启动Bochs运行和调试
但这种方式存在一个潜在的问题,就是引导扇区空间有限,只有512字节。随着我们的程序越来越大,很快512字节就会不够用了。写一个能够加载我们程序的引导扇区可以解决这个问题,但现阶段来说有点难。于是我们可以求助于现成的操作系统内核,如DOS,加载我们的程序。而且很多教程也都是基于DOS来讲解的。
3.1 可引导FreeDos
下载FreeDos镜像,并修改bochsrc配置文件中的软驱设置。注意:Sourceforge已基本瘫痪,我是从CSDN用积分下载下来的。而且我从freedos官网上下的freedos可引导软盘版也不好用,所以还是乖乖从Bochs上下载了。
floppya: 1_44=freedos.img, status=inserted
floppyb: 1_44=a.img, status=inserted
3.2 用FreeDos格式化a.img
启动Bochs,格式化B盘,清除掉之前写入到a.img的内容。
Type INSTALL to start the FreeDOS installation
If you need to create a partition on your hard disk for FreeDOS, you
will need to do that yourself. Use FDISK to create a partition, and
use FORMAT to make the partition writable by FreeDOS. You can run
both programs from this Install Boot Floppy.
_________________________________________________________________________
A:\>format B:
Reading boot sector...
Cylinder: 0 Head: 0
Saving UNFORMAT information...
Cylinder: 77 Head: 1
Creating file system...
Cylinder: 0 Head: 0
Format operation complete.
3.3 重编译boot.asm
首先,修改boot.asm文件第一行的07c00h,改为0100h。因为DOS与Linux的引导扇区加载到内存中的位置不同。改好后重新用NASM编译,后缀名是COM。
cdai@cdai ~/Workspace/syspace/1-assembly/orange's/ch03 $ nasm boot.asm -o boot.com
3.4 拷贝程序到软盘映像
4)将编译出的COM文件复制到软盘映像中。如果没有/mnt/floppy文件夹就用sudo创建一个,没有什么特殊的。有一点要特别注意:一定要停掉Bochs,否则a.img会损坏。
cdai@cdai ~/Workspace/syspace/1-assembly/orange's/ch03 $ sudo mkdir /mnt/floppy
cdai@cdai ~/Workspace/syspace/1-assembly/orange's/ch03 $ sudo mount -o loop a.img /mnt/floppy
cdai@cdai ~/Workspace/syspace/1-assembly/orange's/ch03 $ sudo cp boot.com /mnt/floppy/
cdai@cdai ~/Workspace/syspace/1-assembly/orange's/ch03 $ sudo umount /mnt/floppy
3.5 通过FreeDos运行
重新启动Bochs,执行软驱B中的boot.com就能在屏幕第一行看到红色的”Hello, OS world!”了!
Hello, OS world!�________________________________________________________
WELCOME TO THE FREEDOS BETA4 RELEASE!
Type INSTALL to start the FreeDOS installation
If you need to create a partition on your hard disk for FreeDOS, you
will need to do that yourself. Use FDISK to create a partition, and
use FORMAT to make the partition writable by FreeDOS. You can run
both programs from this Install Boot Floppy.
_________________________________________________________________________
A:\>dir B:
Volume in drive B has no label
Directory of B:\*.*
BOOT COM 512 09-13-115 11:37a
1 file 512 bytes
0 dirs 1,457,664 bytes free
A:\>B:\boot.com
4.Bochs常见问题
4.1 [安装] error adding symbols: DSO missing from command line
修改Makefile的LIBS中加上”-lpthread”。
4.2 [运行] romimage directive malformed
romimage语法错误,例如没写”file=”。
4.3 [运行] dlopen failed for module ‘x’
除了bochs,还要安装bochs-x。
4.4 [运行] bochs-bin: symbol lookup error: /usr/lib/bochs/plugins/libbx_x.so: undefined symbol: XpmCreatePixmapFromData
我是Linux Mint系统(Ubuntu),网上资料说还要安装bochs-sdl,并且在bochsrc配置文件的开头加上”display_library: sdl”。
4.5 [运行] unknown host key name ‘XK_0’ (wrong keymap ?)
注释掉#keyboard_mapping: enabled=1, map=/usr/share/bochs/keymaps/x11-pc-us.map
4.6 我最终的环境和配置
apt安装Bochs时需要设置”display_library: sdl”并注释掉”keyboard_mapping”,但源码安装却没有碰到类似问题。
cdai@cdai ~ $ sudo apt-get install bximage bochs bochs-x bochs-sdl
cdai@cdai ~ $ cat bochsrc
###########################################################
# Configuration file for Bochs
###########################################################
#display_library: sdl
# how much memory the emulated machine will have
megs: 32
# filename of ROM images
romimage: file=/usr/share/bochs/BIOS-bochs-latest
vgaromimage: file=/usr/share/vgabios/vgabios.bin
# what disk images will be used
floppya: 1_44=a.img, status=inserted
# choose the boot disk
boot: floppy
# where do we send log messages
log: bochsout.txt
# disable the mouse
mouse: enabled=0
# enable key mapping, using US layout as default
keyboard_mapping: enabled=1, map=/usr/share/bochs/keymaps/x11-pc-us.map