实验二 操作系统的引导

实验二 操作系统的引导

一、实验目的

  • 熟悉 hit-oslab 实验环境;

  • 建立对操作系统引导过程的深入认识;

  • 掌握操作系统的基本开发过程;

  • 能对操作系统代码进行简单的控制,揭开操作系统的神秘面纱。

二、实验内容

  1. 阅读《Linux 内核完全注释》的第 6 章,对计算机和 Linux 0.11 的引导过程进行初步的了解;
  2. 按照下面的要求改写 0.11 的引导程序 bootsect.s
  3. 有兴趣同学可以做做进入保护模式前的设置程序 setup.s。

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

  1. bootsect.s 能在屏幕上打印一段提示信息“XXX is booting…”,其中 XXX 是你给自己的操作系统起的名字,例如 LZJos、Sunix 等

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

  1. bootsect.s 能完成 setup.s 的载入,并跳转到 setup.s 开始地址执行。而 setup.s 向屏幕输出一行"Now we are in SETUP"。
  2. setup.s 能获取至少一个基本的硬件参数(如内存参数、显卡参数、硬盘参数等),将其存放在内存的特定地址,并输出到屏幕上。
  3. setup.s 不再加载 Linux 内核,保持上述信息显示在屏幕上即可。
相关代码文件

Linux 0.11 文件夹中的 boot/bootsect.sboot/setup.stools/build.c 是本实验会涉及到的源文件。它们的功能详见《注释》的 6.2、6.3 节和 16 章。

引导程序的运行环境

引导程序由 BIOS 加载并运行。它活动时,操作系统还不存在,整台计算机的所有资源都由它掌控,而能利用的功能只有 BIOS 中断调用。

实验中主要使用 BIOS 0x10 和 0x13 中断。

三、实验步骤

首先阅读赵炯博士的《Linux内核完全注释:基于0.11内核》第6章内容。

在这里插入图片描述

linux系统启动过程如下:

在这里插入图片描述

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

bootsect.s代码是磁盘引导块程序,驻留在磁盘的第一个扇区中(引导扇区,0磁道(柱面),0磁头,第一个扇区)。在PC机加电ROM BIOS自检后,ROM BIOS会把引导扇区代码bootsect加载到内存地址0x7C00开始处并执行之。在bootsect代码执行期间,它会将自己移动到内存绝对地址0x90000开始处并继续执行。该程序的主要作用是首先把从磁盘第二个扇区开始的4个扇区的setup模块(由setup.s编译而成)加载到内存紧接着bootsect后面位置处(0x90200),然后利用BIOS中断0x13取磁盘参数表中当前启动引导盘的参数,接着在屏幕上显示"Loading system…"字符串。再者把setup模块后面的system模块加载到内存0x10000开始的地方。随后确定根文件系统的设备号,若没有指定,则根据所保存的引导盘的每磁道扇区数判别出盘的类型和种类(是1.44M A 盘吗?)并保存其设备号于root_dev(引导块的508地址处),最后长跳转到setup程序的开始处(0x90200)执行setup程序。

在这里插入图片描述

查看linux0.11屏幕显示的关键代码:

在这里插入图片描述

根据自己方式做出修改如下:

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

! 显示字符串 “MOSS IS LOADING...”
! 要显示的字符串长度
    mov cx,#24
    mov bx,#0x0007
    mov bp,#msg1
! es:bp 是显示字符串的地址
! 相比与 linux-0.11 中的代码,需要增加对 es 的处理,因为原代码中在输出之前已经处理了 es
    mov ax,#0x07c0
    mov es,ax
    mov ax,#0x1301
    int 0x10

! 设置一个无限循环
inf_loop:
    jmp inf_loop

这里需要修改的是字符串长度,即用需要输出的字符串长度替换 mov cx,#24 中的 24。要注意:除了我们设置的字符串 msg1 之外,还有三个换行 + 回车,一共是 6 个字符。比如这里 Hello OS world, my name is LZJ 的长度是 30,加上 6 后是 36,所以代码应该修改为 mov cx,#36

接下来就是修改输出的字符串了:

! msg1 处放置字符串
msg1:
! 回车 + 换行
    .byte   13,10
    .ascii  "MOSS IS LOADING..."
! 两对回车 + 换行
    .byte   13,10,13,10

