关于16位的OS尝试

首先我要申明的是我并不是个OS专家,关于OS的研究仅仅是出于自己的兴趣. 但是我认为仅仅是为了自己,也应该把这段时间自己在写OS的经验写出来. 我第一次做的这个OS是个16为实式模式下的OS.因为它比起保护模式要简单,而且容易上手. 首先要找到一张1.44MB的软盘.我的OS就是写到软盘上的.当然你也可以写到硬盘上,不过你得要有两个或更多的硬盘才行.否则硬盘数据被 破坏,计算机就无法启动了.在这里我还得提到我曾经做的一件傻事.由于我的电脑上没有软驱,只有个USB移动硬盘,所以我拿USB盘来代替软盘.后来写上 去的程序无论如何都有问题.经过一步一步细致测试,才发现原来的是USB盘根本不能用BIOS 13h来读.因为USB盘不是磁盘,居然我当时来拿它作磁 盘来读写.现在想起来真是可笑. 我首先写的是Boot Loader,就是软盘上第一个扇区的程序.计算机启动的时候就会自动把这个程序放到0x0000:0x7c00(似乎是这样)去执行.但是只有一个扇区,你不可能把你的整个OS都放到这一个扇区里面.一个扇区才512字节.不过我可以通过这个扇区上的程序,把软盘上其它部分的数据调出来运行.所以老外叫它Boot Loader(引导装载程序). 关 于这个Boot Loader是很简单的.特别是对于我要做的16位实式模式下的OS来说,几乎没有什么要求,你想怎么做就怎么做了.但是如果你要做保护 模式下的OS,就需要设计到很多比如"A20开起"等麻烦的事情.现在网上到处都有关于OS编写的介绍,但是大多都是停留在这个Boot Loader的 讲解中,而且绝大部分还都是讲解16位实式模式下的Boot Loader.比如到www.google.com去搜索一 下"Write your own Operating System",可以找到好多这样的文章.当然,这些主要的都是英文的.看看也不错.国外的这些 网站大多都是讲如何上手,将一些很实际的东西,而且都是不错.比如我知道的一个网站http://osdev.neopages.net /index.php,就是个很不错的.它关于OS的介绍可不是简单地停留在Boot Loader上哦.而且里面还有我们写OS需要的一切工具,和资料 收集. 我喜欢的老师上课最爱讲费话,或许我也汲取了他的优点,讲了上面这么大段的费话,下面我就开始真正写我的Boot Loader了. Boot Loader 似乎只能用汇编写.而最好的汇编编译器是nasm.我开始写Boot Loader的时候,几乎100%的人都说应该使用nasm来作汇编编译器.或许是 因为nasm是公开源代码的吧,也或许nasm支持很多格式的生成文件,所以这个东西向来是汇编高手们推荐的汇编编译器.这个东西你可以在 http://sourceforge.net/找到下载的,连它的源代码都可以找得到呢.不过http://osdev.neopages.net /index.php里面也是提供了的.现在用了段时间nasm,我也确实觉得它是个好东西.而且关于它的文档也是很齐备的,查询很方便. 好,这就是我的Boot Loader的程序 ;---------------------------------------------------------------------- ; Hello World Operating System Boot Sector00 Program ; ; tangl_99 2003 ; ; Disclaimer: I am not responsible for any results of the use of the contents ;   of this file ;---------------------------------------------------------------------- BITS 16 org 0x7c00 ; This is where BIOS loads the bootloader %define  kernel_sectors  16 ; 8K大小的kernel ; Execution begins here entry: jmp short begin ; jump over the DOS boot record data ; ---------------------------------------------------------------------- ;  +-------------------------------------------------------------+ ;  | Data section of boot.asm bootstrap file                     | ;  +-------------------------------------------------------------+ bsOEM       DB 'DEVIATOR'               ; OEM String bsSectSize  DW 512                      ; Bytes per sector bsClustSize DB 1                        ; Sectors per cluster bsRessect   DW 1                        ; # of reserved sectors bsFatCnt    DB 2                        ; # of fat copies bsRootSize  DW 224                      ; size of root directory bsTotalSect DW 2880                     ; total # of sectors if < 32 meg bsMedia     DB 0xF0                     ; Media Descriptor bsFatSize   DW 9                        ; Size of each FAT bsTrackSect DW 18                       ; Sectors per track bsHeadCnt   DW 2                        ; number of read-write heads bsHidenSect DD 0                        ; number of hidden sectors bsHugeSect  DD 0                        ; if bsTotalSect is 0 this value is ; the number of sectors bsBootDrv   DB 0                        ; holds drive that the bs came from bsReserv    DB 0                        ; not used for anything bsBootSign  DB 29h                      ; boot signature 29h bsVolID     DD 0                        ; Disk volume ID also used for temp ; sector # / # sectors to load bsVoLabel   DB 'DeviatorOS '            ; Volume Label bsFSType    DB 'FAT12   '               ; File System type ;------------------------------------------------------------------------ ; -------------------------------------------- ;  Boot program code begins here ; -------------------------------------------- ; boot code begins at 0x0040 begin: xor ax, ax  ; zero out ax mov ds, ax  ; set data segment to base of RAM mov si, WelcomeMsg ; load address of our welcome message call putstr  ; print the welcome message mov si, newline call putstr mov si, loadMsg ; load address of loading message call putstr  ; print the loading message mov si, newline call putstr xor ax,ax int 13h jc fail ;------------------------------------------------- ; 把下一个扇区01的数据读到0x500:0000,然后执行 ;------------------------------------------------- readsector01: mov ax, 0x500  ; 先将扇区01的数据存放的缓冲段地址传递给AX mov es, ax   ; 通过AX,再缓冲段地址传递给ES mov bx, 0   ; 缓冲偏移地址为0 mov dl, 0   ; 要读取的驱动器号为0h,为A软驱 mov dh, 0   ; 要读取的磁头号为0 mov ch, 0   ; 要读取的磁道号为0 mov cl, 2   ; 要读取的扇区号为2 mov al, kernel_sectors ; 要读取的扇区数为kernel_sectors mov ah, 2   ; 调用读磁盘的中断程序 int 13h cmp ah, 0   ; 查看是否读成功,ah为0表示读取成功 jz gotosector01  ; 如果成功,转到gotosector01 fail: mov si,readerrorMsg  ; 将readerrorMsg的地址传给si,准备打印 call putstr   ; 打印读磁盘错误的信息 mov si,newline call putstr hang: jmp hang gotosector01: mov si, LoadSectorOKMsg ; 显示读取第二个扇区成功的信息 call putstr mov ax, 0x500  ; 跳转指令到0x500:0000,并把es,ds都改到0x500,但是注意,在jmp指令前不能改cs mov es, ax mov ds, ax jmp 0x0500:0x0000 ; -------------------------------------------- ; data for our program ;---------------------------------------------- WelcomeMsg db 'Welcome to Tangl Operating System',0 loadMsg  db 'Operating System Boot Program is Loading......', 0 LoadSectorOKMsg db 'loaing next sector OK',0 readerrorMsg db 'Error: Can not read sector 01 !', 0 newline db 13,10,0 ; --------------------------------------------- ; Print a null-terminated string on the screen ; --------------------------------------------- putstr: lodsb   ; AL = [DS:SI] or al, al  ; Set zero flag if al=0 jz putstrd  ; jump to putstrd if zero flag is set mov ah, 0x0e ; video function 0Eh (print char) mov bx, 0x0007 ; color int 0x10 jmp putstr putstrd: retn ;--------------------------------------------- size equ $ - entry %if size+2 > 512 %error "code is too large for boot sector" %endif times (512 - size - 2) db 0 db 0x55, 0xAA  ;2  byte boot signature 这么长一篇,你不要觉得干了很多事情.简单地说,我只做了一件有用的事情. 就是把软盘后面16个扇区的数据读出来,并去执行. 代码开头有块叫"引导记录"数据的定义,就是记录一些关于这张磁盘有多少个扇区,多少个磁头,每个扇区多少字节等信息.其实1.44MB的磁盘这些信息都是不变的,只要是1.44MB的软盘,这些数据都 是一样的,根本没有必要写出来.但是如果我不把它们写出来,那么当我这张磁盘插入软驱后,Windows或Dos会说它没有格式化,还要我重新格式话,那 么我写在上面的boot loader程序就会没有.所以我还是讲究一下windows/dos,按照它们的标准,把这些信息写上去. 后面的代码主要就是显示些提示信息,然后就是一个调用BIOS 13h读磁盘的中断程序.通过它,把后面16个扇区的数据读出来,读到0x500:0x0000去,最后跳到0x500:0x0000去执行那些代码.那16个扇区的代码才是我真正的OS的kernel内核的代码.
posted @ 2012-07-15 23:12  adodo1  Views(157)  Comments(0Edit  收藏  举报