zoukankan      html  css  js  c++  java
  • linux0.11的bootsect.s和setup.s

     1、计算机的启动

       1、首先计算机的工作原理可以简单的概述为取指,执行;再取指,再执行;以此类推的过程,cpu就是一个不停取指执行不会休息的机器。
       2、那么x86结构的计算机上电后是怎么工作的呢?其实上电后(未加载操作系统代码之前)会先执行内存中一段为BIOS固化的区域,这段区域是每次开机都必须执行的,正常情况下不被我们所控,主要作用是对一些硬件环境做出检测,是否有硬件损坏。这段期间cpu处在实模式下工作。在BIOS代码执行完毕后,cpu会去磁盘的0磁道0扇区读取512字节到内存地址的0x7c00处,然后设置cs:ip = 0x7c00,开始取指,执行。。。这512个字节就是今天的重点,操作系统的引导代码bootsect.s就放在其中。
       3、bootsect.s就是一个操作系统的引导代码,一个操作系统的起步就从这里开始。因此bootsect.s重要性无可厚非。
    2、 bootsect.s
      bootsect.s的作用:
      1、bootsect.s在执行时,首先将自身代码内存位置0x7c00开始的512个字节 挪到0x90000开始的内存地址处,然后载入setup.s代码块(又一个重点)到0x90200位置开始的 4*512字节(这是setup.s)的大小。
        mov ax,#BOOTSEG        !BOOTSEG=0x7c0
        mov ds,ax
        mov ax,#SETUPSEG       !SETUPSEG=0x9000
        mov es,ax
        mov cx,#256
        sub si,si
        sub di,di
        rep
        movs              ! ds:si -->  es:di 
        jmpi load_setup,SETUPSEG     !jmpi是段间跳转,具体跳转的地址为9000:load_setup 
         load_setup:   

        load_setup:
        mov dx,#0x0000                  
        mov cx,#0x0002    !cl表示从第二个扇区开始读
        mov bx,#0x0200      !bx表示段内偏移地址 ,读到0x90200
        mov ax,#0x0200+SETUPLEN
        int 0x13                           !0x13号中断开始读磁盘

        jnc ok_load_setup          !读取成功后跳转
        mov dx,#0x0000
        mov ax,#0x0000
        int 0x13
        jmp load_setup
      ok_load_setup:
        jmpi 0,SETUP   !SETUP=0x9020  最后执行段间跳转指令,cs:ip-->9020:0

      2、载入setup程序后bootsect继续执行,先向屏幕打印提示system is loading... 在此的提示就和window开机的窗口是一个原理。最后bootsect在将system模块读入后,完成使命,将执行权交到setup模块。

        mov ah,#0x03    !功能号ah=0x03
        xor bh,bh    !页号,应该是屏幕位置的页号
        int 0x10      !读取光标所在的位置 返回参数保存在dx寄存器中
        mov cx,#36     !设置字符串长度 
        mov bx,#0x0007       !bl = 0x07 表示字符属性为normal
        mov bp,#msg1     !设置字符串偏移
        mov ax,#0x07c0  !7c00是bootsect模块所在首地址
        mov es,ax      !设置字符串基地址  es:bp 表示要显示字符串的内存地址
        mov ax,#0x1301      !ah = 0x13 表示显示字符功能号,al = 0x01 表示光标的属性在bl保存。
        int 0x10      !开启中断,开始从内存中读字符到屏幕中

    3、setup.s

      setup.s的功能:setup的主要功能是首先获得光标,内存,显卡,磁盘等参数存放在0x90000为起始地址的空间中,在这个模块之前放的bootsect.s,现在bootsect.s已经执行完成,这段空间也可以重新可利用了。然后将system模块从起始地址0x10000的所有代码,挪到0x0000(内存的起始地址处,之后system就一直存在于此处)。然后setup会初始化gdt表,idt表等等,最后用一个很酷的指令开启32位寻址方式,进入保护模式(在bootsect和setup执行的过程中cpu一直处于实模式,16位地址模式,最多能寻址1M的空间)。保护模式可以寻址4G的内存空间。

        mov ax,#0x0001

         mov cr1,ax    !等价于lmsw ax      将cr0寄存器最后一位置1,便进入了保护模式

         jmpi 0,8

        

                                这两幅图来自linux0.11内核完全注释v3.0版

    4、具体实验(用代码实践实践)

          

          截图所示是,操作系统的第二个实验,改写bootsect.s 和setup.s从新编译后,实现开机引导启动,获取硬件参数,显示到屏幕上。

    实验具体代码:

    SETUPLEN=2
    SETUPSEG=0x9000
    SETUP=0x9020
    BOOTSEG=0x7c0
    entry _start
    _start:
    mov ah,#0x03
    xor bh,bh
    int 0x10
    mov cx,#36
    mov bx,#0x0007
    mov bp,#msg1
    mov ax,#0x07c0
    mov es,ax
    mov ax,#0x1301
    int 0x10

    mov ax,#BOOTSEG
    mov ds,ax
    mov ax,#SETUPSEG
    mov es,ax
    mov cx,#256
    sub si,si
    sub di,di
    rep
    movs
    jmpi load_setup,SETUPSEG

    load_setup:
    mov dx,#0x0000
    mov cx,#0x0002
    mov bx,#0x0200
    mov ax,#0x0200+SETUPLEN
    int 0x13
    jnc ok_load_setup
    mov dx,#0x0000
    mov ax,#0x0000
    int 0x13
    jmp load_setup
    ok_load_setup:
    jmpi 0,SETUP
    msg1:
    .byte 13,10
    .ascii "Hello OS world, my name is til"
    .byte 13,10,13,10
    .org 510
    boot_flag:
    .word 0xAA55
    -------------------------------------------------以上是2019.11.9实验二6.8bootsect.s正确代码

    INITSEG = 0x9000
    entry _start
    _start:
    ! Print "NOW we are in SETUP"
    mov ah,#0x03
    xor bh,bh
    int 0x10
    mov cx,#25
    mov bx,#0x0007
    mov bp,#msg2
    mov ax,cs
    mov es,ax
    mov ax,#0x1301
    int 0x10

    mov ax,cs
    mov es,ax
    ! init ss:sp
    mov ax,#INITSEG
    mov ss,ax
    mov sp,#0xFF00

    ! Get Params
    mov ax,#INITSEG
    mov ds,ax
    mov ah,#0x03
    xor bh,bh
    int 0x10
    mov [0],dx
    mov ah,#0x88
    int 0x15
    mov [2],ax
    mov ax,#0x0000
    mov ds,ax
    lds si,[4*0x41]
    mov ax,#INITSEG
    mov es,ax
    mov di,#0x0004
    mov cx,#0x10
    rep
    movsb
    ! Be Ready to Print
    mov ax,cs
    mov es,ax
    mov ax,#INITSEG
    mov ds,ax

    ! Cursor Position
    mov ah,#0x03
    xor bh,bh
    int 0x10
    mov cx,#18
    mov bx,#0x0007
    mov bp,#msg_cursor
    mov ax,#0x1301
    int 0x10
    mov dx,[0]
    call print_hex
    ! Memory Size
    mov ah,#0x03
    xor bh,bh
    int 0x10
    mov cx,#14
    mov bx,#0x0007
    mov bp,#msg_memory
    mov ax,#0x1301
    int 0x10
    mov dx,[2]
    call print_hex
    ! Add KB
    mov ah,#0x03
    xor bh,bh
    int 0x10
    mov cx,#2
    mov bx,#0x0007
    mov bp,#msg_kb
    mov ax,#0x1301
    int 0x10
    ! Cyles
    mov ah,#0x03
    xor bh,bh
    int 0x10
    mov cx,#7
    mov bx,#0x0007
    mov bp,#msg_cyles
    mov ax,#0x1301
    int 0x10
    mov dx,[4]
    call print_hex
    ! Heads
    mov ah,#0x03
    xor bh,bh
    int 0x10
    mov cx,#8
    mov bx,#0x0007
    mov bp,#msg_heads
    mov ax,#0x1301
    int 0x10
    mov dx,[6]
    call print_hex
    ! Secotrs
    mov ah,#0x03
    xor bh,bh
    int 0x10
    mov cx,#10
    mov bx,#0x0007
    mov bp,#msg_sectors
    mov ax,#0x1301
    int 0x10
    mov dx,[12]
    call print_hex
    inf_loop:
    jmp inf_loop

    print_hex:
    mov cx,#4

    print_digit:
    rol dx,#4        !循环左移命令,最高位的4bit放在最低位的4bit上,因为4bit是一个16进制字符
    mov ax,#0xe0f      !0x10号中断,功能号ah=0x0e表示显示al所对应ascii码的字符到屏幕上。这里的低16位是掩码
               !特别注意,区别上面功能号为0x13是显示es:bp内存地址的字符到屏幕上
    and al,dl        !将dl的低4位通过and操作放到al的低4位
    add al,#0x30      !al = al + 0x30 因为0x30~0x39为数字
    cmp al,#0x3a         !判断al中存放是否为数字
    jl outp          !如果为数字跳转
    add al,#0x07      !否则+7表示为一个字母 因为字母a~f的ascii码为 0x41~0x46
    outp:
    int 0x10        !将al中的内容以ascii码形式输出到屏幕上
    loop print_digit      !循环四次,把dx的每四位都拿出来输出一次
    ret !四次结束后返回。

    print_nl:

    mov ax,#0xe0d ! CR
    int 0x10
    mov al,#0xa ! LF
    int 0x10
    ret
    msg2:
    .byte 13,10
    .ascii "NOW we are in SETUP"
    .byte 13,10,13,10
    msg_cursor:
    .byte 13,10
    .ascii "Cursor position:"
    msg_memory:
    .byte 13,10
    .ascii "Memory Size:"
    msg_cyles:
    .byte 13,10
    .ascii "Cyls:"
    msg_heads:
    .byte 13,10
    .ascii "Heads:"
    msg_sectors:
    .byte 13,10
    .ascii "Sectors:"
    msg_kb:
    .ascii "KB"
    .org 510
    boot_flag:
    .word 0xAA55
    ----------------------------------------------以上是2019.11.9实验二6.8 setup.s正确代码

      

  • 相关阅读:
    mysql服务的注册,启动、停止、注销。 [delphi代码实现]
    java初始化
    git的使用
    jmeter测试
    Linux上安装Redis
    java多线程
    设计模式之装饰着模式
    IO流之字符流知识总结
    IO流之字节流知识总结
    java File类
  • 原文地址:https://www.cnblogs.com/Ccluck-tian/p/11827500.html
Copyright © 2011-2022 走看看