! boot_flag 必须在最后两个字节
.org 510
! 设置引导扇区标记 0xAA55
! 必须有它,才能引导
boot_flag:
    .word   0xAA55

.org 508 修改为 .org 510,是因为这里不需要 root_dev: .word ROOT_DEV,为了保证 boot_flag 一定在最后两个字节,所以要修改 .org

完整代码如下:

entry _start
_start:
    mov ah,#0x03
    xor bh,bh
    int 0x10
    mov cx,#24
    mov bx,#0x0007
    mov bp,#msg1
    mov ax,#0x07c0
    mov es,ax
    mov ax,#0x1301
    int 0x10
inf_loop:
    jmp inf_loop
msg1:
    .byte   13,10
    .ascii  "MOSS IS LOADING..."
    .byte   13,10,13,10
.org 510
boot_flag:
    .word   0xAA55

接下来,编译和链接botsect.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 去除最后生成的可执行文件中的符号信息。

如果这两个命令没有任何输出,说明编译与链接都通过了。

在这里插入图片描述

在这里插入图片描述

需要留意的文件是 bootsect 的文件大小是 544 字节,而引导程序必须要正好占用一个磁盘扇区,即 512 个字节。造成多了 32 个字节的原因是 ld86 产生的是 Minix 可执行文件格式,这样的可执行文件除了文本段、数据段等部分以外,还包括一个 Minix 可执行文件头部。

去掉该文件头部:

$ dd bs=1 if=bootsect of=Image skip=32

在这里插入图片描述

将生成的Image文件拷贝到linux-0.11目录下

# 当前的工作路径为 /home/shiyanlou/oslab/linux-0.11/boot/

# 将刚刚生成的 Image 复制到 linux-0.11 目录下
$ cp ./Image ../Image

# 执行 oslab 目录中的 run 脚本
$ ../../run

在这里插入图片描述

2. bootsect.s读入setup.s

首先编写一个setup.s,直接拷贝前面的bootsect.s,然后稍加修改

在这里插入图片描述

接下来需要编写 bootsect.s 中载入 setup.s 的关键代码。原版 bootsect.s 中下面的代码就是做这个的。

在这里插入图片描述

所有需要的功能在原版 bootsect.s 中都是存在的,我们要做的仅仅是将这些代码添加到新的 bootsect.s 中去,并去掉原bootsect.s中的无限循环。

SETUPLEN=4
SETUPSEG=0x07e0
entry _start
_start:
    mov ah,#0x03
    xor bh,bh
    int 0x10
    mov cx,#24
    mov bx,#0x0007
    mov bp,#msg1
    mov ax,#0x07c0
    mov es,ax
    mov ax,#0x1301
    int 0x10
load_setup:
    mov dx,#0x0000
    mov cx,#0x0002
    mov bx,#0x0200
    mov ax,#0x0200+SETUPLEN
    int 0x13
    jnc ok_load_setup
    mov dx,#0x0000
    mov ax,#0x0000
    int 0x13
    jmp load_setup
ok_load_setup:
    jmpi    0,SETUPSEG
msg1:
    .byte   13,10
    .ascii  "MOSS IS LOADING..."
    .byte   13,10,13,10
.org 510
boot_flag:
    .word   0xAA5

修改tools/buid.c

在这里插入图片描述

编译:

$ cd ~/oslab/linux-0.11
$ make BootImage
$ ../run

在这里插入图片描述

3.获取硬件参数

这一部分汇编代码没怎么看懂,建议参考李治军老师的在线实验教程。

4.总结

Linux操作系统启动部分主要执行流程:

  1. 开机上电后,CPU进入实模式,从0xFFFF0处开始执行,为ROM-BIOS的地址。
  2. BIOS执行系统检测、在地址0处初始化中断向量、把硬盘启动扇区的512字节读入内存绝对地址0x7C00处,并跳转至这个地方。
  3. bootsect.s把自己移动到0x90000继续执行,加载setup.s到0x90200处,显示开机字符串,再把system.s加载到0x10000处。随后跳转到setup.s部分执行
  4. setup.s利用BIOS终端读取系统参数,然后把system模块移动到0x00000处,设置IDT和GDT,进入保护模式
  5. head.s重新设置IDT和GDT,并设置页表,进入main.c
  6. 初始化内存和数据结构,创建第一个进程。
  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值