linux 0.11 源码学习(四)

setup.s

在setup中最主要的工作是使系统进入保护模式,并转入system模块具体如下:

  • 通过BIOS中断读取系统数据,如光标、显卡、硬盘等信息,这些信息存放至内存0x9000至0x901FC处,典型代码如下:
! ok, the read went well so we get current cursor position and save it for
! posterity.

    mov    ax,#INITSEG    ! this is done in bootsect already, but...
    mov    ds,ax
    mov    ah,#0x03    ! read cursor pos
    xor    bh,bh
    int    0x10        ! save it in known place, con_init fetches
    mov    [0],dx        ! it from 0x90000.
  • 将system模块移到内存0x0000处(这里看代码有点不懂,感觉只移动了64K,而不是完整 system的512K):
    mov    ax,#0x0000
    cld            ! 'direction'=0, movs moves forward
do_move:
    mov    es,ax        ! destination segment //es+di 目的地址
    add    ax,#0x1000
    cmp    ax,#0x9000
    jz    end_move
    mov    ds,ax        ! source segment //ds+si:源地址
    sub    di,di
    sub    si,si
    mov     cx,#0x8000 //movsw循环的次数
    rep
    movsw
    jmp    do_move
  •  加载GDT和LDT,选择A20地址线,系统进入保护模式。其中GDT初始设置值(包含三个描述符)如下:
gdt:
    .word    0,0,0,0        ! dummy

    .word    0x07FF        ! 8Mb - limit=2047 (2048*4096=8Mb) //代码段
    .word    0x0000        ! base address=0
    .word    0x9A00        ! code read/exec
    .word    0x00C0        ! granularity=4096, 386

    .word    0x07FF        ! 8Mb - limit=2047 (2048*4096=8Mb) //数据段
    .word    0x0000        ! base address=0
    .word    0x9200        ! data read/write
    .word    0x00C0        ! granularity=4096, 386

 

备注:GDT描述符定义 -》 BYTE0,BYTE1(段界限),BYTE2、BYTE3、BYTE4(段基地址1),BYTE5,BYTE6(属性)、BYTE7(段基地址2)。上述代码中比较困惑的是为什么代码段和地址段的基地址都是0x0000。

  • 操作8259中断控制器,应该是初始化芯片,未细看;
  • 跳转至gdt的第二个描述符,即地址0x0000处,为sysyem模块的head.s,参看链接过程中生成的system.map,该地址重定向到的函数是head.s的startup。这里比较困惑的是为什么0x0000处会是head.s,代码段在链接的时候,多个目标文件不是会重新组合吗?难道是老的连接器采用不整合,简单拼接的方法??
    mov    ax,#0x0001    ! protected mode (PE) bit
    lmsw    ax        ! This is it!
    jmpi    0,8        ! jmp offset 0 of segment 8 (cs) //一定要注意此时已经是保护模式,跳转的是GDT的偏移:)

 

posted @ 2013-05-04 08:26  Fredric_2013  阅读(540)  评论(0编辑  收藏  举报