ucore - 第一章 - bootloader启动过程

目录

1、概述

2、引用

3、关键字

4、cup上电过程

5、bootloader

 5.1、关闭中断、初始化段寄存器

5.2、开启A20总线

5.3、初始化GDT表

5.3.1、实模式和保护模式

5.3.2、分段存储管理机制

5.3.3、段表初始化

5.4、开启保护模式

5.5、设置函数栈,跳转到C语言运行

 5.6、 加载内核程序并运行

5.6.1、读取ELF文件头

5.6.2、加载每个程序段

5.6.3、跳转执行kernel


1、概述

        此文章用于描述并回顾ucore lab1中学习过程,加深对x86启动的认识。错误理解和认识还望看到的伙伴加以指正,感谢!

2、引用

uCore OS实验指导书

通过ucore学习OS(一):First part——Booting

Intel 80386 Reference Programmers Manual-i386

3、关键字

        无

4、cup上电过程

        机器上电时,将CS寄存器设置成0xF000,它的shadow register(CPU真正直接引用的寄存器)的值初始化设置为0xFFFF0000,EIP寄存器初始化设置为0x0000FFF0。则CPU从物理地址0XFFFFFFF0开始执行。此处存放了一条跳转指令,这条指令是16字节长的长跳转指令JMP F000:E05B。

        长跳转指令将CS更新成0xF000,CS的shadow register被更新成0x000F0000,则此时形成的物理地址为0x000FE05B,为CPU将要执行的第二条指令,即为BIOS的第一条指令。

        BIOS将通过读取硬盘主引导扇区内存一个特定的地址0x7c00处,并jump到此地址开始执行bootloader。

5、bootloader

         bootloader完成的工作包括:

  1. 切换到保护模式,启用分段机制
  2. 读磁盘中ELF执行文件格式的ucore操作系统到内存
  3. 显示字符串信息
  4. 把控制权交给ucore操作系统

        对应其工作的实现文件在lab1中的boot目录下的三个文件asm.h、bootasm.S和bootmain.c。

完整的bootasm.S汇编代码如下所示:

#include <asm.h>

# Start the CPU: switch to 32-bit protected mode, jump into C.
# The BIOS loads this code from the first sector of the hard disk into
# memory at physical address 0x7c00 and starts executing in real mode
# with %cs=0 %ip=7c00.

.set PROT_MODE_CSEG,        0x8                     # kernel code segment selector
.set PROT_MODE_DSEG,        0x10                    # kernel data segment selector
.set CR0_PE_ON,             0x1                     # protected mode enable flag

# start address should be 0:7c00, in real mode, the beginning address of the running bootloader
.globl start
start:
.code16                                             # Assemble for 16-bit mode
    cli                                             # Disable interrupts
    cld                                             # String operations increment

    # Set up the important data segment registers (DS, ES, SS).
    xorw %ax, %ax                                   # Segment number zero
    movw %ax, %ds                                   # -> Data Segment
    movw %ax, %es                                   # -> Extra Segment
    movw %ax, %ss                                   # -> Stack Segment

    # Enable A20:
    #  For backwards compatibility with the earliest PCs, physical
    #  address line 20 is tied low, so that addresses higher than
    #  1MB wrap around to zero by default. This code undoes this.
seta20.1:
    inb $0x64, %al                                  # Wait for not busy(8042 input buffer empty).
    testb $0x2, %al
    jnz seta20.1

    movb $0xd1, %al                                 # 0xd1 -> port 0x64
    outb %al, $0x64                                 # 0xd1 means: write data to 8042's P2 port

seta20.2:
    inb $0x64, %al                                  # Wait for not busy(8042 input buffer empty).
    testb $0x2, %al
    jnz seta20.2

    movb $0xdf, %al                                 # 0xdf -> port 0x60
    outb %al, $0x60                                 # 0xdf = 11011111, means set P2's A20 bit(the 1 bit) to 1

    # Switch from real to protected mode, using a bootstrap GDT
    # and segment translation that makes virtual addresses
    # identical to physical addresses, so that the
    # effective memory map does not change during the switch.
    lgdt gdtdesc
    movl %cr0, %eax
    orl $CR0_PE_ON, %eax
    movl %eax, %cr0

    # Jump to next instruction, but in 32-bit code segment.
    # Switches processor into 32-bit mode.
    ljmp $PROT_MODE_CSEG, $protcseg

.code32                                             # Assemble for 32-bit mode
protcseg:
    # Set up the protected-mode data segment registers
    movw $PROT_MODE_DSEG, %ax                       # Our data segment selector
    movw %ax, %ds                                   # -> DS: Data Segment
    movw %ax, %es                                   # -> ES: Extra Segment
    movw %ax, %fs                                   # -> FS
    movw %ax, %gs                                   # -> GS
    movw %ax, %ss                                   # -> SS: Stack Segment

    # Set up the stack pointer and call into C. The stack region is from 0--start(0x7c00)
    movl $
评论 1
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值