linux0.11在x86架构芯片上启动流程分析

233 阅读4分钟

携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第24天,点击查看活动详情

若看到相同文章,为本人其他平台

intel8086系列的cpu可以分别在16位实模式和32位保护模式下运行。为了兼容intel将所有80x86系列cpu都设计为上电既进入16位实模式状态运行。并将cs值置为:0xffff ip值置为:0x0000.这样cs:ip指向0xffff0

Intel 8086 在16位实模式下可以访问 1MB 的内存空间,地址范围为 0x00000 到 0xFFFFF。

16位实模式下,有20位地址总线,所有可以访问1mb的地址空间。

出于各方面的考虑,计算机系统的设计者将这 1MB 的内存空间从物理上分为几个部分。 8086 有 20 根地址线,但并非全都用来访问 DRAM,也就是内存条。事实上,这些地址 线经过分配,大部分用于访问 DRAM,剩余的部分给了只读存储器 ROM 和外围的板卡.

1.0x00000-0x9FFFF:DRAM(动态随机访问存储器):

2.0xA0000-0xEFFFF: 分给外围设备

3.0xF0000-0xFFFFF: ROM(只读存储器),占据内存顶端的64k空间. 固化了开机时要执行的指令

0xB8000~0xBFFFF : 分给显卡的.

8086加电或复位时,cs=0xffff,ip=0x0000,位于rom处,开始执行bios程序.

物理地址为0xFFFF0, 到最后结束也只有16个字节.所以一般为一个jmp指令.

处理器取指令执行的自然顺序是从内存的低地址向高地址推进.

1.linux0.11启动流程分析

1.1 初始化阶段/boot/中的汇编代码

1.bios入口地址为0xffff0,bios的第一条指令就设计在这个位置上。

2.bios检测显卡内存,并在内存中建立中断向量表和中断服务程序。

中断向量表:0x000000x003ff,1kb的内存空间。并在紧挨着他的位置用256字节构建bios数据区:0x004000x004ff,在大约56kb以后的位置(0x0x0e2ce),加载了8kb左右的与中断向量表相对应的中断服务程序。

3.bios调用0x19中断服务程序(启动加载服务程序)将启动盘的第一个扇区512b读入到内存0x7c00处。这个512b的程序就是启动扇区。就是linux0.11代码中bootsect.s汇编而成的。

4.在bootsect.s中,start.执行将0x7c00处的代码(也就是自己)复制到0x9000处. 然后跳转到新地址中的go标记继续执行.

; 刘十三
; 1.将要加载的setup程序的扇区数(SETUPLEN),和被加载到的位置(SETUPSEG)
; 启动扇区被bios加载的位置(BOOTSEG),和将要移动到的新位置(INITSEG)
; 内核被加载的位置(SYSSEG),内核的末尾位置(ENDSEG)
; 根文件系统设备号(ROOT_DEV)
entry start
start:
    mov    ax,#BOOTSEG
    mov    ds,ax
    mov    ax,#INITSEG
    mov    es,ax
    mov    cx,#256
    sub    si,si
    sub    di,di
    rep
    movw                
    ; 从start到这行, bootsect将自身从内存0x7c00处拷贝到0x9000处.

5.初始化栈寄存器,就可使用push和pop操作, 压栈方向从高地址到低地址。

;  刘十三:
;  2.对DS(数据段寄存器) ES(附加段寄存器) SS(栈基址寄存器) 设置成0x9000, 并将sp(栈顶指针)指向0xff00处.
;  对这几个寄存器的设置,就可以在后边使用push和pop操作。
go:    mov    ax,cs
    mov    ds,ax
    mov    es,ax
;  put stack at 0x9ff00.
    mov    ss,ax
    mov    sp,#0xFF00        ;  arbitrary value >>512

6.调用0x13中断,将软盘从第2扇区开始的4个扇区(2~5扇区),既setup.s对应的程序加载到0x90200处,紧挨着启动扇区。

load_setup:
    mov    dx,#0x0000        ;  drive 0, head 0
    mov    cx,#0x0002        ;  sector 2, track 0
    mov    bx,#0x0200        ;  address = 512, in INITSEG
    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

7.调用0x13中断,将system模块加载到内存。

​ system模块有240个扇区,然后跳转到0x90200处执行。

8.setup.s开始运行,提取内核运行需要的机器系统数据。

从0x41和0x46的中断向量函数中获取硬盘参数表1和硬盘参数表2并分别放在0x9000:0x0080和0x9000:0x0090处。 大约占用内存0x90000~0x901fc. 覆盖了原来的bootsect程序,只剩余2字节未被覆盖。 后续main函数执行时,需要用到这里边的机器系统数据。

未完待续,汇编太多,看不下去了。

1.2 从main到怠速状态

系统调用

1.系统调用号: 对应相应的系统调用。