码迷,mamicode.com
首页 > 其他好文 > 详细

[操作系统理论] 1, 操作系统的启动

时间:2015-08-17 13:44:15      阅读:106      评论:0      收藏:0      [点我收藏+]

标签:

一, 执行BIOS程序

    x86 PC刚开机的时候, CPU处于实模式, 实模式和保护模式相对应, 实模式的寻址是cs:ip (CS左移4位+ip). 开机时, cs=0xFFFF, ip=0x0000, 也就是说cpu从0xFFFF0地址处开始执行, 但是我们发现0xFFFF0这个地址距离0xFFFFF只有16个字节, 这16个字节并不能做什么事情, 所以在0xFFFF0处的指令是一个跳转指令 jmp far f000:e05b 跳转到对应的地址处执行. 这里的代码具体的任务是检查硬件, 如RAM, 键盘, 显示器, 软盘, 硬盘等. 如果电脑的这些硬件没有什么问题, 就将启动设备(可以是磁盘, 软盘, U盘等, 这可以在BIOS菜单中设置)的0磁道0扇区的512个字节的代码读入到0x7c00处, 然后设置cs=0x7c0, ip=0x0000, CPU就从0x7c00处开始执行了

 

二, 操作系统的引导(1)

   在磁盘的0磁道1扇区中处的程序对应的源代码是bootsect.s  下面是对这个程序代码的简要分析:

......

_start:
    ! bootsect模块是在内存中的0x7c00处
    ! 先把bootsect模块自身拷贝到内存中的0x90000处
    ! 然后在0x9000段里继续向下执行
    mov    ax,#BOOTSEG       ! BOOTSEG  = 0x07c0
    mov    ds,ax            
    mov    ax,#INITSEG       ! INITSEG  = 0x9000
    mov    es,ax            
    mov    cx,#256
    sub    si,si            
    sub    di,di            
    rep
    movw                
    jmpi    go,INITSEG    

go:    mov    ax,cs
    mov    ds,ax
    mov    es,ax

    ! 把0磁道2扇区开始的4个扇区的程序读入到0x90200处, 这个模块的名字叫做setup
load_setup:        
    mov    dx,#0x0000        
    mov    cx,#0x0002        
    mov    bx,#0x0200        
    mov    ax,#0x0200+SETUPLEN       ! SETUPLEN = 4
    int    0x13
    
    jnc    ok_load_setup    
    mov    dx,#0x0000
    mov    ax,#0x0000        
    int    0x13                    
    j    load_setup

ok_load_setup:
    
    ......
 
    ! 获取光标位置
    mov    ah,#0x03
    xor    bh,bh
    int    0x10
        
    ! 打印启动信息到屏幕上
    mov    cx,#24            
    mov    bx,#0x0007        
    mov    bp,#msg1        
    mov    ax,#0x1301        
    int    0x10

    mov    ax,#SYSSEG
    mov    es,ax
    call    read_it
    ......

! 读入system模块到0x10000处, 此处代码比较复杂, 省略了
read_it: ...... msg1: .
byte 13,10 .ascii "Loading system ..." .byte 13,10,13,10 ......

    总结一下bootsect模块的主要任务:

    1, bootsect模块本身是在内存的0x7c00处

    2, 首先将bootsect模块自身复制到0x90000处

    3, 将setup模块复制到0x90200处

    4, 显示一些欢迎进入系统的信息

    5, 将system模块复制到0x10000处

    此时, 内存中的情况如下: 

 技术分享

三, 操作系统的引导(2)

    在磁盘的0磁道2扇区到5扇区中处的程序对应的源代码是setup.s. 下面是对这个程序代码的简要分析:

......

start:

    ! 取出光标位置的信息, 存放到地址0x90000处
    mov    ax,#INITSEG     ! INITSEG = 0x9000
    mov    ds,ax
    mov    ah,#0x03
    xor    bh,bh
    int    0x10
    mov    [0],dx

    ! 取出内存大小的信息, 存放到地址0x90002处
    mov    ah,#0x88
    int    0x15
    mov    [2],ax
    ......
    
    ! 将system模块移动到地址0x0处
do_move:
    mov    es,ax        ! destination segment
    add    ax,#0x1000
    cmp    ax,#0x9000
    jz    end_move
    mov    ds,ax        ! source segment
    sub    di,di
    sub    si,si
    mov     cx,#0x8000
    rep
    movsw
    jmp    do_move

end_move:
    mov    ax,#SETUPSEG    
    mov    ds,ax
    lidt    idt_48        ! 将IDT表的地址存放到LDTR寄存器中
    lgdt    gdt_48        ! 将GDT表的地址存放到GDTR寄存器中

    ! 切换到保护模式
    mov    ax,#0x0001    ! CR0寄存器的第0位如果为0表示启动实模式, 为1表示启动保护模式, 
    lmsw    ax        ! 启用保护模式. 这个可以替换为mov cr0,ax 用lmsw是为了兼容以前的CPU
    
    ! ip的值为0, cs的值为8(0b0000,0000,0000,10000) 
    ! 在保护模式下, cs表示选择子, 即GDT表的索引
    ! 通过查GTD表可以知道基址为0, 即跳转到0x0地址处开始执行
    jmpi    0,8        


    ! 初始化GDT表
gdt:
    .word    0,0,0,0        
    .word    0x07FF, 0x0000, 0x9A00, 0x00C0
    .word    0x07FF, 0x0000, 0x9200, 0x00C0
    
    ! idt是保护模式下的中断函数表
idt_48:
    .word    0            ! idt limit=0
    .word    0,0            ! idt base=0L

    ! gdt是全局描述符表
gdt_48:
    .word    0x800        ! gdt limit=2048, 256 GDT entries
    .word    512+gdt,0x9    ! gdt base = 0X9xxxx
    
    ......

    总结一下setup模块的主要任务:

    1, 读取硬件相关的信息, 并将这些信息存储到0x9000处

    2, 将system模块复制到0x0000处

    3, 从实模式切换到保护模式

    4, 跳转到0x0000处开始执行system模块

 

至此, 操作系统的引导就完成了

[操作系统理论] 1, 操作系统的启动

标签:

原文地址:http://www.cnblogs.com/XiangfeiAi/p/4736264.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!