您的位置:首页 > 其它

哈工大操作系统实验1—系统初始化

2015-07-12 20:49 344 查看
此次实验的基本内容是:

阅读《Linux内核完全注释》的第6章,对计算机和Linux 0.11的引导过程进行初步的了解;
按照下面的要求改写0.11的引导程序bootsect.s
修改build.c,以便可以使用 make BootImage命令

改写bootsect.s主要完成如下功能:

bootsect.s能在屏幕上打印一段提示信息“XXX is booting...”,其中XXX是你给自己的操作系统起的名字,例如LZJos、Sunix等(可以上论坛上秀秀谁的OS名字最帅,也可以显示一个特色logo,以表示自己操作系统的与众不同。)

完成bootsect.s的屏幕输出功能

首先来看完成屏幕显示的关键代码如下:

! 首先读入光标位置
    mov	ah,#0x03		
    xor	bh,bh
    int	0x10

    ! 显示字符串“LZJos is running...”
    mov	cx,#25			! 要显示的字符串长度
    mov	bx,#0x0007		! page 0, attribute 7 (normal)
    mov	bp,#msg1
    mov	ax,#0x1301		! write string, move cursor
    int	0x10

inf_loop:
    jmp	inf_loop		! 后面都不是正经代码了,得往回跳呀
    ! msg1处放置字符串

msg1:
    .byte 13,10			! 换行+回车
    .ascii "LZJos is running..."
    .byte 13,10,13,10			! 两对换行+回车
    !设置引导扇区标记0xAA55
    .org 510
boot_flag:
    .word 0xAA55			! 必须有它,才能引导

接下来,将完成屏幕显示的代码在开发环境中编译,并使用linux-0.11/tools/build.c将编译后的目标文件做成Image文件。

这里改动
mov	cx,#25			! 要显示的字符串长度
和
msg1:
    .byte 13,10			! 换行+回车
    .ascii "LZJos is running..."
    .byte 13,10,13,10			! 两对换行+回车
    !设置引导扇区标记0xAA55


修改你要显示的内容及计算长度,其中13算一个,10算一个,字母或空格算1个
修改bootsect.s

! Print some inane message

	mov	ah,#0x03		! read cursor pos
	xor	bh,bh
	int	0x10
	
	mov	cx,#27                  !修改这里
	mov	bx,#0x0007		! page 0, attribute 7 (normal)
	mov	bp,#msg1
	mov	ax,#0x1301		! write string, move cursor
	int	0x10


及(msg1可以改成很多种)
msg1:
	.byte 13,10
	.ascii "Jinux OS is booting ..."
	.byte 13,10,13,10


修改build.c

build.c从命令行参数得到bootsect、setup和system内核的文件名,将三者做简单的整理后一起写入Image。其中system是第三个参数(argv[3])。当“make all”或者“makeall”的时候,这个参数传过来的是正确的文件名,build.c会打开它,将内容写入Image。而“make BootImage”时,传过来的是字符串"none"。所以,改造build.c的思路就是当argv[3]是"none"的时候,只写bootsect和setup,忽略所有与system有关的工作,或者在该写system的位置都写上“0”。

修改工作主要集中在build.c的尾部,请斟酌。

当按照前一节所讲的编译方法编译成功后,run,就得到了如图3所示的运行结果,和我们想得到的结果完全一样。

因为传过来的是字符串"none",所以只要在build.c判断一下第三个值是否为none,修改最下面

bulid.c之前为

if ((id=open(argv[3],O_RDONLY,0))<0)  
            die("Unable to open 'system'");  
    //  if (read(id,buf,GCC_HEADER) != GCC_HEADER)  
    //      die("Unable to read header of 'system'");  
    //  if (((long *) buf)[5] != 0)  
    //      die("Non-GCC header of 'system'");  
        for (i=0 ; (c=read(id,buf,sizeof buf))>0 ; i+=c )  
            if (write(1,buf,c)!=c)  
                die("Write call failed");  
        close(id);  
        fprintf(stderr,"System is %d bytes.\n",i);  
        if (i > SYS_SIZE*16)  
            die("System is too big");  
        return(0);  </span></span>
改为

