[原创]操作系统编写详解
2010年08月09日
前一篇文章中我们学习了写引导程序,可是,引导程序大小不能超过512B,将运行代码写到引导程序里并不是不行,但是大小限制会让你的操作系统异常的"精简"
所以一般的操作系统(包括Linux)都是使用一种叫二次加载的方法,也就是写一个及其简单的Boot引导程序,它只做两件事:一是初始化段寄存器(mov ds,ax....),二是从软盘第二扇区读入真正的内核加载到内存指定位置并用1个Jmp跳转到指定位置并执行内核
到回来看看Linux,Linux0.11的Boot文件夹里有Boot.s与Head.s,boot.s的作用就是引导,并跳转至Head,Head才开始进入保护模式,最后跳转至Main.c(init/main.c,当然以编译为.o,并以链接到Tool/System)的,下面是一部分的Linux0.11 Makefile代码
Image: boot/boot tools/system tools/build
tools/build boot/boot tools/system > Image
sync
boot/head.o: boot/head.s
tools/system:boot/head.o init/main.o \
$(ARCHIVES) $(LIBS)
$(LD) $(LDFLAGS) boot/head.o init/main.o \
$(ARCHIVES) \
$(LIBS) \
-o tools/system > System.map
boot/boot:boot/boot.s tools/system
(echo -n "SYSSIZE = (";ls -l tools/system | grep system \
| cut -c25-31 | tr '\012' ' '; echo "+ 15 ) / 16") > tmp.s
cat boot/boot.s >> tmp.s
$(AS86) -o boot/boot.o tmp.s
rm -f tmp.s
$(LD86) -s -o boot/boot boot/boot.o
可以看到head.o与main.o被链接到tool/system,而boot只是负责引导,经过一连的Jmp之后,main函数开始初始化并运行Kernel,这就是二次加载
考虑下面的程序代码
;boot.asm
[ORG 0]
jmp 07c0h:start
start:
;设置段寄存器
mov ax,cs
mov ds,ax
mov es,ax
reset: ;重置软盘驱动器
mov ax,0
mov dl,0 ;Driver=0(=A)
int 31h
jc reset ;if error reset again
read:
mov ax,1000h ;ES:BX=1000:0000
mov es,ax
mov bx,0
mov ah,2 ;读取磁盘数据到地址ES:BX
mov al,5 ;读取5个扇区
mov ch,0 ;柱面0
mov cl,2 ;第二扇区,即为读入文件所在扇区
mov dh,0 ;Head=0
mov dl,0 ;Driver=0
int 13h ;开始读
jc read ;if error try again
jmp 1000h:0000 ;跳转到装载的程序处开始执行
times 510-($-$$) db 0
dw 0AA55h ;结束标志
;Kernel.asm
[ORG 0]
jmp start2
msg db 'Here is Xue s Operating System!OK,Here we go',$0 ;打印字符串定义
start2:
;设置段寄存器
mov ax,cs
mov ds,ax
mov es,ax
mov si,msg
print:
lodsb
cmp al,0 ;al为0?
je hang ;if al=0 then 挂起
mov ah,0Eh ;打印
mov bx,7
int 10h
jmp print ;打印下一字符
hang:
jmp hang ;挂起,即无限循环
times 510-($-$$) db 0
dw 0AA55h ;结束标志
编译
nasm boot.asm -o boot.bin
nasm kernel.asm -o kernel.bin
可以发现,boot.bin在引导后,就从软盘第二扇区将Kernel.bin读取并装入内存,接下来跳转并执行Kernel.bin,而Kernel.bin便在屏幕上打印一字符串
在这里要用到一个特殊工具:Partcopy 它能将文件写入软盘映像指定位置
available at:http://newworklife.spaces.live.com/blog/cns!27EB11C0372B9EB1!348.entry
编译好两个bin后,就要将它们写入磁盘
用法
partcopy boot.bin 0 200 floppy.img 0
partcopy kernel.bin 0 200 floppy.img 200
运行后,会发现当前目录多了个floppy.img,那正是我们需要的软盘映像文件
我们还需要一个软件:Bochs
这是个虚拟机,不用Vitrual Box是因为它引导软盘映像的成功率低
available at:http://sourceforge.net/projects/bochs/
它需要一个Bochsrc.bxrc文件作为配置
在floppy.img同目录下创建一个Bochsrc.bxrc
右键->编辑,写入
###############################################################
# bochsrc.bxrc file for Xue's OS
#(c)copyright xuejin 2010
#All right reserved
###############################################################
megs: 32
romimage: file=$BXSHARE/BIOS-bochs-latest
floppya: 1_44=C:\FLOPPY.IMG, status=inserted
boot: a
log: bochsout.txt
mouse: enabled=0
keyboard_mapping: enabled=1, map=$BXSHARE/keymaps/x11-pc-us.map
保存,然后运行,
我们会发现Here is Xue s Operating System!OK,Here we go已被打印出来,说明二次装载成功了,ye~~~
2010年08月09日
前一篇文章中我们学习了写引导程序,可是,引导程序大小不能超过512B,将运行代码写到引导程序里并不是不行,但是大小限制会让你的操作系统异常的"精简"
所以一般的操作系统(包括Linux)都是使用一种叫二次加载的方法,也就是写一个及其简单的Boot引导程序,它只做两件事:一是初始化段寄存器(mov ds,ax....),二是从软盘第二扇区读入真正的内核加载到内存指定位置并用1个Jmp跳转到指定位置并执行内核
到回来看看Linux,Linux0.11的Boot文件夹里有Boot.s与Head.s,boot.s的作用就是引导,并跳转至Head,Head才开始进入保护模式,最后跳转至Main.c(init/main.c,当然以编译为.o,并以链接到Tool/System)的,下面是一部分的Linux0.11 Makefile代码
Image: boot/boot tools/system tools/build
tools/build boot/boot tools/system > Image
sync
boot/head.o: boot/head.s
tools/system:boot/head.o init/main.o \
$(ARCHIVES) $(LIBS)
$(LD) $(LDFLAGS) boot/head.o init/main.o \
$(ARCHIVES) \
$(LIBS) \
-o tools/system > System.map
boot/boot:boot/boot.s tools/system
(echo -n "SYSSIZE = (";ls -l tools/system | grep system \
| cut -c25-31 | tr '\012' ' '; echo "+ 15 ) / 16") > tmp.s
cat boot/boot.s >> tmp.s
$(AS86) -o boot/boot.o tmp.s
rm -f tmp.s
$(LD86) -s -o boot/boot boot/boot.o
可以看到head.o与main.o被链接到tool/system,而boot只是负责引导,经过一连的Jmp之后,main函数开始初始化并运行Kernel,这就是二次加载
考虑下面的程序代码
;boot.asm
[ORG 0]
jmp 07c0h:start
start:
;设置段寄存器
mov ax,cs
mov ds,ax
mov es,ax
reset: ;重置软盘驱动器
mov ax,0
mov dl,0 ;Driver=0(=A)
int 31h
jc reset ;if error reset again
read:
mov ax,1000h ;ES:BX=1000:0000
mov es,ax
mov bx,0
mov ah,2 ;读取磁盘数据到地址ES:BX
mov al,5 ;读取5个扇区
mov ch,0 ;柱面0
mov cl,2 ;第二扇区,即为读入文件所在扇区
mov dh,0 ;Head=0
mov dl,0 ;Driver=0
int 13h ;开始读
jc read ;if error try again
jmp 1000h:0000 ;跳转到装载的程序处开始执行
times 510-($-$$) db 0
dw 0AA55h ;结束标志
;Kernel.asm
[ORG 0]
jmp start2
msg db 'Here is Xue s Operating System!OK,Here we go',$0 ;打印字符串定义
start2:
;设置段寄存器
mov ax,cs
mov ds,ax
mov es,ax
mov si,msg
print:
lodsb
cmp al,0 ;al为0?
je hang ;if al=0 then 挂起
mov ah,0Eh ;打印
mov bx,7
int 10h
jmp print ;打印下一字符
hang:
jmp hang ;挂起,即无限循环
times 510-($-$$) db 0
dw 0AA55h ;结束标志
编译
nasm boot.asm -o boot.bin
nasm kernel.asm -o kernel.bin
可以发现,boot.bin在引导后,就从软盘第二扇区将Kernel.bin读取并装入内存,接下来跳转并执行Kernel.bin,而Kernel.bin便在屏幕上打印一字符串
在这里要用到一个特殊工具:Partcopy 它能将文件写入软盘映像指定位置
available at:http://newworklife.spaces.live.com/blog/cns!27EB11C0372B9EB1!348.entry
编译好两个bin后,就要将它们写入磁盘
用法
partcopy boot.bin 0 200 floppy.img 0
partcopy kernel.bin 0 200 floppy.img 200
运行后,会发现当前目录多了个floppy.img,那正是我们需要的软盘映像文件
我们还需要一个软件:Bochs
这是个虚拟机,不用Vitrual Box是因为它引导软盘映像的成功率低
available at:http://sourceforge.net/projects/bochs/
它需要一个Bochsrc.bxrc文件作为配置
在floppy.img同目录下创建一个Bochsrc.bxrc
右键->编辑,写入
###############################################################
# bochsrc.bxrc file for Xue's OS
#(c)copyright xuejin 2010
#All right reserved
###############################################################
megs: 32
romimage: file=$BXSHARE/BIOS-bochs-latest
floppya: 1_44=C:\FLOPPY.IMG, status=inserted
boot: a
log: bochsout.txt
mouse: enabled=0
keyboard_mapping: enabled=1, map=$BXSHARE/keymaps/x11-pc-us.map
保存,然后运行,
我们会发现Here is Xue s Operating System!OK,Here we go已被打印出来,说明二次装载成功了,ye~~~