实验二:操作系统的启动

Linux内核启动过程:bootsect.s与setup.s详解

实验二:操作系统的启动

前言:

bootsect.s与setup.s均位于linux-0.11内核源码boot目录下,setup.sbootsect.s一样都是操作系统进入system的准备工作,其主要功能就是获取各种硬件参数,并将这些数据保存到内存0x90000处,也就是覆盖bootsect程序所在的空间,然后我们就可以进入保护模式啦,那么如何进入保护模式呢?

我们将寻址方式从16位扩展到32位,就可以进入保护模式,在16位实模式下寻址方式是cs寄存器中左移4位+ip地址,扩展到32即通过ax寄存器存储0x0001值后存储到cr0寄存器内,等价于将CR0寄存器的PE置为1开启保护模式,在保护模式下,我们的寻址方式就是根据cs查表+ip。

实践

修改linux-0.11内核源码boot目录下的bootsect.s

bootsect.s

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
inf_loop:
    jmp inf_loop
msg1:
    .byte   13,10
    .ascii  "Hello OS world, my name is WYN"
    .byte   13,10,13,10
.org 510
boot_flag:
    .word   0xAA55
   

编译运行:

cd ~/oslab/linux-0.11/boot/
as86 -0 -a -o bootsect.o bootsect.s
ld86 -0 -s -o bootsect bootsect.o
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;     //符号表大小 
};

我们可以分析该结构体的总字节数,char6字节、short2字节、long24字节,那么我们可以计算出该结构的总字节数为32字节,然而bootsect文件字节数是544个字节,一个磁盘扇区字节数为512字节,刚好多了32个字节即Id86产生的Minix可执行文件格式,所以我们需要将多余的32个字节进行删除,先查看一下它的信息,我们可以发现我们要删除的32个字节正好对应文件头部32个字节。

在这里插入图片描述

$ dd bs=1 if=bootsect of=Image skip=32//删除并保存到Image文件
cp Image ../Image//复制到 linux-0.11/目录中
../run //运行oslab目录下的run命令

在这里插入图片描述

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 WYN"
    .byte   13,10,13,10
.org 510
boot_flag:
    .word   0xAA55
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

在linux-0.11目录下运行报错 make,根据 Makefile 的指引执行了 tools/build.c,它是为生成整个内核的镜像文件而设计的,没考虑我们只需要 bootsect.ssetup.s 的情况。所以我们需要做出修改。

make BootImage

我们发现提示不能打开system模块哦
7%89%87%5C7.png&pos_id=img-g5DneQe3-1696989943409)

修改build.c

在这里插入图片描述

成功图如下

在这里插入图片描述

bochs上运行结果最终显示图

在这里插入图片描述

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

我们需要对内核重新编译并cp Image到linux0.1目录下,bochs最终结果图:

在这里插入图片描述

在这里插入图片描述

分析:

运行结果图Memory Size:0x3C00KB转换成十进制即15360KB,我们知道1KB=0.0009766MB,所以我们最终可以得到当前所加载系统的内存总容量为15360✖15.000576=15MB,我们要求当前系统最低内存容量是16MB,所以需要加上1MB,我们在bochs/bochsrc.bxrc配置文件中可以查看参数情况与预期结果吻合。

我们现在可以对操作系统的启动涉及到的.s文件做一个简单的总结。

bootsect.s将操作系统从磁盘上读入到内存中
setup.s获取硬件参数,启动保护模式
head.s初始化gdt表以及idt表以及一些页表,在system模块起始位置
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值