首页
社区
课程
招聘
[原创]操作系统开发之实现多系统引导
发表于: 2007-12-22 16:39 10373

[原创]操作系统开发之实现多系统引导

HSQ 活跃值
8
2007-12-22 16:39
10373
一. 一点说明
   一直都想写一个属于自己的操作系统,可是总是由于这样或那样的原因,一直没有集中精力去搞下来,暂时也没时间继续了。现公布一点自己些的垃圾,写得不好,请大家不要抛砖头砸我

二.设计与实现
  硬盘多系统引导功能基本有两部分组成,包括引导启动代码安装和导启动代码. 考虑到测试的环境和处理问题的方便性, 安装程序为没有使用TASM来写。就拿从硬盘定位一个引导文件来说吧, 就得考虑该分区的文件系统类型是VFAT还是NTFS或是EXT2之类情况。由于我们的主要目的是实现多系统引导, 为了不喧宾夺主就将主要精力花在引导的设计上,至于文件系统的设计与处理,等以后有机会在于大家探讨  安装部分必须完成的任务有:保存原MBR内容,修改分区类型,恢复MBR内容,修改MBR启动代码,其他的可以安自己需要添加。
  对于多系统引导的设计与处理,考虑到代码可移植性与稳定性,没有采用默认开始执行的IP为0000:7c00,而是选择程序自己动态调整;另外为了便于测试和改进代码应该具有重定位功能,在
非引导环境下也应当能够执行(不然你没法DEBUG

三.具体代码
  每个部分都有详细的注释,相信大家都该能够看明白.

/* MDISK.C 功能简介:
	1.)保存MBR内容
	2.)修改分区类型
	3.)删除分区
	4.)恢复MBR内容
	5.)修改MBR启动代码
*/
#include <stdio.h>
#include <conio.h>
#include <bios.h>

void main(void)
{
	FILE *fp;
	unsigned char buff[512];
	int x,y,z,ch,i,s;
	/* read MBR 
    int biosdisk(int cmd,int drive,int head,int track,int sector,int nsects,void *buffer)
	*/
	/*读取MBR并检测是否改动*/
	biosdisk(2,0x80,0,0,1,1,buff);
	if(buff[3]=='H'&&buff[4]=='S'&&buff[5]=='Q')
	{
		printf("\n MBR had been modifled by HSQ ");
		printf("\n Do you want to Overlay MBR (y/n) :");
		for(ch='*';ch!='y'&&ch!='n';)ch=getchar();
		if(ch=='y')
		{
			printf("\n Enter (1-9) sector index to be read :"); /* 49-57*/
			for(x='*';x<'1'||x>'9';)x=getchar();
			biosdisk(2,0x80,0,0,x-48+10,1,buff); /* 2-10 */
			biosdisk(3,0x80,0,0,1,1,buff);
			printf("\n Overlay Complete !");
		}
	}
	else
	{	/*在处理原始MBR前,必须备份*/	
		printf("\n Save MBR to (1-9) sector index :");
		for(x='*';x<'1'||x>'9';)x=getchar();
		biosdisk(3,0x80,0,0,x-48+10,1,buff);
		printf("\n Save MBR Complete !");
	}

	/*显示操作菜单*/
	while(1)
	{
		clrscr();
		printf("\n\n Disk Partition type information :");
		for(x=0x1c2;x<=0x1f2;x+=16)printf("%02x",buff[x]);
		printf("\n\n *************** Menu Title ******************");
		printf("\n *                                           *");
		printf("\n *     1--> Change partition type            *");
		printf("\n *                                           *");
		printf("\n *     2--> Delete partition                 *");
		printf("\n *                                           *");
		printf("\n *     3--> Recover MBR                      *");
		printf("\n *                                           *");
		printf("\n *     4--> Load LDMBR File                  *");
		printf("\n *                                           *");
		printf("\n *     5--> Load BOOT File                   *");
		printf("\n *                                           *");
		printf("\n *     0--> Quit this Program                *");
		printf("\n *                                           *");
		printf("\n *  MDISK v1.23 by Huang Shiquan  2007-10-06 *");
		printf("\n *                                           *");
		printf("\n *********************************************");
		printf("\n Enter your choice :");
		for(ch='*';ch<'0'||ch>'5';)ch=getchar();
		if(ch=='0')break;
		if(ch=='1')
		{
			printf("\n Partition do you want to change (1-4) :");
			for(x='*';x<'1'||x>'4';)x=getchar();
			printf("\n Current partition type is %02x",buff[0x1c2+(x-49)*16]);
			printf("\n Enter new partition type :");
			scanf("%02x",&y);
			buff[0x1c2+(x-49)*16]=y;
			biosdisk(3,0x80,0,0,1,1,buff);
			printf("\n Change Complete !");
			getch();
		}
		if(ch=='2')
		{
			printf("\n Partition do you want to delete (1-4) :");
			for(x='*';x<'1'||x>'4';)x=getchar();
			for(x-=49,y=0;y<(3-x)*16;y++)
			{
				z=0x1be+x*16+y;
				buff[z]=buff[z+16];
			}
			for(y=0;y<16;y++)buff[0x1ee+y]=0;
			biosdisk(3,0x80,0,0,1,1,buff);
			printf("\n Delete Complete !");
			getch();
		}
		if(ch=='3')								/*调用备份扇区覆盖启动扇区*/
		{
			printf("\n Enter (1-9) sector index to read be :");
			for(x='*';x<'1'||x>'9';)x=getchar();/*HEX: 31 - DEC: 49 - ASCII: 1*/
			biosdisk(2,0x80,0,0,x-48+10,1,buff);
			biosdisk(3,0x80,0,0,1,1,buff);
			printf("\n Recover Complete !");
			getch();
		}
		if(ch=='4')								/*装载启动扇区文件*/
		{
			s=1;
			if((fp=fopen("LDMBR.COM","rb")) == NULL)
			{
				printf("\n Open file LDMBR.COM error !\n");
				break;
			}
			for(i=2;i<=10;i++)					/*执行前检查被覆盖分区是否含有MBR信息*/
			{
				biosdisk(2,0x80,0,0,i,1,buff);
				if(buff[0x1fe]==0x55&&buff[0x1ff]==0xaa)
				{
					printf("\n Warming : The [%d] sector have MBR information!",i);
				    printf("\n Are you sure to continue work (y/n) :");
					for(ch='*';ch!='y'&&ch!='n';)ch=getchar();
					if(ch=='n')
					{
						s=0;break;
					}
				}
			}
			for(i=1;s==1&&i<=10;i++)				/*读入10个扇区大小的文件*/
			{
				for(x=0;x<0x200;x++)buff[x]=0;	/*初始化缓冲区*/
				fread(buff,0x200,1,fp);
				biosdisk(3,0x80,0,0,i,1,buff);
			}
			if(s==1)printf("\n Modify Complete !");
			fclose(fp);
			getch();
		}
		if(ch=='5')								/*装载启动扇区文件*/
		{
			s=1;
			if((fp=fopen("Boot.bin","rb")) == NULL)
			{
				printf("\n Open file Boot.BIN error !\n");
				break;
			}
			for(i=1;s==1&&i<=1;i++)			/*最多读入1个扇区大小的文件*/
			{
				for(x=0;x<0x200;x++)buff[x]=0;	/*初始化缓冲区*/
				fread(buff,0x200,1,fp);
				biosdisk(3,0x80,0,0,i,1,buff);
			}
			if(s==1)printf("\n Modify Boot Complete !");
			fclose(fp);
			getch();
		}
	}
	return;
}


说明: 此部分我只是具体实现了读取MBR并检测是否改动和备份,安装LDMBR和恢复MBR(功能4和5),其他的没有测试.

[培训]内核驱动高级班,冲击BAT一流互联网大厂工作,每周日13:00-18:00直播授课

收藏
免费 7
支持
分享
最新回复 (16)
雪    币: 381
活跃值: (140)
能力值: ( LV13,RANK:330 )
在线值:
发帖
回帖
粉丝
2
;   LDMBR.ASM 启动代码功能:
;	(1) 根据用户输入的分区索引号,把对应的操作系统的原MBR内容装入内存的0000:7c00处;
;	(2) 检测硬盘分区表变动,根据需要决定是否修改LDMBR分区信息并保存;
;	(3) 将控制权还给原MBR启动代码.
;	(4) 内含默认MBR启动代码,以便在没有可引导的MBR时使用.
;	(5) 支持DOS下直接远行LDMBR引导MBR.
;	(6) LDMBR添加代码自动定位功能,一次编译无需修改
;	一般情况零道零面,除BootSector(启动扇区),也就是硬盘的第一个扇区,存在重要数据
;  包括MBR,DPT,BRID三部分. 其余的62个扇区全部为空闲,每磁道最大扇区数为63.
.386
.model tiny

code	segment byte public 'CODE' use16
	assume cs:code,ds:code
	org 100h

start:
	call	begin
	db	'HSQ'				;检测标志
begin:
	cli					;关中断
	pop	ax
	sub	ax, 3				;ax=7C00 (DOS下不可能,需重定位)
	mov     sp, ax				;SP=7C00
	mov	bp, ax				;bp保存入口基址,为字符串寻址参照值
	push	cs
	push	cs
	push	cs
	pop	ds				;DS=0 (DOS下不可能,需重定位)
	pop	ss				;SS=0
	pop	es				;ES=0
	sti					;中断允许

	push	ax				;ax为入口基址,保存作为字符串寻址参照值
	mov	bx, ax				;bx保存,重定位标志
	add	bx, 200h
	mov	cx, 02h
	mov	ax, 020Ah			;es=0000h    bx=7c00+200h
	mov	dx, 80h
	int	13h				;将硬盘0道0面2扇区读入10个扇区0000:7c00处后	
         
	pop	bx				;保存入口基址 bx
	call	ShowAuthorInformation		;输出版权信息
			
	mov     ax, 1000h
	mov	es, ax	
	mov	di, bx	
	add	di, offset next	- 100h		;剔除已经执行部分
	push	ax
	push	di				;指向目的地址
	mov	si, bx				;设置源地址 ds:si
	mov	di, bx				;设置目的地址 es:di,di=es(保证偏移相同)
	mov     cx, offset mbr_end - 100h	;设置 cx 为传输长度
	cld					;设置正向传输
	rep	movsb				;把启动代码搬到1000::offset next处
	retf					;跳转到1000:next处
next:			
	push	ds
	push	es				
	pop	ds				;ds=1000h	
	pop	ax				;es=0000h
	test	ax, ax
	je	normalboot
	xor	ax, ax				;确保DOS下也能顺利装在原MBR到0000:7c00处
	mov	bx, 7c00h
normalboot:
	mov	es, ax
	call	ClearScreen			;清屏

	push	bx
	mov	bx, offset folengthtable - 100h
	add	bx, bp
	mov	di, offset fouctiontable - 100h
	add	di, bp				;字符串寻址参照值
showtitle:
	mov	si, [di]
	add	si, bp
	mov	cx, [bx]
	call	dbgprint			;显示功能信息
	add	di, 2
	add	bx, 2
	cmp	word ptr [di], 0	
	jne	showtitle
	pop	bx

	mov	si, offset msg_01 - 100h
	add	si, bp				;字符串寻址参照值
	mov	cx, msg_01_len
	call	dbgprint			;显示输入提示信息
read:
	xor	ah, ah
	int	16h				;从键盘读字符
	cmp	al, '1'
	jb	read
	cmp	al, '9'
	ja	read				;检查字符的合法性
	and	al, 0fh				;将高四位清零
	add	al, 0ah				;前10个扇区默认备MBR占用
	mov	cl, al				;设置扇区号: 用户输入值	
	xor	ch, ch				;设置磁道号: 0
rmbr:
	mov	ax, 0201h			;es=0000h    bx=7c00
	mov	dx, 80h
	int	13h				;将硬盘0道0面指定扇区读入0000:7c00处
	cmp	word ptr es:[bx].1feh, 0AA55h	;检验引导区是否合法
	je	loadDPT
	mov	si, offset msg_02 - 100h
	add	si, bp
	mov	cx, msg_02_len
	call	dbgprint			;显示出错信息提示信息

	mov	ah, 1h
	mov	ch, 10h
	mov	cl, 0     
	int	10h				;关闭光标
	xor	ah, ah
	int	16h				;暂停
reboot:
	xor	ax, ax
	mov	bx, ax
	dec	ax
	mov	es, ax				;设置重启PC
loadmbr:
	call	ClearScreen
	xor	ax, ax
	mov	ss, ax
	mov	sp, bx
	mov	bp, sp
	push	es
	push	bx
	retf					;将控制权还给原MBR启动代码
loadDPT:
	push	es				;es=0000
	push	ds				;ds=1000
	pop	es				;es=1000
	pop	ds				;ds=0000
	lea	si, [bx+1BEh]			;bx=7c00
						;设置源地址 ds:si=0000:7DBEh 
	lea	di, [bp+1BEh]                   ;设置目的地址 es:di=1000:7DBEh  
	mov	cx, 40h				;10h*4
	push	si
	push	di
	repe	cmpsb				;检测是否有必要修改分区表
	pop	di
	pop	si
	test	cx, cx
	je	same_DPT
	push	si
	mov	ax, es
	push	ds
	mov	ds, ax
	mov	si, offset msg_03 - 100h
	add	si, bp
	mov	cx, msg_03_len
	call	dbgprint			;显示修改分区表提示信息
	pop	ds
	pop	si
reread:
	xor	ah, ah
	int	16h				;从键盘读字符(等待用户确认)
	cmp	al, 'n'
	je	same_DPT
	cmp	al, 'N'
	je	same_DPT
	cmp	al, 'y'
	je	upate_DPT
	cmp	al, 'Y'
	jne	reread
upate_DPT:
	mov	cx, 40h
	rep	movsb				
	xchg	bx, bp				;bx=7c00, bp=0100			
	mov	ax, 0301h			;es=1000, bx=(0100)7c00
	mov	cx, 01h	
	int	13h				;修改并保存分区信息
	xchg	bx, bp	
	jmp	reboot				;重启兼容实际CMOS程序(在VMware中可以不重启)
	cmp	bx, bp				;检测DOS还是启动模式
	jz      reboot
same_DPT:
	push	ds				;ds=0000
	pop	es				;es=0000
	jmp	loadmbr				;将控制权还给原MBR启动代码	
;未了稳定和兼容,MBR启动扇区只使用1BEH个字节,防止覆盖DPT和BRID
currentcodelen = $ - start
leavecodelen   = 1beh - currentcodelen		;对齐LDMBR
	db	40h + leavecodelen dup(?),55h,0AAh
;*******************************以下为程序所需的数据*******************************
yyy	equ   8                           ;上边框行值
xxx	equ   60                          ;边框长度减二
color	dw    5fh                         ;字符串颜色值
gtable		dw g1-100h,g2-100h,g3-100h,g4-100h,g5-100h,g6-100h,g7-100h,g8-100h,\
                   g9-100h,0
fouctiontable	dw fouction_00-100h,fouction_01-100h,fouction_02-100h,fouction_03-100h,\
                   fouction_04-100h,0
folengthtable	dw fouction_01-fouction_00,fouction_02-fouction_01,fouction_03-fouction_02,\
                   fouction_04-fouction_03,msg_01-fouction_04
chartable	dw char00a-100h,char00b-100h,char00c-100h,char01-100h,char02-100h,0
lengthtable	dw char00b-char00a,char00c-char00b,char01-char00c,char02-char01,\
                   fouction_00-char02
g1     db   201,xxx dup(205),187         
g2     db   186,xxx dup(' '),186
g3     db   186,xxx dup(' '),186
g4     db   186,xxx dup(' '),186
g5     db   204,xxx dup(205),185         
g6     db   186,xxx dup(' '),186
g7     db   199,xxx dup(196),182
g8     db   186,xxx dup(' '),186
g9     db   200,xxx dup(205),188         ;画边框数据
gg     equ  $-g9                         ;边框长度
xx     equ  (80-gg)/2                    ;让边框水平居中显示
char00a		db  'SoftWare Version Information 1.01 Compiled By Huang Shiquan' 
char00b		db  'Break Hard Disk Saving Card Program'                   
char00c		db  'This program is used to break the hard disk saving card'       
char01		db  219,219,219,178,178,177,177,176,176, ,\
		    'HD Anti-Virus & Security System', ,176,176,177,177,178,178,3 dup (219)        
char02		db  '(C)opyRight HSQ persion program company 2007.10.06' 
fouction_00	db  'Muility Opertation System Loader V1.25',0dh,0ah,0dh,0ah
fouction_01	db  '1.) Seclect One Opertation System For Loading',0dh,0ah
fouction_02	db  '2.) Set A Default Opertation System For Loading',0dh,0ah
fouction_03	db  '3.) Loading Mini DOS Opertation System By Huang Shiquan',0dh,0ah
fouction_04	db  '4.) Remove This Muility Opertation System Loader Program',0dh,0ah
msg_01		db  0dh,0ah,'Enter sector index (1-9) to load operation system :'
msg_01_len = $ - msg_01
msg_02		db  0dh,0ah,0dh,0ah,4 dup(20h),'Sorry, cant load MBR becuase its invalid.Recommend information for you:',\
		    0dh,0ah,'If this problem continue, please change another sector index to try again and ',\
		    0dh,0ah,'maybe solve this problem Now, Press any key to restart your PC'
msg_02_len = $ - msg_02
msg_03		db  0dh,0ah,0dh,0ah,4 dup(20h),'Warning, The Disk Partition Table will be replace, are you sure to do this',\
		    0dh,0ah,'Sure(Y), Cancel (N) ? :'
msg_03_len = $ - msg_03
;*******************************以下为应用子程序*******************************
ClearScreen:
	 pusha
         mov  ax, 0600h
         mov  bh, 7
         mov  cx, 0
         mov  dx, 184fh
         int  10h				;清屏
	 
         mov   dx, 0
         mov   ax, 2
         int   10h				;置光标在首位
	 popa
	 ret
dbgprint:
	push	ax
	push	bx
	mov	bx, 07h 
	mov	ah, 0eh
show_continue:
	mov	al, [si]
	int	10h
	inc	si
	loop	show_continue			;显示输入提示信息
	pop	bx
	pop	ax
	ret
ShowAuthorInformation:
	pusha
	push	cs
	pop	es
	mov	ax, 3				;显示版本信息
	int	10h				;置彩色文本方式80*25*16色

	mov	ah, 1h
	mov	ch, 10h
	mov	cl, 0     
	int	10h				;关闭光标
	         
	mov	si, offset gtable -100h
	add	si, bx				;bx为入口基址
	mov	dh, yyy				;起始行
show_frame:
	push	si
	mov	bp, [si]
	add	bp, bx				;待处理串
	pop	si
	mov	dl, xx				;起始列
	mov	cx, gg				;串长度
	push	bx
	mov	bx, 005fh
	mov	ax, 1301h
	int	10h				;BIOS中断调用
	pop	bx

	inc	dh
	add	si, 2
	cmp	word ptr [si], 0
	jne	show_frame			;显示边框  

	mov	si, offset chartable -100h
	add	si, bx
	mov	di, offset lengthtable -100h
	add	di, bx
	mov	ax, 1301h			;显示字符串,光标返回起始位
	mov	dh, yyy+1			;起始行
show_infromation:
	push	si
	mov	bp, [si]
	add	bp, bx				;待处理串
	pop	si
	push	bx
	mov	cx, [di]			;串长度
	mov	bx, 80
	sub	bx, cx
	shr	bx, 1
	mov	dl, bl				;让字符串水平居中显示
	mov	bx, 005fh
	mov	ax, 1301h
	int	10h
	pop	bx
	cmp	dh, yyy+3
	jbe	normal_addnum
	inc	dh
normal_addnum:
	inc	dh
	add	si, 2
	add	di, 2
	cmp	word ptr [si], 0
	jne	show_infromation		;显示字符串
         
	xor	ah, ah
	int	16h				;从键盘读字符

	mov	ah, 01h
	mov	ch, 0
	int	10h				;打开光标
	popa
	ret
mbr_end:
code	ends
end	start


讨论: 当修改分区表后,在VMware中可以不重启而直接引导相应系统;可是在实际PC机上却行不通.每次当我试着跟踪,进入到到实际的OS引导代码部分一段距离时,系统就会僵死,没法继续了.不知那位知道其原由,还望赐教.

三.效果截图和相关源码
  具体使用方法我就不说了,描述起来很麻烦的,能够看懂代码的应该就知道怎么用.我就是用这个来引导WINDOWS和LINUX以及自己的系统
代码一帖出来,都乱了 ,我也懒得慢慢调整, 不过附件中的源码是很工整的
上传的附件:
2007-12-22 16:41
0
雪    币: 324
活跃值: (91)
能力值: ( LV9,RANK:140 )
在线值:
发帖
回帖
粉丝
3
顶!无私分享自己的东西/心得的共享精神很棒!呵呵!

我想, 你的代码会对需要的朋友有帮助, 支持原创!
2007-12-22 18:09
0
雪    币: 321
活跃值: (271)
能力值: ( LV13,RANK:1050 )
在线值:
发帖
回帖
粉丝
4
biosdisk这个函数好像是在bc上用的吧? 在vc的环境下,没有这个函数。
2007-12-22 19:25
0
雪    币: 381
活跃值: (140)
能力值: ( LV13,RANK:330 )
在线值:
发帖
回帖
粉丝
5
C的代码用TC2.0编译,ASM的用TASM5.X编译
2007-12-22 19:34
0
雪    币: 486
活跃值: (13)
能力值: ( LV9,RANK:430 )
在线值:
发帖
回帖
粉丝
6
楼主汇编功力很深厚啊,佩服佩服。
2007-12-23 20:12
0
雪    币: 200
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
7
楼主。。。。
不知道说什么了   收藏
2007-12-23 23:16
0
雪    币: 647
活跃值: (564)
能力值: ( LV8,RANK:130 )
在线值:
发帖
回帖
粉丝
8
确实不错呀,支持楼主
2007-12-24 10:09
0
雪    币: 201
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
9
很好的 东西
谢谢楼主
正在学习中。。。。。
2007-12-25 02:51
0
雪    币: 200
活跃值: (21)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
10
大五?什么专业,难道也是医学?
2007-12-26 00:34
0
雪    币: 189
活跃值: (4810)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
11
很好的 东西
谢谢楼主
正在学习中。。。。。
2007-12-28 23:44
0
雪    币: 66
活跃值: (16)
能力值: ( LV8,RANK:130 )
在线值:
发帖
回帖
粉丝
12
很强大  nice  job:D
2007-12-29 13:54
0
雪    币: 200
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
13
谢谢楼主的分享!
2007-12-31 17:23
0
雪    币: 200
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
14
强人,
看了不少这方面资料
正打算动手操作
多谢分享~
2008-3-13 10:21
0
雪    币: 200
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
15
  yun le
2008-4-9 11:09
0
雪    币: 148
活跃值: (11)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
16
我功力太浅,还需向您学习
2008-4-11 15:58
0
雪    币: 200
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
17
强人,楼主
好好学习
2008-4-14 13:10
0
游客
登录 | 注册 方可回帖
返回
//