if(strcmp("none",argv[3]) == 0)    //添加判断
          return 0;
	if ((id=open(argv[3],O_RDONLY,0))<0)
          die("Unable to open 'system'");
//	if (read(id,buf,GCC_HEADER) != GCC_HEADER)
//		die("Unable to read header of 'system'");
//	if (((long *) buf)[5] != 0)
//		die("Non-GCC header of 'system'");
	for (i=0 ; (c=read(id,buf,sizeof buf))>0 ; i+=c )
		if (write(1,buf,c)!=c)
			die("Write call failed");
	close(id);
	fprintf(stderr,"System is %d bytes.\n",i);
	if (i > SYS_SIZE*16)
		die("System is too big");
        
	return(0);</span>
附report1:
1.有时,继承传统意味着别手蹩脚。x86计算机为了向下兼容,导致启动过程比较复杂。请找出x86计算机启动过程中,被硬件强制,软件必须遵守的两个“多此一举”的步骤(多找几个也无妨),说说它们为什么多此一举,并设计更简洁的替代方案。
答:1)x86CPU启动时为了向下兼容16位使用实模式:纯16位无保护执行环境。对于80286或以上的CPU通过A20 GATE来控制A20地址线。 
       技术发展到了80286,虽然系统的地址总线由原来的20根发展为24根,这样能够访问的内存可以达到2^24=16M,但是Intel在设计80286时提出的目标是向下兼容,
       所以在实模式下,系统所表现的行为应该和8086/8088所表现的完全一样,也就是说,在实模式下,80386以及后续系列应该和8086/8088完全兼容仍然使用A20地址线。
       所以高级芯片为了运行以前的程序,不得不保留实模式。所以说80286芯片存在一个BUG:它开设A20地址线。
       如果程序员访问100000H-10FFEFH之间的内存,系统将实际访问这块内存。进入实模式多此一举,可以直接进入保护模式。
       解决方案:是不向下兼容直接进入32位的保护模式,经管在Intel 80286手册中已经提出了虚地址保护模式,但实际上它只是一个指引,真正的32位地址出现在Intel 80386上。
       保护模式本身是80286及以后兼容处理器序列之后产成的一种操作模式,它具有许多特性设计为提高系统的多道任务和系统的稳定性。
       例如内存的保护,分页机制和硬件虚拟存储的支持。现代多数的x86处理器操作系统都运行在保护模式下。

    2)当PC的电源打开后,80x86结构的CPU将自动进入实模式,并从地址0xFFFF0开始自动执行程序代码,这个地址通常是ROM—BIOS中的地址。
	   PC机的BIOS将执行某些系统的检测,并在物理地址0处开始初始化中断向量。此后将启动设备的第一个扇区512字节读入内存绝对地址0x7C00处。
	   因为当时system模块的长度不会超过0x80000字节大小512KB,所以bootsect程序把system模块读入物理地址0x10000开始位置处时并不会覆盖
	   在0x90000处开始的bootsect和setup模块,多此一举的是system模块移到内存中相对靠后的位置,以便加载系统主模块。 
       解决方案是在保证操作系统启动引导成功的前提下尽量扩大ROM—BIOS的内存寻址范围,以达到不需要读入靠后的位置处。

2.操作系统的引导程序都完成哪些功能?你知道几个操作系统引导程序?分别是什么?
    1)操作系统的引导程序一般完成识别主机的某些特性,
    2)确保内核被正确加载;
    3)加载内核到内存;
    4)将系统控制权交给内核;
    5)通知内核所需要的根文件系统的位置;
    6)确定根文件的设备号;
    7)将CPU由实模式切换为保护模式等功能。
    我知道的操作系统的引导程序有:
    1)NTLDR,它是windows nt 4.0/windows 2000/windows xp/windows server 2003的引导文件
    2)GNU GRUB,它是是一个来自GNU项目的多操作系统启动程序。GRUB是多启动规范的实现,它允许用户可以在计算机内同时拥有多个操作系统,
	   并在计算机启动时选择希望运行的操作系统。</span>


由于实验简化,setup.s的相关实验已经不作要求,此处可参考往届学长学姐实验博客
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: