晤…… 如果你的开发工具都已经准备好了,那么我们来开始干活吧!
IA-32体系下的 i386 及以后的处理器,为了同当年的8086相兼容,在系统启动的时候都是将处理器置于实模式。这个时候你可以将系统看做是 "高速的8086" 因此这决定了我们启动部分的代码,是必须用16bit代码去编写的。 IBM PC在引导的时候,是从有效引导设备的第0磁头0面1扇区开始的,BIOS读取这个扇区的所有数据,并将它们加载到0x0:0x7c00地址处,然后BIOS会跳到这个地址,开始执行这个扇区的内容,也就是开始引导PC了。
基于以上2点,我给出如下的代码:
; MyOS Ver 0.0 Boot.asm
; Play!Zone 2002-2005 kakashi.r
;
; 从磁盘上加载0磁道 0磁头 第2扇区的 detect检测程序并跳转执行.
;
;
;
;
;
;
.8086
.model small
.code ;一些程序中使用的常量的定义
INIT_SEG = 07c0h
INIT_STACK = INIT_SEG
RUN_SEG = 9000h
CORE_SEG = 9020h
org 0
.startup
entry:
mov ax, INIT_SEG
mov ds, ax
mov cx, 256
mov ax, RUN_SEG
mov es, ax
mov si, 0
mov di, 0
rep movsw ;移动7c00:0的代码到90000:0处并跳转过去执行
mov ax, INIT_STACK
mov ss, ax
mov sp, 0200h
mov ax, RUN_SEG
mov bx, offset Start
push ax
push bx
retf
Start: ;以下部分使用的是int10h 不熟悉的话参考BIOS手册
DisplayText:
mov ax, cs
mov ds, ax
mov si, offset MSG
sub cx, cx
ShowText: ;循环显示字符串
mov al,[si]
inc si
inc cx
mov ah, 0eh
mov bx, 0007h
int 10h
cmp cx, 1dh
jle ShowText
Load_Kernel: ; 下面的部分使用的是int13中断,不熟悉的话请参考BIOS中断手册。
mov ax, CORE_SEG
mov es, ax
mov bx, 0
mov cl, 2
mov ch, 0
mov al, 2 ;读取1个扇区
mov dx, 0
mov ah, 2
int 13h
cmp ah, 0
jne Load_Kernel ;读取失败,死循环
mov ax, CORE_SEG
mov bx, 0
push ax
push bx
retf ;成功则跳到90200:0开始执行
Data:
org 200h-21h
MSG db "Loading Kaka's Opeart System",0dh,0ah
org 01feh
Boot dw 0aa55h ;启动扇区正常结束标志
end
这段代码使用masm611编译连接,并使用exe2bin工具转换。总长度为512字节,其中最后的2个字节 0xaa 0x55 是有效引导扇区的标志字节。BIOS通过这2个字节来判断是否是有效引导扇区。
代码的作用很简单,在屏幕上显示一行Loading Kaka's Opeart System 然后将加载引导设备上的0头0面2扇区的数据到 0x90200:0,加载成功的话则会跳到这个位置去执行。这样就完成了最初期的引导工作,0x90200:0处的代码会接着完成其他的工作。至于0x90200:0处的程序就是是什么,这个可以按你的要求去做。我自己的则是将处理器设置为保护模式,下次放出给大家看。
大家在用Bochs调试的时候,推荐使用软盘进行引导,使用Uedit将编译好的代码,保存到软盘映象文件的前512个字节上就可以了。注意不要写错了位置啊 - -b 然后启动Bochs开始看你写的启动代码是如何一句一句执行的吧!