实验目的<编辑>
? ? ? ?
熟悉hit-oslab实验环境;
建立对操作系统引导过程的深入认识; 掌握操作系统的基本开发过程;
能对操作系统代码进行简单的控制,揭开操作系统的神秘面纱。
实验内容<编辑>
此次实验的基本内容是: 1. 2. 3.
阅读《Linux内核完全注释》的第6章,对计算机和Linux 0.11的引导过程进行初步的了解;
按照下面的要求改写0.11的引导程序bootsect.s 有兴趣同学可以做做进入保护模式前的设置程序setup.s。
改写bootsect.s主要完成如下功能: 1.
bootsect.s能在屏幕上打印一段提示信息“XXX is booting...”,其中XXX是你给自己的操作系统起的名字,例如LZJos、Sunix等(可以上论坛上秀秀谁的OS名字最帅,也可以显示一个特色logo,以表示自己操作系统的与众不同。) 改写setup.s主要完成如下功能: 1. 2. 3.
bootsect.s能完成setup.s的载入,并跳转到setup.s开始地址执行。而setup.s向屏幕输出一行\。
setup.s能获取至少一个基本的硬件参数(如内存参数、显卡参数、硬盘参数等),将其存放在内存的特定地址,并输出到屏幕上。
setup.s不再加载Linux内核,保持上述信息显示在屏幕上即可。
实验报告<编辑>
在实验报告中回答如下问题: 1.
有时,继承传统意味着别手蹩脚。x86计算机为了向下兼容,导致启动过程比较复杂。请找出x86计算机启动过程中,被硬件强制,软件必须遵守的两个“多此一举”的步骤(多找几个也无妨),说说它们为什么多此一举,并设计更简洁的替代方案。
评分标准<编辑>
? ? ? ? ? ? ? bootsect显示正确,1020% bootsect正确读入setup,10% setup显示正确,10% setup获取硬件参数正确,5% setup正确显示硬件参数,5% tools/build.c修改正确,1020% 实验报告,5060% 实验提示<编辑>
操作系统的boot代码有很多,并且大部分是相似的。本实验仿照Linux-0.11/boot目录下的bootsect.s和setup.s,以剪裁它们为主线。当然,如果能完全从头编写,并实现实验所要求的功能,是再好不过了。
同济大学赵炯博士的《Linux内核0.11完全注释(修正版V3.0)》(以后简称《注释》)的第6章是非常有帮助的参考,实验中可能遇到的各种问题,几乎都能找到答案。可以在“资料和文件下载”中下载到该书的电子版。同目录中,校友谢煜波撰写的《操作系统引导探究》也是一份很好的参考。
需要注意的是,oslab中的汇编代码使用as86编译,语法和汇编课上所授稍有不同。 下面将给出一些更具体的“提示”。这些提示并不是实验的一步一步的指导,而是罗列了一些实验中可能遇到的困难,并给予相关提示。它们肯定不会涵盖所有问题,也不保证其中的每个字都对完成实验有帮助。所以,它们更适合在你遇到问题时查阅,而不是当作指南一样地亦步亦趋。本书所有实验的提示都是秉承这个思想编写的。
Linux 0.11相关代码详解
boot/bootsect.s、boot/setup.s和tools/build.c是本实验会涉及到的源文件。它们的功能详见《注释》的6.2、6.3节和16章。
如果使用Windows下的环境,那么要注意Windows环境里提供的build.c是一个经过修改过的版本。Linus Torvalds的原版是将0.11内核的最终目标代码输出到标准输出,由make程序将数据重定向到Image文件,这在Linux、Unix和Minix等系统下都是非常有效的。但Windows本身的缺陷(也许是特色)决定了在Windows下不能这么做,所以flyfish修改了build.c,将输出直接写入到Image(flyfish是写入到Boot.img文件,我们为了两个环境的一致,也为了最
大化地与原始版本保持统一,将其改为Image)文件中。同时为了适应Windows的一些特殊情况,他还做了其它一些小修改。
引导程序的运行环境
引导程序由BIOS加载并运行。它活动时,操作系统还不存在,整台计算机的所有资源都由它掌控,而能利用的功能只有BIOS中断调用。
完成bootsect.s的屏幕输出功能
首先来看完成屏幕显示的关键代码如下:
! 首先读入光标位置 mov ah,#0x03 xor bh,bh int 0x10
! 显示字符串“LZJos is running...” mov cx,#25 mov bx,#0x0007 mov bp,#msg1 mov ax,#0x1301 int 0x10
inf_loop: jmp inf_loop
! 要显示的字符串长度
! page 0, attribute 7 (normal) ! write string, move cursor
! 后面都不是正经代码了,得往回跳呀
! msg1处放置字符串
msg1:
.byte 13,10
! 换行+回车
.ascii \ .byte 13,10,13,10 !设置引导扇区标记0xAA55 .org 510
! 两对换行+回车
boot_flag: .word 0xAA55
! 必须有它,才能引导
接下来,将完成屏幕显示的代码在开发环境中编译,并使用linux-0.11/tools/build.c将编译后的目标文件做成Image文件。
编译和运行
Ubuntu上先从终端进入~/oslab/linux-0.11/boot/目录。Windows上则先双击快捷方式“MinGW32.bat”,将打开一个命令行窗口,当前目录是oslab,用cd命令进入linux-0.11\\boot。无论那种系统,都执行下面两个命令编译和链接bootsect.s:
as86 -0 -a -o bootsect.o bootsect.s ld86 -0 -s -o bootsect bootsect.o
其中-0(注意:这是数字0,不是字母O)表示生成8086的16位目标程序,-a表示生成与GNU as和ld部分兼容的代码,-s告诉链接器ld86去除最后生成的可执行文件中的符号信息。 如果这两个命令没有任何输出,说明编译与链接都通过了。Ubuntu下用ls -l可列出下面的信息:
-rw--x--x 1 root root 544 Jul 25 15:07 bootsect -rw------ 1 root root 257 Jul 25 15:07 bootsect.o -rw------ 1 root root 686 Jul 25 14:28 bootsect.s
Windows下用dir可列出下面的信息:
2008-07-28 20:14 544 bootsect 2008-07-28 20:14 924 bootsect.o 2008-07-26 20:13 5,059 bootsect.s
其中bootsect.o是中间文件。bootsect是编译、链接后的目标文件。
需要留意的文件是bootsect的文件大小是544字节,而引导程序必须要正好占用一个磁盘扇区,即512个字节。造成多了32个字节的原因是ld86产生的是Minix可执行文件格式,这样的可执行文件处理文本段、数据段等部分以外,还包括一个Minix可执行文件头部,它的结构如下:
struct exec {
unsigned char a_magic[2]; //执行文件魔数 unsigned char a_flags;
unsigned char a_cpu; //CPU标识号
unsigned char a_hdrlen; //头部长度,32字节或48字节 unsigned char a_unused; unsigned short a_version;
long a_text; long a_data; long a_bss; //代码段长度、数据段长度、堆长度
long a_entry; //执行入口地址 long a_total; //分配的内存总量 long a_syms; //符号表大小 };
算一算:6 char(6字节)+1 short(2字节)+6 long(24字节)=32,正好是32个字节,去掉这32个字节后就可以放入引导扇区了(这是tools/build.c的用途之一)。
对于上面的Minix可执行文件,其a_magic[0]=0x01,a_magic[1]=0x03,a_flags=0x10(可执行文件),a_cpu=0x04(表示Intel i8086/8088,如果是0x17则表示Sun公司的SPARC),所以bootsect文件的头几个字节应该是01 03 10 04。为了验证一下,Ubuntu下用命令“hexdump -C bootsect”可以看到:
00000000 01 03 10 04 20 00 00 00 00 02 00 00 00 00 00 00 |.... ...........|
00000010 00 00 00 00 00 00 00 00 00 82 00 00 00 00 00 00 |................|
00000020 b8 c0 07 8e d8 8e c0 b4 03 30 ff cd 10 b9 17 00 |.........0......|
00000030 bb 07 00 bd 3f 00 b8 01 13 cd 10 b8 00 90 8e c0 |....?...........|
00000040 ba 00 00 b9 02 00 bb 00 02 b8 04 02 cd 13 73 0a |..............s.|
00000050 ba 00 00 b8 00 00 cd 13 eb e1 ea 00 00 20 90 0d |............. ..|
00000060 0a 53 75 6e 69 78 20 69 73 20 72 75 6e 6e 69 6e |.Sunix is runnin|
00000070 67 21 0d 0a 0d 0a 00 00 00 00 00 00 00 00 00 00 |g!..............|
00000080 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| *
00000210 00 00 00 00 00 00 00 00 00 00 00 00 00 00 55 aa