【我所認知的BIOS】-->自己動手啟動計算機
LightSeed
2009-11-5
我当时在做《汇编语言》王爽(第一版)著的那本书的最后一题“课程设计二”的时候有关于启动OS的操作,想想这个题目对理解我们BIOS到OS的控制权的交付有比较形象的理解,故在这里也和大家探讨一下。
1、软盘的引导扇区格式及原理
1.1引导扇区的格式
(笔者:以下这段是参考
http://hi.baidu.com/rabbit5455/blog/item/7f482fdf2dccc310632798ec.html的文章。)
FAT12是DOS时代就开始使用的文件系统,目前软盘上也一直在用。
引导扇区是软盘的第0个扇区,在这个扇区中有一个很重要的数据结构叫BPB(BIOS Parameter Block),下面是引导扇区格式,其中BPB_开头的属于BPB,以BS_开头的只是BOOT Sector的一部分,不属于BPB。见图1
图1 软盘的启动扇区格式
紧接着引导扇区的是两个完全相同的FAT表,每个占用BPB_FATSz16(0x9)个扇区;第二个FAT之后就是根目录区的第一个扇区,根目录区后面是数据区。根目录区的位置:引导扇区占1个Sec,两个FAT表共18Sec,所以根目录区开始扇区号为19。根目录区中由若干个目录入口(Directory Entry)组成,最多有BPB_RootEntCnt个,所以根目录区大小不固定。每个Directory Entry占32字节。
1.2 提取其中的原理
其实看了那么多,我们不妨投机取巧一下,发现了一个现象了没有?原来这个扇区的第一条指令是jmp。那么我们就可以在这里做文章了。因为这里用了jmp指令,那么CPU取指令的时候必定是到这里来了的。所以我们只需要在这添上合理的(小于510 byte)的程序来完成引导等其他的任务即可。故我们只是那软盘的引导扇区来做我们自己的动作而已。
2、我们想要实现的功能
在明知道有C盘的情况下通过软盘来启动。如果可以顺便实现自己的功能。(比如说显示时钟呀,输入密码呀等等什么的。。。自己加了。)实现的功能程序在启动扇区中的逻辑图,在第一个扇区中的代码会把从第二扇区开始的代码copy到相应的内存中去。见图2
图2 启动扇区程序结构图
3、构思一下我们的程序架构
可以分成这么几个小块:
①安装启动代码到软盘的启动扇区模块
②重定位启动程序实体模块(因为自己写的程序,大多会超过512byte)
③检测键盘输入输出模块
④针对输入输出可以分支处理(进入各个功能的子程序)
⑤调用本来OS的启动程序。(调用原本的0:7C00H处的程序)
4、代码实例
外甥打灯笼,我们来看看实际的代码并加注。
;********************************************************************
;Note::这段代码是参考一位前辈的不过不记得是哪里了---------
; 如果您发现了是哪里的code还希望您提示我一下--------
; 在全部code基础之上,我做了简化,目的是为了结构明显易懂----
;Function: 大致實現了 重啟電腦,啟動電腦-----------------------------
; 查看系統時鐘,修改系統時鐘四個功能---------------------
;PS: 值得學習的地方是怎麼通過自製啟動扇區來引導現有的OS,并在引導
; OS之前可加入自己的function。
;
; By LightSeed-2009-10-27-----------------------
;********************************************************************
ASSUME CS:CODE
CODE SEGMENT
;**********************************************************************************
;安装程序模块:
;写入以下的程序到第一个和后面的扇区
;不需要确定程序的确切固定长度,因为int 13h只能按照512字节的倍数传递,所以即使比512多
;一个字节,也要传递512个。
;**********************************************************************************
ERROR00H DB 'successful completion!',0
begin:
MOV AX,CS
MOV ES,AX ;要写的内存基址
MOV DS,AX
LEA BX,REAL ;要写的内存偏移
MOV AH,3 ;功能号,写
MOV AL,((PROGRAMEEND-REAL)/512+1) ;写扇区的数目,浪费一个扇区以获得编写的方便。
MOV CH,0 ;磁道号
MOV CL,1 ;扇区号
MOV DL,0 ;驱动器号
MOV DH,0 ;磁头号(面)
INT 13H
;磁盘写容错处理
;容错的代码请加在这里
;/成功写入,显示提示符并返回DOS
WriteFinish:
;清屏
CALL CLEARSCREAN
;清屏后,显示您想要显示的信息
MOV SI,OFFSET ERROR00H
MOV DH,10 ;显示子函数入口参数---显示的横行位置
MOV DL,20 ;显示子函数入口参数---显示的纵行位置
PUSH CX
MOV CL,00001111B
CALL SHOW_STR
POP CX
;//键盘等待输入按任意键返回DOS
MOV AH,0
INT 16H
ok_WriteErrorManage:
;