《Linux内核完全剖析》这本书在第4章给出了一个简单多任务内核示例程序,我们称之为Linux 0.00系统。本文介绍了一种把它跑起来的方法。
一、实验环境
Win7(64位)+Vmware+Ubuntu(64位)+Bochs
说明:我是win7的操作系统,在上面安装了虚拟机VMware,虚拟机上安装了Ubuntu 14.04(64位),Ubuntu上又安装了x86模拟器——Bochs(版本是2.4.5)
我准备在Ubuntu环境下编译源码,生成镜像文件;然后用Bochs来运行镜像文件,并观察结果。
二、源码下载
下载地址是
http://oldlinux.org/Linux.old/bochs/
要下载的文件是linux-0.00-050613.zip
下载此文件,并解压。解压后,其中一个文件是linux-0.00-rh9.tar.gz
,继续解压这个文件,得到文件夹linux-0.00-rh9
,此文件里面有3个文件,如下图:
boot.s
,采用as86
语言编写,是引导启动程序,用于把映像文件中的内核代码加载到内存某个指定位置处,并在设置好临时GDT表等信息后,把处理器设置成保护模式,然后跳转到内核代码处运行。
head.s
采用GNU as
汇编语言编写,实现了2个运行在特权及3上的任务,他们在时钟中断控制下相互切换运行,一个在屏幕上打印“A”,另一个在屏幕上打印“B”。
三、编译
(1)因为缺少as86编译器,所以需要安装bin86
sudo apt-get install bin86
(2)之后进行make, 但是有一大堆报错信息。
as86 -0 -a -o boot.o boot.s
ld86 -0 -s -o boot boot.o
as -o head.o head.s
head.s: Assembler messages:
head.s:59: Error: invalid instruction suffix forpushf'
popf’
head.s:61: Error: invalid instruction suffix for
head.s:68: Error: invalid instruction suffix forpush'
push’
head.s:69: Error: invalid instruction suffix for
head.s:70: Error: invalid instruction suffix forpushf'
push’
head.s:71: Error: invalid instruction suffix for
head.s:72: Error: invalid instruction suffix forpush'
push’
head.s:99: Error: invalid instruction suffix for
head.s:113: Error: invalid instruction suffix forpop'
push’
head.s:121: Error: operand type mismatch for
head.s:122: Error: invalid instruction suffix forpush'
pop’
head.s:127: Error: invalid instruction suffix for
head.s:128: Error: operand type mismatch forpop'
push’
head.s:134: Error: operand type mismatch for
head.s:135: Error: invalid instruction suffix forpush'
ljmp’
head.s:144: Error: unsupported instruction
head.s:147: Error: unsupported instructionljmp'
pop’
head.s:148: Error: invalid instruction suffix for
head.s:149: Error: operand type mismatch forpop'
push’
head.s:155: Error: operand type mismatch for
head.s:156: Error: invalid instruction suffix forpush'
push’
head.s:157: Error: invalid instruction suffix for
head.s:158: Error: invalid instruction suffix forpush'
push’
head.s:159: Error: invalid instruction suffix for
head.s:163: Error: invalid instruction suffix forpop'
pop’
head.s:164: Error: invalid instruction suffix for
head.s:165: Error: invalid instruction suffix forpop'
pop’
head.s:166: Error: invalid instruction suffix for
head.s:167: Error: operand type mismatch for `pop’
make: * [head.o] 错误 1
我们在head.s
文件开头加上一句.code32
,如下图所示,问题就解决了。
SCRN_SEL = 0x18
TSS0_SEL = 0x20
LDT0_SEL = 0x28
TSS1_SEL = 0X30
LDT1_SEL = 0x38
.code32 # 加上这句话
.global startup_32
.text
startup_32:
movl $0x10,%eax
mov %ax,%ds
(3)再次make,还会有错误:
ld -m elf_i386 -Ttext 0 -e startup_32 -s -x -M head.o -o system > System.map
ld: i386:x86-64 architecture of input file `head.o’ is incompatible with i386 output
make: * [system] 错误 1
我们修改Makefile文件,在AS=as
后面加上--32
,变成AS=as --32
.
make clean后重新make,就成功了。显示如下:
as86 -0 -a -o boot.o boot.s
ld86 -0 -s -o boot boot.o
as –32 -o head.o head.s
ld -m elf_i386 -Ttext 0 -e startup_32 -s -x -M head.o -o system > System.map
dd bs=32 if=boot of=Image skip=1
记录了16+0 的读入
记录了16+0 的写出
512字节(512 B)已复制,0.000836727 秒,612 kB/秒
objcopy -O binary system head
cat head >> Image
四、运行
首先写一个简单的Bochs配置文件,假设命名为bochsrc-0.00.bxrc
:
romimage: file=$BXSHARE/BIOS-bochs-latest
vgaromimage: file=$BXSHARE/VGABIOS-lgpl-latest
megs: 16
floppya: 1_44="Image", status=inserted
boot: a
log: bochsout.txt
把这个配置文件和编译出的镜像Image
放在同一目录下,然后运行命令
bochs -f bochsrc-0.00.bxrc
会看到
- Restore factory default configuration
- Read options from…
- Edit options
- Save options to…
- Restore the Bochs state from…
- Begin simulation
- Quit now
Please choose one: [6]
按回车
(0) [0xfffffff0] f000:fff0 (unk. ctxt): jmp far f000:e05b ; ea5be000f0
< bochs:1>
输入 c ,再回车,就可以看到运行结果了。