<body>

kenshou

天空没有飞过的痕迹,但我已经努力飞过……

« Home | Next » | Next » | Next » | Next » | Next » | Next » | Next » | Next » | Next » | Next »

os之hello world!(2)

在上篇helloworld的基础改为bootsect负责加载setup到内存,然后由setup来显示我们可爱的“Hello, keroro!”

1:在这里boot程序先把自己移动到0x9000处,
然后读磁盘的引导区后的2个扇区的setup到内存0x9020:0后,
最后跳转到0x9020:0(也就是执行setup程序)

2:本来写了个简单的makefile文件,那知道在我的cygwin中总是说找不到/bin/sh,我就修改成bat文件了。
nasm.exe boot.asm -o boot.bin
nasm.exe setup.asm -o setup.bin
cat setup.bin >> boot.bin
dd if=boot.bin of=myos.img bs=512 count=2880
bochs -f myos.bochsrc
其中用cat来把setup程序加载在boot的后面
3:到现在都是用的实模式的汇编还比较简单了,下一步准备setup开启保护模式,进入32位汇编,呵呵,当年学的微机原理都已经忘记完了,下一步可能比较难了。

参考linux 0.11的bootsect.s的程序然后用nasm的语法来编写的

附录1:boot.asm引导程序

;boot.asm引导程序
org 0h ;
SETUPLEN equ 4 ;nr of setup-sectors,setup程序的扇区值
BOOTSEG equ 0x07c0;boot的原始地址(段地址,以下都是段地址)
INITSEG equ 0x9000;boot移动以后的地址
SETUPSEG equ 0x9020;setup程序的起始地址

start:
;移动自身到INITSEG处
mov ax,BOOTSEG
mov ds,ax
mov ax,INITSEG
mov es,ax
mov cx,256
sub si,si
sub di,di
rep
movsw;注:第一次写的时候我不知道与as86用movw不同的是nasm用movsw

jmp INITSEG:go;跳转到移动以后的新的地址执行程序

go:

;从新初始化ds,es,ss到新的代码所在段处(INITSEG)
mov ax,cs
mov ds,ax;因为程序中有堆栈操作(push,pop,call),因此必须设置堆栈
mov es,ax
;将堆栈指针指向(0x9000:0xff00)
;因为代码段移动过了,所以要重新设置堆栈段位置
;sp只要大于512偏移处都可以,但因为从0x90200地址开始放置setup程序(大约为4个扇区)
;所以sp要指向大于(0x200+0x200*4+堆栈大小)处
mov ss,ax
mov sp,0xff00

;开始加载setup程序到内存
;INT 13H 直接磁盘服务中断
;
;功能描述: 读扇区
;入口参数: AH=02H
;AL=扇区数
;CH=柱面
;CL=扇区
;DH=磁头
;DL=驱动器,00H~7FH:软盘;80H~0FFH:硬盘
;ES:BX=缓冲区的地址
;出口参数: CF=0——操作成功,AH=00H,AL=传输的扇区数,否则,AH=状态代码,参见功能号01H中的说明

load_setup:
mov dx,0x0000
mov cx,0x0002
mov bx,0x0200;注,第一次忘记加了:(
mov ax,0x0200+SETUPLEN ;ah=02h,读setuplen个扇区
int 0x13

jnc ok_load_setup ;成功读取setup后跳转
;如果没有成功则磁盘系统复位然后再重新读取
mov dx,0x0000
mov ax,0x0000
int 0x13
jmp load_setup;

;如果加载成功
ok_load_setup:
jmp SETUPSEG:0

times 510-($-$$) db 0 ; 填充满512字节
dw 0x55aa ; 按照书上说的必须结尾两字节为55aa,但在bochs中好像并没有检测这引导扇区标志

-----------------------------------------------------------------------------
附录2:setup.asm程序显示hello keroro!

;setup.asm
mov ax,cs ;将ds,es,ss都设置成移动后的代码所在段处(因为下面的打印程序需要es)
mov ds,ax
mov es,ax

call ClearSrc ;//清屏幕
call DispStr ; 调用显示字符串例程
jmp $ ; 无限循环

ClearSrc: ;清屏
mov bh,00
mov cx,0
mov dx,0x184f
mov ax,0x0600
int 10h
ret

DispStr:
mov ax, BootMessage
mov bp, ax ; ES:BP = 串地址
mov ax,0x9020
mov es,ax
mov cx, 14 ; CX = 串长度
mov dx,0x0 ;DH,DL=起始行,列
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, keroro!"

参考资料
1:《操作系统引导研究》 谢煜波 http://purec.binghua.com
2:《linux 内核0.11完全注释》(赵炯,2003)

标签:

leave a response