zoukankan      html  css  js  c++  java
  • x01.os.18: MBR

    硬盘不同于软盘,它是要分区的。这时,mbr(master boot record)便不可少了。安装 os 硬盘的第一扇区,开始有一小段不多于 446 字节的程序,然后是分区表 512-446-2 字节,然后是引导标志 0xAA55 两字节。这一小段程序,便是 mbr 的主体。mbr 首先将其自身复制到 0x0600 处,代码如下:

    ; 0x7C00 => 0x0600
        mov        si, sp
        push       si
        mov        di, 0x0600
        mov        cx, 0x200
        cld
        rep        movsw
        

    这是要给分区的引导代码腾位置。操作系统的引导代码,可能位于软盘,光盘等 Media 中,其代码首先便是 org   0x7C00,所以 mbr 复制自身进行重定位,就必不可少了。

    第二步,当然就是寻找活动分区的启动代码了。有这么一句:test  dl, dl。这个 dl 的值,便是 drive number, 由 bios 的 int 0x19 取得。通过 dl 判断设备的类型,作不同的选择。mbr.s 的内容如下:

    ; ----------------------
    ; mbr.s (c) 2014 by x01
    ; ----------------------
    
    P_EntrySize        equ        16        ; 分区表每项为 16 字节
    P_PartOffset    equ        0x1BE     ; 分区表在引导扇区的偏移位置
    P_BootOffset    equ        0        ; 分区项中引导标志的偏移位置
    P_TypeOffset    equ        4        ; 分区项中分区类型的偏移位置
    P_LbaOffset        equ        8        ; 分区项中起始扇区 LBA 的偏移位置
    
    ; Partition table struct
    ; ----------------------
    ; offset    len                    description
    ;   0         1            状态(80h=可引导,00h=不可引导,其他不合法)
    ;    1         1            起始磁头号
    ;    2         1            起始扇区号(仅用了低 6 位,高 2 位为起始柱面号的第 8-9 位
    ;    3         1            起始柱面号的低 8 位
    ;    4         1            分区类型(System ID)
    ;    5         1            结束磁头号
    ;    6         1            结束扇区号(仅用了低 6 位,高 2 位为结束柱面号的第 8-9 位
    ;    7         1            结束柱面号的低 8 位
    ;    8         4            起始扇区的 LBA
    ;    12         4            扇区数目
    
    boot:
        xor        ax, ax
        mov        ds, ax
        mov        es, ax
        cli
        mov        ss, ax        ; ds = es = ss = 0, 段偏移地址直接映射为物理地址
        mov        sp, 0x7C00
        sti
    
        ; 0x7C00 => 0x0600
        mov        si, sp
        push    si
        mov        di, 0x0600
        mov        cx, 0x200
        cld
        rep        movsw
    
        jmp        0:0x0600 + active
    
    active:
        test    dl, dl        ; BIOS int 19h => dl = drive_nr
                            ; SF <- MSB(dl): most significact bit, 1 is -, 0 is +
        jns        nextdisk
    
        mov        si, 0x0600 + P_PartOffset
        
    find:
        cmp        byte [si + P_TypeOffset], 0        ; if not equal 0 then can use
        jz        nextpart
        test    byte [si + P_BootOffset], 0x80    ; 0x80: bootable
        jz        nextpart
    
    loadpart:
        call    load
        jc        error
        ret                ; goto secondary boot => 0x0000:0x7C00
        
    nextpart:
        add        si, P_EntrySize
        cmp        si, 0x0600 + P_PartOffset + 4 * P_EntrySize
        jb        find
        
        call    print
        db        "No active partition"
        jmp        reboot
        
    nextdisk:
        inc        dl
        test    dl, dl
        js        nexthd
        int        0x11        ; get active drive info
        shl        ax, 2        ; floppy info at al[6-7], but after shl at ah[0-1]
        and     ah, 3
        cmp        dl, ah        ; dl <= ah then floppy exist
        ja        nextdisk
        call    loadfloppy
        jc        nextdisk
        ret
        
    nexthd:
        call    loadfloppy
    
    error:
        jc        handle_err
        ret
    
    ; load floppy 0 sector
    loadfloppy:
        mov        si, 0x0600 + zero - P_LbaOffset
        
    ; load hd boot
    load:
        mov        di, 3
        
    retry:
        push    dx    ; dl = old drive_nr protect
        
        push    es
        push    di
        
        ; Get disk info(int 0x13: ah=0x8)
        ; ch: cyl low 8 bit, cl[6-7]: cyl high 2 bit
        ; cl[0-5]: sectors per track
        ; dh: heads, dl: drive_nr
        mov        ah, 0x08
        int        0x13
        
        pop        di
        pop        es
        
        and        cl, 0x3F    ; sectors base 1
        inc        dh            ; heads base 0, so inc
        
        mov        al, cl        ; al = cl = sectors per track
        mul        dh            ; ax = cyl sectors = heads * sectors_per_track
        mov        bx, ax
        
        mov        ax, word [si + P_LbaOffset + 0]
        mov        dx, word [si + P_LbaOffset + 2]    ; dx:ax = secondary boot offset
        
        cmp        dx, (0x16390 * 0xFF * 0x3F - 0xFF) >> 0x10
        jae        bigdisk
        
        div        bx        ; /: ax is cyl_nr, mod: dx is cyl_offset
        xchg    ax, dx
        mov        ch, dl    ; ch is cyl_nr low 8 bit
        
        div        cl        ; /: al is head_nr, mod: ah is track offset(base 0)
        xor        dl, dl
        shr        dx, 2    ; dl[6-7] = cyl_nr high 2 bit
        or        dl, ah    ; dl low 5 bit store track offset
        mov        cl, dl    ; cl high 2 bit is cyl high 2 bit, cl low 5 bit is track offset
        inc        cl        ; base 1
        pop        dx        ; old drive_nr
        mov        dh, al    ; head_nr => dh
        mov        bx, 0x7C00    ; es:bx is load addr
        mov        ax, 0x0201    ; read disk sector entry_point parameter
        int        0x13        ; read 1 sector to es:bx
        jmp        read_check
        
    bigdisk:
        mov        bx, dx
        pop        dx
        push    si
        mov        si, 0x0600 + dap_offset    ; dap: disk addr packet, for up 8G
        mov        word [si + 8], ax        ; low 
        mov        word [si + 0xA], bx        ; high
        mov        ah, 0x42                ; extend read parameter
        int        0x13
        pop        si
        
    read_check:
        jnc        read_ok
        cmp        ah, 0x80    ; timeout
        je        read_bad
        dec        di
        jl        read_bad
        xor        ah, ah
        int        0x13
        jnc        retry
        
    read_bad:
        stc
        ret        ; have a bug, need clear zero
        
    read_ok:
        cmp        dword [0x7C00 + 510], 0xAA55
        jne        notboot
        ret
        
    notboot:
        call    print
        db        "Not bootable"
        jmp        reboot
        
    handle_err:
        mov        si, 0x7C00 + err_nr + 1        ; err_nr low bit
        
    print_num:
        mov        al, ah    ; ah: int 0x13 error code
        and        al, 0x0F
        cmp        al, 0xA
        jb        digit
        add        al, 0x7
        
    digit:
        add        byte [si], al    ; err_nr low bit is '0', after add is correct number
        dec        si                ; err_nr high bit
        mov        cl, 4
        shr        ah, cl
        jnz        print_num
        call    print
        db        "Read error"
        
    err_nr:
        db        "00"
        
    reboot:
        call     print
        db        "Hit any key reboot."
        xor        ah, ah
        int        0x16    ; wait key
        call    print
        db        "
    "
        int        0x19    ; reboot
        
    print:
        pop        si        ; ip => get string addr
    
    print_next:
        lodsb            ; al = *si++
        test    al, al
        jz        print_done
        mov        ah, 0x0E
        mov        bx, 0x0001
        int        0x10
        jmp        print_next
        
    print_done:
        jmp        si
        
    dap_offset:
        PacketSize        db    0x10
        Reserved        db    0x0
        BlockCount        dw    0x1
        BufferOffset    dw    0x7C00
        BufferSegment    dw    0x0
        BlockNumLow        dd    0x0
    zero:
        BlockNumHigh    dd    0x0
        
    times 510-($-$$)     db    0
    BootFlag            dw    0xAA55
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
    View Code

    后面加了两句引导标志,是为了快速检验一下运行效果,实际是不需要的。minix 通过 installboot 程序来完成组装与添加。检验方法如下:

    1.编译: nasm -o mbr mbr.s

    2.写入硬盘:dd if=mbr of=c.img bs=512 count=1 conv=notrunc

    其中,c.img 是硬盘映像。配置 bochs 后运行,可看到因找不到活动分区而停止。当然,这又是另一个问题,就不多说了。

  • 相关阅读:
    谷歌关闭中国区购物搜索小思考
    java生成本地头文件用javah出错问题
    hadoop源代码分析(4)org.apache.hadoop.util包GenericOptionsParser类【原创】
    Ext.util.MixedCollection 用法
    eval 函数用法
    Rails Devise_demo
    rails rake 指南
    accepts_nested_attributes_for
    将Rails3.0无缝升级到Rails3.1.0.beta1
    spork + autotest 实现rails自动化测试
  • 原文地址:https://www.cnblogs.com/china_x01/p/4179085.html
Copyright © 2011-2022 走看看