<body>

kenshou

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

bootsystem之hello(3)

哇哈哈,本人的第一个保护模式程序诞生了,从实模式转换到保护模式经历了很多曲折的东西,gdt的地址一直加载不对,经过对bochs的调试和参考大量文献的基础上终于发现在linux0.11的setup中加载gdt的时候是把gdt的地址加上512才对了,修改后我的也就成功运行了第一在保护模式下打印“hello keroro!”的程序了。不过现在保护模式下的测试打印程序还有点问题,呵呵,明天继续修改。
总结下明天需要对今天的一些东西进行学习:1.机器高字节和nasm编译出来的字节的关系;2:gdtr,gdt等东西的定义。

先把今天的代码成列出来,明天再记录今天解决问题所使用的一些方法了。

----
boot.asm程序就使用之前的,修改了setup.asm,增加了system.asm这个实模式下的程序文件.

setup.asm文件

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

jmp Main

SETUPSEG equ 0x9000;setup程序的起始地址
SETUPLEN equ 2048
SETUPOFFSET equ 0x200;

SYSTEMSEG equ 0x0000
SYSTEMOFFSET equ 0x0000
SYSTEMSIZE equ 1024

;定义GDT表描述符
gdt_addr:
dw 0x800 ;gdt表的大小
dw gdt+512 ;gdt表的位置/*****最刚开始我没有加512导致一直gdt没有加载对
dw 0x0009
gdt:
gdt_null:
dw 0x0000
dw 0x0000
dw 0x0000
dw 0x0000
gdt_system_code:
dw 0x07ff
dw 0x0000
dw 0x9a00
dw 0x00c0
gdt_system_data:
dw 0x07ff
dw 0x0000
dw 0x9200
dw 0x00c0

;等待键盘控制器空闲的子程序
Empty_8042
in al,0x64
test al,0x2
jnz Empty_8042
ret

;清屏子程序
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 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!"
;----------------------------------
Main:

; call ClearSrc ;//清屏幕

;读取system的代码到setup程序后面
load_system:
mov ch,0 ;
mov cl,1+1+SETUPLEN/512 ;system所在的启始扇区
mov dx,0x0000;暂时直接就设置为读取软驱
mov bx,SETUPLEN
mov ax,0x0200+SYSTEMSIZE/512

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

ok_load_system:
;jmp 0x90a0:0
;jmp SETUPSEG+SETUPOFFSET/0x10+SETUPLEN/0x10:0 ;用来测试system是否加载成功

cld
;移动system代码到0x0000


mov ax,SETUPSEG+SETUPOFFSET/0x10+SETUPLEN/0x10
mov ds,ax
mov ax,SYSTEMSEG
mov es,ax
mov cx,SYSTEMSIZE


sub si,si
sub di,di
rep movsw


;设置gdt
cli ;关中断
;由于要加载gdt重置一下段
mov ax,cs
mov ds,ax
lgdt [gdt_addr]

;打开A20地址线
call Empty_8042
mov al,0xd1
out 0x64,al
call Empty_8042
mov al,0xdf
out 0x60,al
call Empty_8042
;下面设置进入32位保护模式运行
mov eax,cr0
or eax,1
mov cr0,eax
jmp dword 0x8:0x0
times SETUPLEN-($-$$) db 0

----------------------

bits 32
org 0x0
jmp Main
DATA_SEL equ 0x10 ;内核代码段选择子
BootMessage: db "Hello keroro!"
dw 0x0000
dw 0x0000


Main:
mov eax,DATA_SEL

mov ds,ax
mov es,ax
mov fs,ax
mov gs,ax
mov ss,ax
mov esp,DATA_SEL ;# 所有数据段选择子设置为0x10,即GDT的第3项,特权级为0。

mov al,0x07
mov esi,BootMessage
mov edi,0xb8000
display:
cmp esi,0
je endPro
movsb
stosb
jmp display
endPro:
jmp endPro






参考文献(注:以前的参考文献同样会参考,这里就不列举了):
1:[Bochs]Bochs调试技术 http://huqingyu.cnblogs.com/archive/2005/02/19/105864.html
2:《自己动手写内核(中文版)》http://www.cppblog.com/jinglexy

标签:

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)

标签:

宅男侵略电脑之OS“hello world”

作为一代宅男的我在看《keroro军曹》后被keroro的侵略精神所感动,决定学习其坚韧的侵略精神,因此我准备侵略电脑。

侵略电脑的这个万里长征的第一步就是在裸机上写出自己的“hello world”,考虑了安全起见等,先需要演习一下,于是我的侵略环境和工具选择为:
1:bochs:虚拟电脑软件,在sf上面下载。
2:cygwin:在win下面运行许多linux命令,主要网上很多资料都是linux下面的,就选择了它让我在win下面运行常用的linux命令。(http://www.cygwin.cn/)
3:nasm: 汇编编译器(不用问我为什么用这个,我看网上很多用的这个就用这个了,是个随大流的)

第一步:编写第一个hello world!程序

org 07c00h ; 告诉编译器程序加载到7c00处
mov ax, cs
mov ds, ax
mov es, ax
call DispStr ; 调用显示字符串例程
jmp $ ; 无限循环
DispStr:
mov ax, BootMessage
mov bp, ax ; ES:BP = 串地址
mov cx, 16 ; CX = 串长度
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, OS world!"
times 510-($-$$) db 0 ; 填充剩下的空间,使生成的二进制代码恰好为512字节
dw 0xaa55 ; 结束标志

-----------------
保存为boot.asm,运行nasm boot.asm -o boot.bin

第二步:生成image文件。

这里我用的dd命令来生成image文件。
dd if=boot.bin of=myos.img bs=512 count=2880

第三步:配置bochs文件。

直接进入bochs安装目录bochsrc-sample.txt另存为myos.bochsrc,然后修改其中的floppya为第二步生成的img文件,并把ata0-master屏蔽然后把引导修改成floppy。

floppya: 1_44=myos.img, status=inserted
boot: floppy

第四步:keroro,霍霍,运行我们hello world!吧
bochs -f myos.bochsrc

ok,侵略电脑的第一步踏出来了,下面宅男我继续看《keroro军曹》了

参考资料:
1:《自己动手写操作系统》的第一个例子 http://blog.csdn.net/areful/archive/2008/01/14/2043217.aspx
2: bochs使用(linux下搭建操作系统开发环境,原创) http://dev.csdn.net/article/83404.shtm
3:dd 用法 http://school.21tx.com/2005/03/13/16475.html
4:BIOS中断表 http://blog.chinaunix.net/u/13171/showart.php?id=341416

标签:

下一秒是否能打开blog是一个迷

前一秒好像还能打开blog,后一秒就又不能打开了。我不禁的又想到薛定谔的那只猫,我的blog到底能不能打开完全是靠我的读者是什么时候打开的来决定的。