2008年(909)
分类:
2008-05-06 22:38:11
下载源代码
摘要
本文给出了软盘镜像生成工具的实现,并用其把自己编译生成的引导文件制作成软盘镜像,写入软盘实现一个简单操作系统的引导。
关键词 软盘镜像工具 操作系统引导。
为了深入的了解80X86计算机的内部原理,参照别人的程序用汇编写了几个小程序。但生成软盘镜像的工具大都是DOS版本的,于是就想自己用VC也实现一个,并用把自己的引导程序写入软盘上验证一下。
1、镜像工具的基本原理
镜像工具读取磁盘上的文件,然后安装一定的格式生成软盘镜像文件,最后把软盘镜像文以512字节扇区为单位,写入软盘上。
2、镜像工具的界面设计及功能介绍
图1 主界面
2.1 【功能1】生成软盘镜像文件
(1)要生成镜像文件,需要先选择源文件,然后点击【生成…】,如MyDiskImg.img,点击【保存】生成镜像文件。
图2 生成镜像文件
(2)然后插入一张软盘,点击写软盘,选择刚生成的镜像文件。点击【打开】,系统便开始把选择的镜像文件写入软盘中。
图3 把镜像文件写入软盘
(3)重新启动计算机,选择从软盘启动,看操作是否成功。
3、具体代码编写
3.1 生成软盘镜像代码
基本原理为对列表中的源文件依次读取,然后写入到一个img文件中,具体的代码请参考(省略了部分不关键代码):
//生成镜像文件函数 UINT FuncGenImageFile(LPVOID pDialog) { //Begin 显示设置 省略… //1.创建输出镜像文件 byte* pBuf = NULL; DWORD count = 0,dwFileLength=0; CFile outfile;//镜像文件 if(!outfile.Open(pCurDlg->m_ImgFileName,CFile::modeCreate | CFile::modeWrite)) { 错误提示… return -1; } //2.依次对输入文件读取,写入输出镜像文件 for( int i = 0 ; i < pList->GetCount(); i ) { CString sInFileName; pList->GetText(i,sInFileName); CFile infile; if(!infile.Open(sInFileName,CFile::modeRead)) { 错误提示… return -1; } dwFileLength = infile.GetLength(); if(i==0) { if(dwFileLength>512) { sOut.Format(_T("文件%S不是一个有效的引导区文件,请使用[功能3]裁减该文件!"),sInFileName); return -1; } } if(i==0)//对0扇区文件进行特殊处理 { pBuf = new byte[BlOCKSIZE]; ::memset(pBuf,0,BlOCKSIZE); infile.Read(pBuf,dwFileLength); if(pBuf[510]!=0x55) pBuf[510]=0x55; if(pBuf[511]!=0xAA) pBuf[510]=0xAA; outfile.Write(pBuf,BlOCKSIZE); dwFileLength = BlOCKSIZE; } else { pBuf = new byte[dwFileLength]; infile.Read(pBuf,dwFileLength); outfile.Write(pBuf,dwFileLength); } infile.Close() ; delete[] pBuf; count = dwFileLength; pProgCtrl->SetPos((int)(count*100/FLOPYBYTESIZE)); } #ifdef ADISKMODE //3.补充剩余的软盘字节为0 DWORD dwRet = FLOPYBYTESIZE-count; pBuf = new byte[dwRet]; memset(pBuf,0,dwRet); outfile.Write(pBuf,dwRet); delete[] pBuf; #endif outfile.Close() ; //end 显示设置 省略… return 0; }3.2 写镜像文件到软盘代码
UINT FuncWriteFlopy(LPVOID pDialog) { //begin显示设置 省略… int nTotalBlocks = 80*18*2; //1.打开A驱动器 HANDLE hFile = CreateFile(_T("\\\\.\\A:"), GENERIC_WRITE, FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL); if(hFile==NULL) { sOut = _T("不能打开驱动器A");//… return -1; } PBYTE pBuffer = (PBYTE)malloc(BlOCKSIZE); if(pBuffer==NULL) { sOut = _T("开辟内存空间失败!");//… return -1; } memset(pBuffer,0,BlOCKSIZE); //2.打开镜像文件 CFile fInFile; BOOL b = fInFile.Open(pCurDlg->m_ImgFileName, CFile::modeRead); if(!b) { sOut.Format(_T("不能打开镜像文件%s!"),pCurDlg->m_ImgFileName); … return -1; } //3.分块写入镜像文件 DWORD dwImgLen = fInFile.GetLength(); for(int i=0;i4、操作系统编写=dwImgLen) break;//镜像文件写入完毕 #endif if(dwLen!=BlOCKSIZE) { sOut.Format(_T("写入镜像文件%s失败,请检查软驱!"),pCurDlg->m_ImgFileName); //… return -1; } pProgCtrl->SetPos((int)(i*100/nTotalBlocks)); } //4.关闭文件 fInFile.Close(); CloseHandle(hFile); free(pBuffer); //end 显示设置 pProgCtrl->SetPos(100); sOut.Format(_T("镜像文件%s写入软驱成功!"),pCurDlg->m_ImgFileName); //… return 0; }
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 = 13h, AL = 01h mov bx, 000ch ; 页号为0(BH = 0) 黑底红字(BL = 0Ch,高亮) mov dl, 0 int 10h ; int 10h ret BootMessage: db " Hello, OS world!" times 510-($-$$) db 0 ;填充剩下的空间,使生成的二进制代码恰好为512字节 dw 0aa55h ; 引导扇区需要以55AA结束4.4 用NASM编译
nasm boot.asm -o boot.bin
4.5 写入镜像文件及运行
按照2.1节所示的步骤把boot.Bin生成镜像文件,然后再写入软盘。下图是我再VMWare下的运行结果:
图4 系统运行显示
4.6 系统的其它功能实现
读取硬盘扇区,BIOS中断向量替换,实现文件系统,实虚模式转换及磁盘文件加载由于自己水平有限,不能详细介绍,网上有许多高手已经实现得很好了。如果感兴趣,可以参考相应的网址。详细请见:
结语
本文中的部分代码来自网上及林永君老师的课件,在此表示感谢。当然,单纯做一个操作系统来说,其现实的意义已不是太大。但对于更好的了解PC机的运行机制及操作系统的中断向量,系统调动及实模式及虚模式还是有很大的意义的。另外,也可以为Linux或者Windows下的驱动及系统开发打下一个良好的基础。
下载本文示例代码
简易软盘镜像工具的实现及操作系统编写初步简易软盘镜像工具的实现及操作系统编写初步简易软盘镜像工具的实现及操作系统编写初步简易软盘镜像工具的实现及操作系统编写初步简易软盘镜像工具的实现及操作系统编写初步简易软盘镜像工具的实现及操作系统编写初步简易软盘镜像工具的实现及操作系统编写初步简易软盘镜像工具的实现及操作系统编写初步简易软盘镜像工具的实现及操作系统编写初步简易软盘镜像工具的实现及操作系统编写初步简易软盘镜像工具的实现及操作系统编写初步简易软盘镜像工具的实现及操作系统编写初步