操作系统的引导

发布时间 2024-01-09 23:00:18作者: 江水为竭

实验目的

  • 熟悉实验环境;
  • 建立对操作系统引导过程的深入认识;
  • 掌握操作系统的基本开发过程;
  • 能对操作系统代码进行简单的控制,揭开操作系统的神秘面纱。

实验过程

编写bootsect.s

  • 显示xxx is booting...字符串,显示Logo
  • 加载setup.s
  • 跳转到setup.s运行。

编写setup.s

  • 显示字符串Now we are in SETUP
  • 调用中断得到光标位置、内存大小和显示参数。
  • 读取硬盘参数表。
  • 将得到的基本硬件参数保存在内存0x9000处。
  • 打印提示字符,将对应参数以16进制的形式,用ASCII码打印出。

修改build.c

注释掉运行make BootImage命令报错的代码。

image

image

实验结果

image

image

可见,硬盘参数与 Bochs配置文件中相同。

内存大小为15MB,加上1MB正好为配置文件中的16MB

显示状态0003意为,安装的显示内存为256KB,显示模式为彩色模式。

实验报告

有时,继承传统意味着别手蹩脚。 x86 计算机为了向下兼容,导致启动过程比较复杂。 请找出 x86 计算机启动过程中,被硬件强制,软件必须遵守的两个“多此一举”的步骤(多找几个也无妨),说说它们为什么多此一举,并设计更简洁的替代方案。

实模式到保护模式的转换

为了兼容旧的8086处理器。现代x86系统在启动时首先运行在16位的实模式。但是现代操作系统需要32位或64位的保护模式运行。

现代计算机可以设计为直接启动为保护模式。

从磁盘引导扇区读入内存地址0x7c00处并执行

该限制来自于PC早期的引导协议。传统BIOS将控制权交给引导扇区代码,该代码必须符合512字节的限制。bootsect.s通常负责将内核的其他部分从磁盘读入内存,并且需要挪动内核代码位置。

可以设计成使用现代引导加载程序来避免这种限制,并直接加载整个内核,即使分散在磁盘上,而不是仅限于从0x7c00地址启动,也应该没有大小为512字节的限制。

中断向量表的初始化

为了向下兼容,BIOS在系统启动时会设置中断向量表 (IVT)到内存地址0处(内存前1KB),并填充预定义中断的处理程序,包括硬件中断、软件中断以及异常处理。而到保护模式,这个位置处会被内核代码覆盖。

现代操作系统不使用这些BIOS中断服务例程;相反,它们在启动时会设置自己的中断描述符表(Interrupt Descriptor Table, IDT),在保护模式下使用。

当操作系统接管硬件之后,BIOS中的IVT中断服务例程将不再被使用,因为操作系统有自己的硬件抽象层和驱动程序来管理硬件。

解决方案是根据操作系统的需求来决定是否需要初始化IVT。

软盘驱动器的初始化

BIOS在启动时会搜索和初始化软盘驱动器这样的遗留设备,但是这些设备在现代计算机上已经不常见。

可以默认不初始化这些遗留设备。

实验代码

bootsect.s

SETUPSEG=0x07e0
SETUPLEN=4

entry start
start:
    ! Cursor
    mov ah,#0x03
    xor bh,bh
    int 0x10

    ! Display
    mov cx,#255
    mov bx,#0x0009
    mov bp,#msg1
    mov ax,#0x07c0
    mov es,ax
    mov ax,#0x1301
    int 0x10

load_setup:
    mov dx,#0x0000
    mov cx,#0x0002
    ! es:bx -> data buffer
    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:
    ! interseg jump
    jmpi 0,SETUPSEG

inf_loop:
    jmp inf_loop

	! Logo
	! escape character
msg1:
    .byte 13,10
    .ascii "  _     _   ___       _                      "
    .byte 13,10
    .ascii " | |   (_) | __|_  _ | |_   __ _  _ _   __ _ "
    .byte 13,10
    .ascii " | |__ | | | _|| || || ' \\ / _` || ' \\ / _` |"
    .byte 13,10
    .ascii " |____||_| |_|  \\_,_||_||_|\\__,_||_||_|\\__, |"
    .byte 13,10
    .ascii "                                       |___/ "
    .byte 13,10
    .ascii "OS is booting..."
    .byte 13,10

    .org 510
boot_flag:
    .word 0xAA55

setup.s

INITSEG=0x0090
entry start
start:
    ! Init Stack
    mov ax,#stack
    mov ss,ax
    ! Init es
    mov ax,cs
    mov es,ax

    mov cx,#25
    mov bp,#msg1
    call print_string

    ! Init ds
    mov ax,#INITSEG
    mov ds,ax

    ! Get cursor
    mov ah,#0x03
    xor bh,bh
    int 0x10
    mov [0],dx

    ! Get memory size
    mov ah,#0x88
    int 0x15
    mov [2],ax ! a word

    ! Get display parameters
    mov ah,#0x12
    mov bl,#0x10
    int 0x10
    mov [4],bx ! bl: memory; bh: status

    ! Get disk drive parameters
    mov ax,#0x0000
    mov ds,ax
    lds si,[4*0x41]
    mov ax,#INITSEG
    mov es,ax
    mov di,#0x0006
    mov cx,#0x10 ! 16 bytes
    rep 
    movsb


! Print Saved Information
    
    !Init
    mov ax,cs
    mov es,ax
    mov ax,#INITSEG
    mov ds,ax

    !Print Cursor
    mov cx,#11
    mov bp,#msg_cursor
    call print_string
    mov dx,[0]
    call print_hex

    !Print Memory Size
    mov cx,#14
    mov bp,#msg_memory
    call print_string
    mov dx,[2]
    call print_hex
    mov cx,#3
    mov bp,#msg_kb
    call print_string

    !Print display parameters
    mov cx,#17
    mov bp,#msg_display
    call print_string
    mov dx,[4]
    call print_hex

    !Print Cyl
    mov cx,#12
    mov bp,#msg_cyl
    call print_string
    mov dx,[6]
    call print_hex

    !Print Headers:
    mov cx,#10
    mov bp,#msg_headers
    call print_string
    mov dl,[8]
    xor dh,dh
    call print_hex

    !Print Sectors
    mov cx,#10
    mov bp,#msg_sectors
    call print_string
    mov dl,[20]
    xor dh,dh
    call print_hex

!End
inf_loop:
    jmp inf_loop

! Print String; cx = NUM; es:bp -> #msg
print_string:
    push cx
    mov ah,#0x03
    xor bh,bh
    int 0x10
    pop cx
    mov bx,#0x0007
    mov ax,#0x1301
    int 0x10
    ret

! Print dx
print_hex:
    mov cx,#4
print_digit:
    rol dx,#4
    mov ah,#0xe
    mov al,dl
    and al,#0xf

    add al,#0x30
    cmp al,#0x39
    jbe good_digit
    add al,#0x41 - 0x30 - 0xa
good_digit:
    int 0x10
    loop print_digit
    ret

msg1:
    .byte 13,10
    .ascii "Now we are in SETUP"
    .byte 13,10
    .byte 13,10
msg_cursor:
    .ascii "Cursor POS:"
msg_memory:
    .byte 13,10
    .ascii "Memory SIZE:"
msg_display:
    .byte 13,10
    .ascii "Display Status:"
msg_cyl:
    .byte 13,10
    .ascii "Cylinders:"
msg_headers:
    .byte 13,10
    .ascii "Headers:"
msg_sectors:
    .byte 13,10
    .ascii "Sectors:"
msg_kb:
    .ascii " KB"
init_stack:
    .long 0,0,0,0
stack: