Linux0.11源码学习--操作系统启动

Linux0.11启动过程

启动过程

需要重点记住:cpu按照pc寄存器的值取值执行,取值后pc的值会加一

  1. 系统加电 从bios启动系统
    系统加电时,cs 寄存器的值是0xFFFF pc 寄存器的值是0x0000
    cs的值左移4位加上pc值等于0xFFFF0 ,cpu从0xFFFF0开始寻址,这个地址映射的bios rom,这段代码会检查内存、硬盘 等设备,并将硬盘的第一个扇区读入到内存的0x7C00处
  2. 硬盘的第一个扇区存放的程序源码为bootsect.s,是操作系统的引导程序,从这一步开始进入操作代码
  3. bootsect会依次读入setup和sytem,
    启动引导试内核在内存中会移动,移动情况如下图:


    启动引导时内核在内存中的移动

Linux0.11内存划分

boot 文件夹源码解析

bootsect.s 源码介绍

!
! SYS_SIZE is the number of clicks (16 bytes) to be loaded.
! 0x3000 is 0x30000 bytes = 196kB, more than enough for current
! versions of linux
!
SYSSIZE = 0x3000  ## 左移4位置等于 3*16^4= 192 kB  ,
!
!   bootsect.s      (C) 1991 Linus Torvalds
!
! bootsect.s is loaded at 0x7c00 by the bios-startup routines, and moves
! iself out of the way to address 0x90000, and jumps there.
!
! It then loads 'setup' directly after itself (0x90200), and the system
! at 0x10000, using BIOS interrupts. 
!
! NOTE! currently system is at most 8*65536 bytes long. This should be no
! problem, even in the future. I want to keep it simple. This 512 kB
! kernel size should be enough, especially as this doesn't contain the
! buffer cache as in minix
!
! The loader has been made as simple as possible, and continuos
! read errors will result in a unbreakable loop. Reboot by hand. It
! loads pretty fast by getting whole sectors at a time whenever possible.

SETUPLEN = 4                ! 加载的扇区数
BOOTSEG  = 0x07c0           ! original address of boot-sector 7*16^3+12*16^2 =31k
INITSEG  = 0x9000           ! 会将 boot-sector移动到此处 9*16*4 = 576k
SETUPSEG = 0x9020           ! setup 会加载到这里 INITSEG  + 512
SYSSEG   = 0x1000           ! system loaded at 0x10000 (65536).
ENDSEG   = SYSSEG + SYSSIZE     ! where to stop loading

entry _start  !程序入口
_start:
    mov ax,#BOOTSEG   !ax寄存器的值设置为0x07c0
    mov ds,ax             !ds(数据段)寄存器的值设置为0x07c0
    mov ax,#INITSEG  !ax寄存器的值设置为 0x9000
    mov es,ax              !es寄存器的值设置为 0x9000
    mov cx,#256         ! cx寄存器的值设为256 ,表示循环次数,
    sub si,si               ! si寄存器 置0  源地址 ds:si = 0x07C0:0x0000
    sub di,di      ! di寄存器 置0  目的地址 es:di = 0x9000:0x0000
    rep                 ! 循环,每循环一次cx减1  
    movw  !移动一个字, 8086 字长16bit,两个字节,总共移动512字节
    jmpi    go,INITSEG !跳转到go 并将cs 设为0x9000
go: mov ax,cs       !后面三句 把ds es都设为0x9000
    mov ds,ax
    mov es,ax
! put stack at 0x9ff00.
    mov ss,ax
    mov sp,#0xFF00      ! arbitrary value >>512

! load the setup-sectors directly after the bootblock.
! Note that 'es' is already set up.

!load_setup用途是利用 BIOS 中断 INT 0x13 将 setup 模块从磁盘第 2 个扇区
! 开始读到 0x90200 开始处,共读 4 个扇区。如果读出错,则复位驱动器,并
! 重试,没有退路。INT 0x13 的使用方法如下:
! 读扇区:
! ah = 0x02 - 读磁盘扇区到内存;al = 需要读出的扇区数量;
! ch = 磁道(柱面)号的低 8 位; cl = 开始扇区(0-5 位),磁道号高 2 位(6-7);
! dh = 磁头号; dl = 驱动器号(如果是硬盘则要置位 7);
! es:bx ?指向数据缓冲区; 如果出错则 CF 标志置位。
load_setup: !加载setup模块
    mov dx,#0x0000      ! drive 0, head 0
    mov cx,#0x0002      ! sector 2, track 0
    mov bx,#0x0200      ! address = 512, in INITSEG 在前面已经将es设置为0x9000
    mov ax,#0x0200+SETUPLEN ! service 2, nr of sectors
    int 0x13            ! read it
    jnc ok_load_setup       ! ok - continue
    mov dx,#0x0000
    mov ax,#0x0000      ! reset the diskette
    int 0x13
    j   load_setup

