codefans

导航

<2008年10月>
2829301234
567891011
12131415161718
19202122232425
2627282930311
2345678

统计

常用链接

留言簿(2)

随笔分类

随笔档案

文章分类

文章档案

程序设计链接

搜索

最新评论

阅读排行榜

评论排行榜

[开发教程][原创] 操作系统DIY - 启动你的计算机

预备知识:
  汇编语言、能读懂NASM语法、了解BIOS 中断INT0x10, INT 0x16,虚拟机的使用

涉及工具:
  NASM,一个文本编辑器(我用的是ConText + NASM语法高亮)

前言:
  第一次写教程,不知道能拿多少分。

  “怎样开始写自己的操作系统”可能是不少有“非分想法”的爱好者来说是一个难题,在我的大学课程《计算机操作系统教程》以教程的形式充分说明了操作系统的原理,这本书会告诉你各个环节的原语;所谓“原理”就指理论上的东西,实际上我们并不知道操作系统是如何工作的。为了不至于让有这个非分想法的朋友不至于放弃,这篇日志就带你走进操作系统开发的殿堂。

一、操作系统是如何启动的?

  首先让我们来看看计算机的启动过程,这里我摘抄了一些东西:

  “首先让我们来了解一些基本概念。第一个是大家非常熟悉的BIOS(基本输入输出系统),BIOS是直接与硬件打交道的底层代码,它为操作系统提供了控制硬件设备的基本功能。BIOS包括有系统BIOS(即常说的主板BIOS)、显卡BIOS和其它设备(例如IDE控制器、SCSI卡或网卡等)的BIOS,其中系统BIOS是本文要讨论的主角,因为计算机的启动过程正是在它的控制下进行的。BIOS一般被存放在ROM(只读存储芯片)之中,即使在关机或掉电以后,这些代码也不会消失。

  “第二个基本概念是内存的地址,我们的机器中一般安装有32MB、64MB或128MB内存,这些内存的每一个字节都被赋予了一个地址,以便CPU访问内存。32MB的地址范围用十六进制数表示就是0~1FFFFFFH,其中0~FFFFFH的低端1MB内存非常特殊,因为最初的8086处理器能够访问的内存最大只有1MB,这1MB的低端640KB被称为基本内存,而A0000H~BFFFFH要保留给显示卡的显存使用,C0000H~FFFFFH则被保留给BIOS使用,其中系统BIOS一般占用了最后的64KB或更多一点的空间,显卡BIOS一般在C0000H~C7FFFH处,IDE控制器的BIOS在C8000H~CBFFFH处。”

  (以上引自:http://article.pchome.net/2003/09/25/13022.htm

二、进一步了解引导的关键所在

  计算机启动的第一个过程由BIOS完成,它做了什么工作是不我们不必理会的,我们也管不了那它;关键在于:BIOS完成设备检查、初始化、更新之后,根据预先设定的引导设备顺序检查可以引导的设备,比如我们设置启动顺序为1:Floppy(软驱)2:HDD1(硬盘1) 3:CD-ROM(光驱),那么,BIOS会从软驱开始查找是否可以启动,如果软驱失败,则会去找HDD1,......
  那么,BIOS如何知道软盘或硬盘能不能引导呢?这个把戏的关键在于:每个可引导设备都有一个512字节的设备头,如果这个设备可引导,最后两个字节必须为0x55(低),0xAA(高),如果BIOS找到这个标志,就会将这512字节(注意:只有512字节)读到内存的0x0000:0x7C00,然后将控制权转交给(跳到)0x0000:0x7C00的程序,这就意味着:如果我们将软盘的第一个扇区最后两个字节打上"0x55,0xAA"的标志,这个软盘就可以启动了!当然,BIOS不会知道你这个引导程序是不是有效的,它只认0x55,0xAA。

  好了,我们知道写自己第一个引导程序的关键在于: 
  1. 一个两字节(一个字长)的引导标志 0x55,0xAA
  2. 引导程序必须占512字节

三、看看实例

  代码用NASM编译:nasmw -f bin boot.asm -o boot.bin
  解释一下上面的命令:在M$命令提示行下编译,-f bin 表示编译为纯二进制文件(我们不需要任何文件头),-o boot.bin 编译。

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; boot.asm
; A demo to show how bootsect works
; Last modified:2005-4-3 10:57:45
; Copyright (c) 2005,E-mean X.
;
; This program is released under GPL,See document for details
; You can use this code anywhere you want in condition keep autor's info
; original
;
; Author: E-mean X.
; Contact: xemean@sina.com
; Website: http://www.xemean.net/
; April,02,2005
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
bits 16         ; 伪指令,告诉编译器这是 16位代码
org 0x7C00      ; 伪指令,告诉编译器这段代码由0x0:0x7C00开始
;===========================================================================
; 程序执行的第一条指令必须是跳转(如果你想使用FAT12这类文件系统的磁盘)
; 必须占用3字节
;===========================================================================
jmp SHORT main ; 2 bits,跳转到主程序执行
nop            ; 1 bit
;===========================================================================
; FAT12 文件系统头,从NYAOS 借过来的,可以参考相关的文档以获得更多细节
; 这个块会让 Winimage 认出编译后的二进制文件为有效的引导文件
; 如果不使用这个块,Winimage将不会将其作为引导程序处理
; 但我们可以借助其它方法和工具处理,比如DEBUG
;===========================================================================
bsOEM       db "ExOS0.01"               ; OEM String,任意你喜欢的8字节ASCII码
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 "NO NAME    "            ; Volume Label
bsFSType    db "FAT12   "               ; File System type <- FAT 12文件系统
;===========================================================================
; Main start here
;===========================================================================
main:
     cli  ; 关闭可屏蔽中断,以备我们接下来初始化寄存器的工作
     mov  ax,cs ; 将代码段传给ax,实模式下,代码段与数据段没什么分别
     mov  ds,ax ; 数据段寄存器,实际上都是0
     mov  es,ax ; 附加段
     mov  ax,ss ; 堆栈段
     mov  sp,0x7C00-1   ; 堆栈指针,指向0x7BFF
     sti  ; 基本工作已经完成,开放中断

     ;
     mov  si,msgHello ; 使 si指向 "Hello World!"字符串
     call printStr    ; 调用显示子程序
    
     mov  si,fixLine  ; 回车换行
     call printStr
    
     mov  si,msgMore  ; 显示更多信息
     call printStr

     ; Mission complete,take a break
     .loop:
     xor  ax,ax       ; ax 清0
     int  0x16        ; 调用int 16h 读取键盘输入

; 重启计算机
;     mov  ax,0x40
;     mov  ds,ax
;     xor  ax,ax
;     mov  [0x0072],ax  ; 向 0x40:0x72写0后再跳到_
;     jmp  0xFFFF:0x0    ; 0xFFFF:0x0 可以实现重启

     jmp  .loop       ; 跳转到 .loop,什么也不做了

;------- END OF MAIN ----------------

;===========================================================================
; printStr
; sub function for print a string to screen by INT 10H
; 入口:ds:si = 指向目标字符串
; 返回:无
;===========================================================================
printStr:
     push si  ; 保护寄存器
     push ax
     push bx

          cld    ; 清除进位标志位,这个标志位会影响 si 的递增方向
          mov  ah,0x0E    ; int 0x10 子功能号,显示字符,参看相关资料以获得细节
          mov  bx,0x0007  ; 页号0,字符前景色 7,浅灰色,试着改变这个数值
                          ; 会给你的文字增添色彩
     .nextChar:
          lodsb           ; [si] -> al,取一个字节码
          or  al,al       ; 如果取得的字节是0,则表示字符串结束
          jz  .OK         ; 退出
          int 0x10        ; 调用BIOS int 10h 中断
          jmp .nextChar   ; 继续下一个字符,直到遇到0
     .OK:
     pop  bx ; 恢复寄存器
     pop  ax
     pop  si
     ret     ; 返回调用程序
;------- END OF printStr --------------

; data area

msgHello db 'Hello World!',0          ; 以物理 0结束
msgMore  db 'Wow,my FIRST boot sector!',0
fixLine  db 13,10,0   ; 回车,换行的ASCII码

; 引导程序必须为512字节,不用的地方以0填充
  times 510-($-$$) db 0            ; $表示程序当前位置,$$表示程序开始位置,由编译器自动计算
 
BOOT_SIGN     DW 0xAA55            ; 最后两个字节为引导标志55AA

;--------------------------- End of this programme --------------------------------------

编译成功之后,会生成一个512字节的boot.bin,用Winimage创建一个新的软盘,在“Options(选项)”菜单里,"Winimage mode selection ..." 选择“WinImage Professional mode(专家模式)”(如果不选专家模式,将不能进行引导扇区的编辑),之后,"Image-> Boot Sector Properties"(映像->引导扇区属性)中,将引导扇区改为你刚才编译的程序,保存,用Vmware/Qemu/Bochs之类的虚拟机工具试试你的启动盘吧!引导成功

发挥你的想像力,让你的引导程序实现更多的功能!

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

E-mean X.
April,03,2005

转载请说明作者及出处


阅读全文(787) | 回复(5) | 引用(24)
 


回复:[原创] 操作系统DIY - 启动你的计
xemean发表评论于2005-8-15 19:59:11

文件系统基本上可认为是文件在磁盘上的组织形式,由操作系统管理文件系统,比如MS$系统就用过FAT12、FAT16、FAT32、NTFS...,Linux有EXT等等,这东西不是几个字就可以说清楚的,还需要看相关的资料。

操作系统基于文件系统来管理文件,比如读、写和修改文件,磁盘从物理上以CHS来定位文件(目前大硬盘有LBA模式),我们在应用中当然不可能通过CHS来定位文件,应用中,我们通过一个路径来标识一个文件,比如c:\boot.ini、/boot/grub/grub.conf,这是文件系统的一个基本功能。


个人主页 | 引用 | 返回
 


回复:[原创] 操作系统DIY - 启动你的计
11(游客)发表评论于2005-7-9 11:54:21
我想问的就是说文件系统是什么概念呢?引导程序原理我是看懂了 请指教

个人主页 | 引用 | 返回
 


回复:[原创] 操作系统DIY - 启动你的计
你好(游客)发表评论于2005-7-9 11:30:16

你们这么一回 我有点晕了 这里可以去除FAT12的文件系统吗? 文件系统启到什么作用?我有点把文件系统和引导程序弄混了,还请指教!

;===========================================================================
bsOEM       db "ExOS0.01"               ; OEM String,任意你喜欢的8字节ASCII码
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 "NO NAME    "            ; Volume Label
bsFSType    db "FAT12   "               ; File System type <- FAT 12文件系统
;===========================================================================

您这一段是干什么用的? 还有我有个问题文件系统是实质存在?还是我们逻辑存在的?由谁管理呢?我看了很多天这文章和其他东西。搞不清楚~还请多多指教!


个人主页 | 引用 | 返回
 


回复:[原创] 操作系统DIY - 启动你的计
xemean发表评论于2005-4-8 20:42:31

To WY.lslrt:

呵呵,的确,我忽略了这一点。

谢谢提醒。


个人主页 | 引用 | 返回
 


回复:[原创] 操作系统DIY - 启动你的计
WY.lslrt(游客)发表评论于2005-4-8 18:27:08

小谢:

  硬盘的引导代码不能是510字节吧,因为从

0x1BE-0x1FD是硬盘的基本分区表啊,这可是64字节啊

posted on 2005-09-14 00:22 春雷的博客 阅读(466) 评论(1)  编辑  收藏

评论

# re: [开发教程][原创] 操作系统DIY - 启动你的计算机 2008-10-06 01:33 思维机器

原来也有同样的爱好者!

我也写过。。。很简单的功能
没有用什么工具,资料也不足,只能从软盘启动。
还需要写保护模式下的代码编译程序。。。。巨大的工程。。。没时间。。没精力,更没希望。
大家多努力
  回复  更多评论   


只有注册用户登录后才能发表评论。


网站导航:
博客园   IT新闻   Chat2DB   C++博客   博问