《操作系统》by李治军 | 实验2 - 操作系统的引导

目录

一、实验内容

二、实验准备

三、正式实验

(一)修改 bootsect.s 代码,实现向屏幕输出信息 “Hello OS world, my name is XXX”。

(二)修改 setup.s 代码,向屏幕输出一行信息 "Now we are in SETUP",并实现 bootsect.s 对 setup.s 的载入。

(三)修改 setup.s 代码获取基本硬件参数。


一、实验内容

1、阅读《Linux内核完全注释:基于0.11内核》第 6 章,对计算机和 Linux 0.11 的引导过程进行初步了解。

2、改写 bootsect.s 代码,实现:

      在屏幕上打印一段自己设定的信息,如 “XXX is booting...” 。

3、改写 setup.s 代码,实现:

      ① bootsect.s 完成 setup.s 的载入,并跳转到 setup.s 开始地址执行。而 setup.s 向屏幕输出信息 "Now we are in SETUP" 。

      ② setup.s 能够获取至少一个基本的硬件参数(如 内存参数、显卡参数、硬盘参数 等),将其存放在内存的特定地址,并输出到屏幕上。

      ③ setup.s 不再加载 Linux 内核,保持上述信息显示在屏幕上即可。

二、实验准备

1、实验环境

        蓝桥云课实验楼:操作系统原理与实践_Linux - 蓝桥云课

2、相关代码文件
       
Linux-0.11/boot 目录下的 bootsect.ssetup.sLinux-0.11/tools 目录下 build.c 是本实验会涉及到的源文件,它们的功能详见《注释》的 6.2、6.3 节和 16 章。

   

3、引导程序的运行环境
        引导程序由
BIOS 加载并运行。它活动时,操作系统还不存在,整台计算机的所有资源都由它掌控,此时能利用的功能只有 BIOS 中断调用。实验中主要使用 BIOS 0x100x13 中断。

三、正式实验

(一)修改 bootsect.s 代码,实现向屏幕输出信息 Hello OS world, my name is XXX

1. 打开 oslab/linux-0.11/boot 目录下的 bootsect.s 源码文件。

    

2. 直接删除原来所有的代码,替换以下新代码并保存。

entry _start
_start:
    !使用 0x10 号中断读取光标位置
    mov ah,#0x03
    xor bh,bh
    int 0x10

    !显示字符串 “Hello OS world, my name is LQN”
    !cx 为要显示字符串的长度(除字符串外还有3个换行+1个回车)
    mov cx,#36
    mov bx,#0x0007

    ! es:bp 为显示字符串的地址
    mov bp,#msg1
    mov ax,#0x07c0
    mov es,ax
    mov ax,#0x1301
    int 0x10

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

!设置显示字符串
msg1:
    !回车+换行
    .byte   13,10
    .ascii  "Hello OS world, my name is LQN"
    !两对 “回车+换行”
    .byte   13,10,13,10

!boot_flag 必须在最后两个字节
.org 510
!设置引导扇区标记 0xAA55(必须设置,否则无法成功引导)
boot_flag:
    .word   0xAA55

3. 打开终端(Ctrl + Alt + T),输入以下命令 编译 新编写的 bootsect.s。

as86 -0 -a -o bootsect.o bootsect.s
  • bootsect.o 为 bootsect.s 编译生成的中间文件

4. 输入以下命令 链接 生成的 bootsect.o 文件。

ld86 -0 -s -o bootsect bootsect.o
  • bootsect 是编译、链接后的生成的目标文件

5. 输入 ls -l 列出文件信息,可以看出 boot 目录下多了一个中间文件 bootsect.o 和一个目标文件 bootsect。

6. 可以看出这里 bootsect 文件大小是 544 字节,而引导程序必须要正好占用一个磁盘扇区,即 512 个字节,这里多出了 32 个字节,所以输入以下指令去掉文件头的 32 个字节。

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

生成的 Image 就是去掉文件头的 bootsect,刚好512字节:

7. 确保上一步生成的 Image 文件位于 linux-0.11 目录下,如果没有就拷贝一下。

cp ./Image ../Image

8. 输入以下指令执行 oslab 目录下的 run 脚本。

../../run

9. 运行结果:

(二)修改 setup.s 代码,向屏幕输出一行信息 "Now we are in SETUP",并实现 bootsect.s 对 setup.s 的载入。

1. 这里 setup.s 的功能和前面 bootsect.s 的功能基本一致,所以可以直接拷贝前面的 bootsect.s 代码,将显示的信息改为 “Now we are in SETUP” 即可 ,完整 setup.s 代码如下。

entry _start
_start:
    mov ah,#0x03
    xor bh,bh
    int 0x10
    !注意字符串长度的变化
    mov cx,#25
    mov bx,#0x0007
    mov bp,#msg2
    mov ax,cs
    mov es,ax
    mov ax,#0x1301
    int 0x10

inf_loop:
    jmp inf_loop

msg2:
    .byte   13,10
    .ascii  "Now we are in SETUP"
    .byte   13,10,13,10

.org 510
boot_flag:
    .word   0xAA55

2. 编写 bootsect.s 中 载入 setup.s 的代码,完整 bootsect.s 代码如下。

SETUPLEN=2
SETUPSEG=0x07e0
entry _start
_start:
    mov ah,#0x03
    xor bh,bh
    int 0x10
    mov cx,#36
    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  "Hello OS world, my name is LQN"
    .byte   13,10,13,10

