ch1 操作系统启动

Posted Y0n1an

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了ch1 操作系统启动相关的知识,希望对你有一定的参考价值。

lab1 实验准备

按照实验解压后进入oslab中,按照make编译。

cd /home/shiyanlou/oslab/
tar -zxvf hit-oslab-linux-20110823.tar.gz \\
  -C /home/shiyanlou/
./run
cd ./linux-0.11/
make all
make clean
.....
make all

运行脚本即可启动内核

调试

汇编级调试和C语言级调试

汇编级调试

# 确认在 oslab 目录下
$ cd ~/oslab/

# 运行脚本前确定已经关闭刚刚运行的 Bochs
$ ./dbg-asm

C语言级调试

需要两个终端并发
第一个进程终端

$ cd ~/oslab
$ ./dbg-c

第二个进程终端

$ cd ~/oslab
$ ./rungdb

文件交换

关闭bochs进程

$ cd ~/oslab/

# 启动挂载脚本
$ sudo ./mount-hdc

在hdc目录即可看见一模一样的文件系统

# 进入挂载到 Ubuntu 上的目录
$ cd ~/oslab/hdc

# 查看内容
$ ls -al

读写完毕后卸载
通过 sudo ./mount-hdc 进行挂载。

然后在 Ubuntu 的 ~/oslab/hdc/usr/root 目录下创建一个 xxx.c 文件,

sudo gedit ~/oslab/hdc/usr/root/xxx.c

再卸载文件系统sudo umount hdc,启动run脚本,在bochs输入ls命令

lab2 操作系统启动

bootsec.s改写

首先是显示要求的字符串

! 首先读入光标位置
    mov ah,#0x03
    xor bh,bh
    int 0x10  !->DH 列->DL
! 显示字符串 “YonglanOS is booting...! 要显示的字符串长度
    mov cx,#36  
    mov bx,#0x0007 !黑底白字
    mov bp,#msg1 ! 取msg地址给bp 
! es:bp 是显示字符串的地址
! 相比与 linux-0.11 中的代码,需要增加对 es 的处理,因为原代码中在输出之前已经处理了 es
    mov ax,#0x07c0
    mov es,ax   
    mov ax,#0x1301
    int 0x10

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


Ubuntu 上先从终端进入 ~/oslab/linux-0.11/boot/ 目录。

Windows 上则先双击快捷方式 “MinGW32.bat”,将打开一个命令行窗口,当前目录是 oslab,用 cd 命令进入 linux-0.11\\boot。

无论那种系统,都执行下面两个命令编译和链接 bootsect.s:

 ~/oslab/linux-0.11/boot/
$ as86 -0 -a -o bootsect.o bootsect.s
$ ld86 -0 -s -o bootsect bootsect.o

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

其中 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  |..............U.|
00000220

去掉这 32 个字节后,将生成的文件拷贝到 linux-0.11 目录下,并一定要命名为“Image”(注意大小写)。然后就“run”吧!
接下来干什么呢?是的,要去掉这 32 个字节的文件头部(tools/build.c 的功能之一就是这个)!随手编个小的文件读写程序都可以去掉它。不过,懒且聪明的人会在 Ubuntu 下用命令:

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

生成的 Image 就是去掉文件头的 bootsect。

Windows 下可以用 UltraEdit 直接删除(选中这 32 个字节,然后按 Ctrl+X)。

去掉这 32 个字节后,将生成的文件拷贝到 linux-0.11 目录下,并一定要命名为“Image”(注意大小写)。然后就“run”吧!

bootsec.s读入setup.s

显示字符的功能直接复制bootsec.s上的内容进行修改

```c
! 首先读入光标位置
    mov ah,#0x03
    xor bh,bh
    int 0x10  !行->DH 列->DL
! 显示字符串 “"Hello OS world, my name is JYL"! 要显示的字符串长度
    mov cx,#36  
    mov bx,#0x0007 !黑底白字
    mov bp,#msg1 ! 取msg地址给bp 
! es:bp 是显示字符串的地址
! 相比与 linux-0.11 中的代码,需要增加对 es 的处理,因为原代码中在输出之前已经处理了 es
    mov ax,#0x07c0
    mov es,ax   
    mov ax,#0x1301
    int 0x10

接下来,读入setup.s

load_setup:
! 设置驱动器和磁头(drive 0, head 0): 软盘 0 磁头
    mov dx,#0x0000
! 设置扇区号和磁道(sector 2, track 0): 0 磁头、0 磁道、2 扇区
    mov cx,#0x0002
! 设置读入的内存地址:BOOTSEG+address = 512,偏移512字节
    mov bx,#0x0200
! 设置读入的扇区个数(service 2, nr of sectors)! SETUPLEN是读入的扇区个数,Linux 0.11 设置的是 4! 我们不需要那么多,我们设置为 2(因此还需要添加变量 SETUPLEN=2)
    mov ax,#0x0200+SETUPLEN
! 应用 0x13 号 Bios 中断读入 2 个 setup.s扇区
    int 0x13
! 读入成功,跳转到 ok_load_setup: ok - continue,int 0x13出错会置位CF
    jnc ok_load_setup
! 软驱、软盘有问题才会执行到这里。我们的镜像文件比它们可靠多了
    mov dx,#0x0000
! 否则复位软驱 reset the diskette
    mov ax,#0x0000
    int 0x13
! 重新循环,再次尝试读取
    jmp load_setup
ok_load_setup:
! 接下来要干什么?当然是跳到 setup 执行。
! 要注意:我们没有将 bootsect 移到 0x9000,因此跳转后的段地址应该是 0x7ce0
! 即我们要设置 SETUPSEG=0x07e0

接下来是一些数据

msg1:
    .byte   13,10
    .ascii  "Hello OS world, my name is JYL"
    .byte   13,10,13,10
.org 510
boot_flag:
    .word   0xAA55

以上是关于ch1 操作系统启动的主要内容,如果未能解决你的问题,请参考以下文章

linux系统引导过程及引导修复

自动化kickstart安装linux系统

硬盘磁头坏了有哪些表现

操作系统:电梯调度算法代码演示

Centos系统启动流程

双系统启动引导 界面怎么美化