• linux 0.11内核源码(1)之开机启动过程


    1.开机

            当我们按下电脑开机键的时候,BIOS程序会充当搬运工的身份,将磁盘0盘0道1扇区(启动区)的代码原封不动的搬运到内存的0x07c0的位置,然后CPU就开始从0x07c0的位置不停机的运行着,具体运行什么内容,我们后面慢慢分析。

    1.1什么是启动区

    启动区:只要磁盘0盘0道1扇区的结尾的两个字节分别是0x55和0xaa,BIOS即可认为该扇区是启动区。

    2.磁盘0盘0道1扇区的代码是什么

    磁盘0盘0道1扇区的代码是位于boot文件夹下面的bootsect.s的二进制文件                

    3.bootsect.s代码讲解

    mov ax,0x07c0

    mov ds,ax

    设置段寄存器的值,因为汇编限制,ds这些寄存器不可以直接赋值,我们需要通过ax寄存器进行赋值,ds是段寄存器,设置好了段寄存器,我们写地址的时候可以直接写偏移地址即可,不需要加段地址了,可以省很多重复性工作。

       mov    ax,BYTE PTR INITSEG        ;// 将es段寄存器置为9000h
        mov    es,ax
        mov    cx,256            ;// 移动计数值 = 256字 = 512 字节
        sub    si,si            ;// 源地址   ds:si = 07C0h:0000h
        sub    di,di            ;// 目的地址 es:di = 9000h:0000h
        rep movsw            ;// 重复执行,直到cx = 0;移动1个字

    这段代码的意思就是将内存地址0x7c00处的代码移动512字节,也就是复制到0x90000处。

    ;    jmp INITSEG:[go]     ;// 间接跳转。这里INITSEG指出跳转到的段地址。
        db 0eah                ;// 间接跳转指令码
        dw go
        dw INITSEG
    go:    mov    ax,cs            ;// 将ds、es和ss都置成移动后代码所在的段处(9000h)。
        mov    ds,ax            ;// 由于程序中有堆栈操作(push,pop,call),因此必须设置堆栈。
        mov    es,ax 

        mov    ss,ax
        mov    sp,0FF00h        ;/* 由于代码段移动过了,所以要重新设置堆栈段的位置。
                            ;   sp只要指向远大于512偏移(即地址90200h)处
                            ;   都可以。因为从90200h地址开始处还要放置setup程序,
                            ;   而此时setup程序大约为4个扇区,因此sp要指向大
                            ;   于(200h + 200h*4 + 堆栈大小)处。 */
     

    go是一个标签,经过编译之后,会生成一个偏移地址。这段代码的意思就是跳转到go标签去执行程序。 这段代码就是一些准备工作,准备加载setup模块的代码数据。

    load_setup:
        ;// 以下10行的用途是利用BIOS中断INT 13h将setup模块从磁盘第2个扇区
        ;// 开始读到90200h开始处,共读4个扇区。如果读出错,则复位驱动器,并
        ;// 重试,没有退路。
        ;// INT 13h 的使用方法如下:
        ;// ah = 02h - 读磁盘扇区到内存;al = 需要读出的扇区数量;
        ;// ch = 磁道(柱面)号的低8位;  cl = 开始扇区(0-5位),磁道号高2位(6-7);
        ;// dh = 磁头号;                  dl = 驱动器号(如果是硬盘则要置为7);
        ;// es:bx ->指向数据缓冲区;  如果出错则CF标志置位。 
        mov    dx,0000h                ;// drive 0, head 0
        mov    cx,0002h                ;// sector 2, track 0
        mov    bx,0200h                ;// address = 512, in INITSEG
        mov    ax,0200h+SETUPLEN        ;// service 2, nr of sectors
        int    13h                    ;// read it
        jnc    ok_load_setup            ;// ok - continue
        mov    dx,0000h
        mov    ax,0000h                ;// reset the diskette
        int    13h
        jmp    load_setup

    ok_load_setup:

    int 指令就是汇编指令里面的中断指令,根据中断号去中断描述符表里面找到段选择子和偏移地址 .

    段选择子去全局描述符表找到段描述符,根据现在的段描述符和偏移地址就可以去找到程序入口地址,然后去执行。0x13是BIOS提取给我们写好的中断程序,是读取磁盘相关的函数。

     这些代码,用途是利用BIOS中断INT 13h将setup模块从磁盘第2个扇区开始的数据,加载到内存0x90200处,共加载4个扇区(1-5扇区)

  • 相关阅读:
    Java面向对象:封装
    【翻译】两阶段运动伪影(MA)去除算法
    linux内核模块编译方法详解
    JavaScript流程控制语法
    【深度学习实验】卷积神经网络(一):卷积运算及其Pytorch实现(一维卷积:窄卷积、宽卷积、等宽卷积;二维卷积)
    VINS学习02——VINS系列代码所有依赖库安装(保姆级)
    CSS基础入门01
    14:00面试,14:06就出来了,问的问题有点变态。。。
    行业篇:自动驾驶场景下的数据标注类别分享
    CSS选择器分类(儿子选择器、 序选择器、下一个兄弟选择器+)
  • 原文地址:https://blog.csdn.net/m0_46392035/article/details/125566562