.org 510
boot_flag:
    .word   0xAA55

3. 再次编译。

        现在有两个文件 bootsect.ssetup.s 需要编译、链接。如果还是使用之前的手动编译,效率较低(先 as86 再 ld86 )。所以可以借助 Makefile 提高效率。

进入 linux-0.11 目录,输入以下命令:

make BootImage

编译失败,显示以下结果:

Unable to open 'system'

make: *** [BootImage] Error 1

  • 因为 make 指令根据 Makefile 的指引执行了 tools/build.c ,它是为生成整个内核的镜像文件而设计的,没考虑我们只需要 bootsect.s 和 setup.s 的情况。它在向我们要求 “系统” 的核心代码,所以为完成实验需要对 build.c 进行一点修改。

4. 修改 build.c 源码,打开 linux-0.11/tools/build.c ,将框中内容注释掉。

    

  • build.c 从命令行参数得到 bootsectsetup system 内核的文件名,将三者做简单的整理后一起写入 Image。其中 system 是第三个参数 - argv[3]
  • 当 make all 或 makeall 时,该参数传过来的是正确的文件名,build.c 会打开它,将内容写入 Image。而 make BootImage 时,传过来的是字符串 "none"

        所以,修改 build.c 的思路就是当 argv[3] 是 "none" 的时候,只将 bootsect 和 setup 写入 Image,忽略所有与 system 有关的工作,或者在该写 system 的位置都写上 “0”。

5. 回到 linux-0.11 目录,再次执行编译命令。

make BootImage

6. 编译成功后,再次执行 run  脚本,运行结果:

(三)修改 setup.s 代码获取基本硬件参数

1. setup.s 参考代码。

INITSEG  = 0x9000
entry _start
_start:
! Print "NOW we are in SETUP"
    mov ah,#0x03
    xor bh,bh
    int 0x10
    mov cx,#25
    mov bx,#0x0007
    mov bp,#msg2
    mov ax,cs
    mov es,ax
    mov ax,#0x1301
    int 0x10

    mov ax,cs
    mov es,ax

! init ss:sp
    mov ax,#INITSEG
    mov ss,ax
    mov sp,#0xFF00

! Get Params
    mov ax,#INITSEG
    mov ds,ax
    mov ah,#0x03
    xor bh,bh
    int 0x10
    mov [0],dx
    mov ah,#0x88
    int 0x15
    mov [2],ax
    mov ax,#0x0000
    mov ds,ax
    lds si,[4*0x41]
    mov ax,#INITSEG
    mov es,ax
    mov di,#0x0004
    mov cx,#0x10
    rep
    movsb

! Be Ready to Print
    mov ax,cs
    mov es,ax
    mov ax,#INITSEG
    mov ds,ax

! Cursor Position
    mov ah,#0x03
    xor bh,bh
    int 0x10
    mov cx,#18
    mov bx,#0x0007
    mov bp,#msg_cursor
    mov ax,#0x1301
    int 0x10
    mov dx,[0]
    call    print_hex

! Memory Size
    mov ah,#0x03
    xor bh,bh
    int 0x10
    mov cx,#14
    mov bx,#0x0007
    mov bp,#msg_memory
    mov ax,#0x1301
    int 0x10
    mov dx,[2]
    call    print_hex

! Add KB
    mov ah,#0x03
    xor bh,bh
    int 0x10
    mov cx,#2
    mov bx,#0x0007
    mov bp,#msg_kb
    mov ax,#0x1301
    int 0x10

! Cyles
    mov ah,#0x03
    xor bh,bh
    int 0x10
    mov cx,#7
    mov bx,#0x0007
    mov bp,#msg_cyles
    mov ax,#0x1301
    int 0x10
    mov dx,[4]
    call    print_hex

! Heads
    mov ah,#0x03
    xor bh,bh
    int 0x10
    mov cx,#8
    mov bx,#0x0007
    mov bp,#msg_heads
    mov ax,#0x1301
    int 0x10
    mov dx,[6]
    call    print_hex

! Secotrs
    mov ah,#0x03
    xor bh,bh
    int 0x10
    mov cx,#10
    mov bx,#0x0007
    mov bp,#msg_sectors
    mov ax,#0x1301
    int 0x10
    mov dx,[12]
    call    print_hex

inf_loop:
    jmp inf_loop

print_hex:
    mov    cx,#4

print_digit:
    rol    dx,#4
    mov    ax,#0xe0f
    and    al,dl
    add    al,#0x30
    cmp    al,#0x3a
    jl     outp
    add    al,#0x07

outp:
    int    0x10
    loop   print_digit
    ret

print_nl:
    mov    ax,#0xe0d     ! CR
    int    0x10
    mov    al,#0xa     ! LF
    int    0x10
    ret

msg2:
    .byte 13,10
    .ascii "NOW we are in SETUP"
    .byte 13,10,13,10

msg_cursor:
    .byte 13,10
    .ascii "Cursor position:"

msg_memory:
    .byte 13,10
    .ascii "Memory Size:"

msg_cyles:
    .byte 13,10
    .ascii "Cyls:"

msg_heads:
    .byte 13,10
    .ascii "Heads:"

msg_sectors:
    .byte 13,10
    .ascii "Sectors:"

msg_kb:
    .ascii "KB"

.org 510
boot_flag:
    .word 0xAA55

2. 运行结果:

猜你喜欢

转载自blog.csdn.net/Amentos/article/details/129150832