ok_load_setup:

! Get disk drive parameters, specifically nr of sectors/track

    mov dl,#0x00
    mov ax,#0x0800      ! AH=8 is get drive parameters
    int 0x13
    mov ch,#0x00
    seg cs
    mov sectors,cx
    mov ax,#INITSEG
    mov es,ax

! Print some inane message    这里是往屏幕打印一些字符

    mov ah,#0x03        ! read cursor pos
    xor bh,bh
    int 0x10
    
    mov cx,#24   ! 打印字符的数量
    mov bx,#0x0007      ! page 0, attribute 7 (normal)
    mov bp,#msg1               ! bp指想msg1 ,这个是下一步要实验的该的地方
    mov ax,#0x1301      ! write string, move cursor
    int 0x10                  !显示器中断

! ok, we've written the message, now
! we want to load the system (at 0x10000)

    mov ax,#SYSSEG     !将ax寄存器设为0x1000
    mov es,ax       ! segment of 0x010000 
    call    read_it            ! 加载system模块
    call    kill_motor

! After that we check which root-device to use. If the device is
! defined (!= 0), nothing is done and the given device is used.
! Otherwise, either /dev/PS0 (2,28) or /dev/at0 (2,8), depending
! on the number of sectors that the BIOS reports currently.

    seg cs
    mov ax,root_dev
    cmp ax,#0
    jne root_defined
    seg cs
    mov bx,sectors
    mov ax,#0x0208      ! /dev/ps0 - 1.2Mb
    cmp bx,#15
    je  root_defined
    mov ax,#0x021c      ! /dev/PS0 - 1.44Mb
    cmp bx,#18
    je  root_defined
undef_root:
    jmp undef_root
root_defined:
    seg cs
    mov root_dev,ax

! after that (everyting loaded), we jump to
! the setup-routine loaded directly after
! the bootblock:

    jmpi    0,SETUPSEG

! This routine loads the system at address 0x10000, making sure
! no 64kB boundaries are crossed. We try to load it as fast as
! possible, loading whole tracks whenever we can.
!
! in:   es - starting address segment (normally 0x1000)
!
sread:  .word 1+SETUPLEN    ! sectors read of current track
head:   .word 0         ! current head
track:  .word 0         ! current track

read_it:
    mov ax,es
    test ax,#0x0fff
die:    jne die         ! es must be at 64kB boundary
    xor bx,bx       ! bx is starting address within segment
rp_read:
    mov ax,es
    cmp ax,#ENDSEG      ! have we loaded all yet?
    jb ok1_read
    ret
ok1_read:
    seg cs
    mov ax,sectors
    sub ax,sread
    mov cx,ax
    shl cx,#9
    add cx,bx
    jnc ok2_read
    je ok2_read
    xor ax,ax
    sub ax,bx
    shr ax,#9
ok2_read:
    call read_track
    mov cx,ax
    add ax,sread
    seg cs
    cmp ax,sectors
    jne ok3_read
    mov ax,#1
    sub ax,head
    jne ok4_read
    inc track
ok4_read:
    mov head,ax
    xor ax,ax
ok3_read:
    mov sread,ax
    shl cx,#9
    add bx,cx
    jnc rp_read
    mov ax,es
    add ax,#0x1000
    mov es,ax
    xor bx,bx
    jmp rp_read



sectors:
    .word 0

msg1:
    .byte 13,10     !13是ascii码的回车键 10是ascii的换行符
    .ascii "Loading system ..."
    .byte 13,10,13,10   !两次回车加换行

源码实验

  1. 实验目的
    原始系统启动界面显示Loading system ...


    原始启动界面

    本实验将Loading system ... 改为guojiangwei is testing ...

  2. 实验过程
    Loading system ... 长度为18
    guojiangwei is testing ... 长度为26
    mov cx,#24 改为mov cx,#32 比之前多打印8个字符
    修改如下代码:
    msg1:
    .byte 13,10 !13是ascii码的回车键 10是ascii的换行符
    .ascii "guojiangwei is testing ..."
    .byte 13,10,13,10 !两次回车加换行
root@c38ac0380e56:~/oslab/linux-0.11# pwd
/root/oslab/linux-0.11
root@c38ac0380e56:~/oslab/linux-0.11# make all
  1. 实验结果


    实验结果
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 215,384评论 6 497
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,845评论 3 391
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 161,148评论 0 351
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,640评论 1 290
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,731评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,712评论 1 294
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,703评论 3 415
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,473评论 0 270
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,915评论 1 307
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,227评论 2 331
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,384评论 1 345
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,063评论 5 340
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,706评论 3 324
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,302评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,531评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,321评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,248评论 2 352

推荐阅读更多精彩内容