亚洲av成人无遮挡网站在线观看,少妇性bbb搡bbb爽爽爽,亚洲av日韩精品久久久久久,兔费看少妇性l交大片免费,无码少妇一区二区三区

  免費(fèi)注冊 查看新帖 |

Chinaunix

  平臺(tái) 論壇 博客 文庫
12下一頁
最近訪問板塊 發(fā)新帖
查看: 11934 | 回復(fù): 12
打印 上一主題 下一主題

FreeBSD7.0 /sys/boot/i386/mbr/mbr.s源代碼分析 [復(fù)制鏈接]

論壇徽章:
0
跳轉(zhuǎn)到指定樓層
1 [收藏(0)] [報(bào)告]
發(fā)表于 2008-06-27 16:35 |只看該作者 |倒序?yàn)g覽
分析數(shù)據(jù)采集自bochs+FreeBSD7.0環(huán)境,分析過程中參考了Luonix Luo和qiuhanty關(guān)于boot0.s的分析文章。


#
# Copyright (c) 1999 Robert Nordier
# All rights reserved.
#
# Redistribution and use in source and binary forms are freely
# permitted provided that the above copyright notice and this
# paragraph and the following disclaimer are duplicated in all
# such forms.
#
# This software is provided "AS IS" and without any express or
# implied warranties, including, without limitation, the implied
# warranties of merchantability and fitness for a particular
# purpose.
#

# $FreeBSD: src/sys/boot/i386/mbr/mbr.s,v 1.7 2004/08/28 08:39:35 yar Exp $

# A 512 byte MBR boot manager that simply boots the active partition.

        .set LOAD,0x7c00        # Load address
        .set EXEC,0x600         # Execution address
        .set PT_OFF,0x1be       # Partition table
        .set MAGIC,0xaa55       # Magic: bootable
        .set FL_PACKET,0x80     # Flag: try EDD

        .set NHRDRV,0x475       # Number of hard drives

        .globl start            # Entry point
        .code16

#
# Setup the segment registers for flat addressing and setup the stack.
#
                                                    # 在/sys/boot/i386/mbr/Makefile中定義的LDFLAGS包含了
                                                    # "-e start -Ttext ${ORG}",即指定程序入口為"start",
                                                    # 并指定.text section的起始為止在絕對(duì)地址ORG處,而ORG
                                                    # 在同一Makefile中被定義為0x600,因此,出現(xiàn)在匯編指令
                                                    # 中的"$start"即表示0x600。這部分引導(dǎo)代碼是被bios加載到
                                                    # 0x7c00的,所以此處"start:"標(biāo)號(hào)對(duì)應(yīng)的"cld"指令的地址
                                                    # 就是0x7c00,這是第一條引導(dǎo)指令。此時(shí),cpu主要寄存器的
                                                    # 內(nèi)容如下:
                                                    #    rax: 0x00000000:0000aa55 rcx: 0x00000000:00000000
                                                    #    rdx: 0x00000000:00000080 rbx: 0x00000000:00000000
                                                    #    rsp: 0x00000000:0000ffda rbp: 0x00000000:00000000
                                                    #    rsi: 0x00000000:ffff0000 rdi: 0x00000000:0008ffac
                                                    #    r8 : 0x00000000:00000000 r9 : 0x00000000:00000000
                                                    #    r10: 0x00000000:00000000 r11: 0x00000000:00000000
                                                    #    r12: 0x00000000:00000000 r13: 0x00000000:00000000
                                                    #    r14: 0x00000000:00000000 r15: 0x00000000:00000000
                                                    #    rip: 0x00000000:00007c00
                                                    #    eflags 0x00000082
start:  cld                     # String ops inc    # 保證后續(xù)字符串操作為增向。
        xorw %ax,%ax            # Zero
        movw %ax,%es            # Address
        movw %ax,%ds            #  data
        movw %ax,%ss            # Set up
        movw $LOAD,%sp          #  stack            # 將ax、es、ds、ss清0,并將sp指向"LOAD",LOAD在本文中被
                                                    # 定義為0x7c00,這是bios加載引導(dǎo)扇區(qū)的地址,也即"start:"
                                                    # 標(biāo)號(hào)處的"cld"指令的地址。此時(shí),cpu主要寄存器的內(nèi)容如下:
                                                    #    rax: 0x00000000:00000000 rcx: 0x00000000:00000000
                                                    #    rdx: 0x00000000:00000080 rbx: 0x00000000:00000000
                                                    #    rsp: 0x00000000:00007c00 rbp: 0x00000000:00000000
                                                    #    rsi: 0x00000000:ffff0000 rdi: 0x00000000:0008ffac
                                                    #    r8 : 0x00000000:00000000 r9 : 0x00000000:00000000
                                                    #    r10: 0x00000000:00000000 r11: 0x00000000:00000000
                                                    #    r12: 0x00000000:00000000 r13: 0x00000000:00000000
                                                    #    r14: 0x00000000:00000000 r15: 0x00000000:00000000
                                                    #    rip: 0x00000000:00007c0c
                                                    #    eflags 0x00000046

#
# Relocate ourself to a lower address so that we are out of the way when
# we load in the bootstrap from the partition to boot.
#
        movw $main-EXEC+LOAD,%si        # Source
        movw $main,%di                  # Destination
        movw $0x200-(main-start),%cx    # Byte count
        rep                     # Relocate
        movsb                   #  code             # 由于bios將本段引導(dǎo)代碼的入口加載至0x7c00,而本段代碼鏈接時(shí)
                                                    # 指定的絕對(duì)入口地址是0x600,因此須將本段代碼拷貝至0x600處才能
                                                    # 正確執(zhí)行后續(xù)與地址相關(guān)的指令。下面的jmp指令是在0x7c00區(qū)域
                                                    # 執(zhí)行的最后一條指令,jmp之后就開始在0x600區(qū)域繼續(xù)執(zhí)行新建的
                                                    # 引導(dǎo)代碼復(fù)本了,而在0x600區(qū)域執(zhí)行的第一條語句就是"main:"標(biāo)號(hào)
                                                    # 對(duì)應(yīng)的xorw指令,因此0x7c00區(qū)域中從"start:"到"main:"之間的
                                                    # 內(nèi)容是不用拷貝到0x600的。EXEC在本文件中定義為0x600,這是
                                                    # "start:"標(biāo)號(hào)的鏈接地址,LOAD則是bios對(duì)本段引導(dǎo)代碼的初始加載
                                                    # 位置,即0x7c00,因此,main-EXEC+LOAD就是0x7c00加上"main:"距
                                                    # "start:"的偏移,即"xorw %si,%si"指令在0x7c00區(qū)域的地址,引導(dǎo)
                                                    # 代碼的拷貝從這里開始。拷貝的目的地則直接使用"main:"標(biāo)號(hào)的鏈接
                                                    # 地址,即"xorw %si,%si"指令在0x600區(qū)域的地址。在計(jì)算需要拷貝的
                                                    # 字節(jié)數(shù)時(shí)需要從引導(dǎo)扇區(qū)尺寸512字節(jié)(0x200)中減去
                                                    # "main:"和"start:" 之間的內(nèi)容。執(zhí)行實(shí)際拷貝指令之前cpu主要
                                                    # 寄存器的內(nèi)容如下:
                                                    #    rax: 0x00000000:00000000 rcx: 0x00000000:000001e6
                                                    #    rdx: 0x00000000:00000080 rbx: 0x00000000:00000000
                                                    #    rsp: 0x00000000:00007c00 rbp: 0x00000000:00000000
                                                    #    rsi: 0x00000000:ffff7c1a rdi: 0x00000000:0008061a
                                                    #    r8 : 0x00000000:00000000 r9 : 0x00000000:00000000
                                                    #    r10: 0x00000000:00000000 r11: 0x00000000:00000000
                                                    #    r12: 0x00000000:00000000 r13: 0x00000000:00000000
                                                    #    r14: 0x00000000:00000000 r15: 0x00000000:00000000
                                                    #    rip: 0x00000000:00007c15
                                                    #    eflags 0x00000046
                                                    # 此時(shí),源地址是0x7c1a,目的地址是0x061a,分別是0x7c00和0x600
                                                    # 偏移0x1a的位置,這正是"main:"和"start:"之間的距離?截愅瓿
                                                    # 之后cpu主要寄存器的內(nèi)容如下:
                                                    #    rax: 0x00000000:00000000 rcx: 0x00000000:00000000
                                                    #    rdx: 0x00000000:00000080 rbx: 0x00000000:00000000
                                                    #    rsp: 0x00000000:00007c00 rbp: 0x00000000:00000000
                                                    #    rsi: 0x00000000:ffff7e00 rdi: 0x00000000:00080800
                                                    #    r8 : 0x00000000:00000000 r9 : 0x00000000:00000000
                                                    #    r10: 0x00000000:00000000 r11: 0x00000000:00000000
                                                    #    r12: 0x00000000:00000000 r13: 0x00000000:00000000
                                                    #    r14: 0x00000000:00000000 r15: 0x00000000:00000000
                                                    #    rip: 0x00000000:00007c17
                                                    #    eflags 0x00000046
#
# Jump to the relocated code.
#
        jmp main-LOAD+EXEC      # To relocated code # 跳轉(zhuǎn)至0x600區(qū)域中"main:"標(biāo)號(hào)對(duì)應(yīng)的指令位置,這是在0x7c00
                                                    # 區(qū)域執(zhí)行的最后一條指令。跳轉(zhuǎn)完成之后cpu主要寄存器的內(nèi)容如下:
                                                    #    rax: 0x00000000:00000000 rcx: 0x00000000:00000000
                                                    #    rdx: 0x00000000:00000080 rbx: 0x00000000:00000000
                                                    #    rsp: 0x00000000:00007c00 rbp: 0x00000000:00000000
                                                    #    rsi: 0x00000000:ffff7e00 rdi: 0x00000000:00080800
                                                    #    r8 : 0x00000000:00000000 r9 : 0x00000000:00000000
                                                    #    r10: 0x00000000:00000000 r11: 0x00000000:00000000
                                                    #    r12: 0x00000000:00000000 r13: 0x00000000:00000000
                                                    #    r14: 0x00000000:00000000 r15: 0x00000000:00000000
                                                    #    rip: 0x00000000:0000061a
                                                    #    eflags 0x00000046
#
# Scan the partition table looking for an active entry.  Note that %ch is
# zero from the repeated string instruction above.  We save the offset of
# the active partition in %si and scan the entire table to ensure that only
# one partition is marked active.
#
main:   xorw %si,%si            # No active partition
        movw $partbl,%bx        # Partition table
        movb $0x4,%cl           # Number of entries # 首先清除si寄存器。然后將位于本段引導(dǎo)扇區(qū)代碼尾端的分區(qū)表
                                                    # 的地址寫入bx寄存器,將分區(qū)表的條目數(shù)寫入cl。此時(shí)cpu主要
                                                    # 寄存器的內(nèi)容如下:
                                                    #    rax: 0x00000000:00000000 rcx: 0x00000000:00000004
                                                    #    rdx: 0x00000000:00000080 rbx: 0x00000000:000007be
                                                    #    rsp: 0x00000000:00007c00 rbp: 0x00000000:00000000
                                                    #    rsi: 0x00000000:ffff0000 rdi: 0x00000000:00080800
                                                    #    r8 : 0x00000000:00000000 r9 : 0x00000000:00000000
                                                    #    r10: 0x00000000:00000000 r11: 0x00000000:00000000
                                                    #    r12: 0x00000000:00000000 r13: 0x00000000:00000000
                                                    #    r14: 0x00000000:00000000 r15: 0x00000000:00000000
                                                    #    rip: 0x00000000:00000621
                                                    #    eflags 0x00000046
                                                    # 此處寫入bx的分區(qū)表地址是0x7be,這是距引導(dǎo)扇區(qū)尾端66字節(jié)
                                                    # 的地方,分區(qū)表一共四個(gè)條目,因此cl的值是4。每個(gè)條目占用
                                                    # 16字節(jié),共64字節(jié),最后的2個(gè)字節(jié)是用來存放幻數(shù)0xaa55的。
                                                    # 參見本文末尾對(duì)"partbl:"的定義。
                                                    # 此時(shí),0x7be之后66個(gè)字節(jié)的內(nèi)容如下:
                                                    #    0x7be : 0x80 0x01 0x01 0x00 0xa5 0x0f 0xff 0xff
                                                    #    0x7c6 : 0x3f 0x00 0x00 0x00 0xa1 0xff 0x7f 0x00
                                                    #    0x7ce : 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00
                                                    #    0x7d6 : 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00
                                                    #    0x7de : 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00
                                                    #    0x7e6 : 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00
                                                    #    0x7ee : 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00
                                                    #    0x7f6 : 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00
                                                    #    0x7fe : 0x55 0xaa
main.1: cmpb %ch,(%bx)       # Null entry?          # 通過分區(qū)條目第一字節(jié)判斷該分區(qū)是否為活動(dòng)分區(qū),0x80為是,0為否
        je main.2            # Yes                  # 此分區(qū)非活動(dòng)分區(qū),準(zhǔn)備查詢下一分區(qū)
        jg err_pt            # If 0x1..0x7f         # 分區(qū)條目第一字節(jié)的合法值只能是0x80或0,否則報(bào)錯(cuò)
        testw %si,%si        # Active already found?    # 通過si是否為0判斷是否已找到一個(gè)活動(dòng)分區(qū)
        jnz err_pt           # Yes                  # 只能有一個(gè)活動(dòng)分區(qū),否則報(bào)錯(cuò)
        movw %bx,%si         # Point to active      # 讓si指向活動(dòng)分區(qū)表?xiàng)l目
                                                    # 對(duì)于示例情況,分區(qū)表第一條目第一字節(jié)為0x80,為活動(dòng)分區(qū),
                                                    # 因此在這里對(duì)si進(jìn)行設(shè)置,此時(shí)cpu主要寄存器的內(nèi)容如下:
                                                    #    rax: 0x00000000:00000000 rcx: 0x00000000:00000004
                                                    #    rdx: 0x00000000:00000080 rbx: 0x00000000:000007be
                                                    #    rsp: 0x00000000:00007c00 rbp: 0x00000000:00000000
                                                    #    rsi: 0x00000000:ffff07be rdi: 0x00000000:00080800
                                                    #    r8 : 0x00000000:00000000 r9 : 0x00000000:00000000
                                                    #    r10: 0x00000000:00000000 r11: 0x00000000:00000000
                                                    #    r12: 0x00000000:00000000 r13: 0x00000000:00000000
                                                    #    r14: 0x00000000:00000000 r15: 0x00000000:00000000
                                                    #    rip: 0x00000000:0000062d
                                                    #    eflags 0x00000046

main.2: addb $0x10,%bl       # Till                 # 讓bx指向下一個(gè)分區(qū)表?xiàng)l目
        loop main.1          #  done                # "main.1:"一共執(zhí)行4次,依次分析分區(qū)表中的4個(gè)條目
        testw %si,%si        # Active found?        # 判斷是否找到了一個(gè)活動(dòng)分區(qū)(有多個(gè)活動(dòng)分區(qū)的情況已在前面報(bào)錯(cuò))
        jnz main.3           # Yes                  # 找到活動(dòng)分區(qū)則跳轉(zhuǎn)至"main.3"
        int $0x18            # BIOS: Diskless boot  # 沒有找到活動(dòng)分區(qū)則嘗試無盤引導(dǎo)
#
# Ok, we've found a possible active partition.  Check to see that the drive
# is a valid hard drive number.
#
main.3: cmpb $0x80,%dl       # Drive valid?         # dl中存放的是bios傳入的引導(dǎo)設(shè)備編號(hào),從0x80開始表示硬盤
        jb main.4            # No                   # 若bios傳入的不是硬盤則將之前找到的活動(dòng)分區(qū)的第一字節(jié)存入dl
        movb NHRDRV,%dh      # Calculate the highest    # bios將硬盤數(shù)目保存在NHRDRV,即0x475處,此處將其寫入dh
        addb $0x80,%dh       #  drive number available  # 硬盤號(hào)從0x80開始,加上硬盤數(shù)目即得到最大可能硬盤號(hào)的上限
        cmpb %dh,%dl         # Within range?        # 判斷bios傳入的硬盤號(hào)是否在合法范圍之內(nèi)
        jb main.5            # Yes                  # 硬盤及分區(qū)有效,準(zhǔn)備讀入對(duì)應(yīng)扇區(qū)
main.4: movb (%si),%dl       # Load drive           # 若bios傳入的不是硬盤或者硬盤號(hào)非法則將之前找到的活動(dòng)分區(qū)的
                                                    # 第一字節(jié)存入dl
#
# Ok, now that we have a valid drive and partition entry, load the CHS from
# the partition entry and read the sector from the disk.
#
                                                    # 執(zhí)行至此已經(jīng)找到了一個(gè)有效的硬盤分區(qū)入口,此時(shí)cpu主要
                                                    # 寄存器的內(nèi)容如下:
                                                    #    rax: 0x00000000:00000000 rcx: 0x00000000:00000000
                                                    #    rdx: 0x00000000:00008180 rbx: 0x00000000:000007fe
                                                    #    rsp: 0x00000000:00007c00 rbp: 0x00000000:00000000
                                                    #    rsi: 0x00000000:ffff07be rdi: 0x00000000:00080800
                                                    #    r8 : 0x00000000:00000000 r9 : 0x00000000:00000000
                                                    #    r10: 0x00000000:00000000 r11: 0x00000000:00000000
                                                    #    r12: 0x00000000:00000000 r13: 0x00000000:00000000
                                                    #    r14: 0x00000000:00000000 r15: 0x00000000:00000000
                                                    #    rip: 0x00000000:0000064a
                                                    #    eflags 0x00000097
                                                    # 此時(shí)si指向的是之前找到的有效分區(qū)條目
main.5: movw %sp,%di         # Save stack pointer   # 將sp保存到di
        movb 0x1(%si),%dh    # Load head            # 分區(qū)條目第1(從0開始計(jì)算)字節(jié)存放的是磁頭號(hào),將其存入dh
        movw 0x2(%si),%cx    # Load cylinder:sector # 分區(qū)條目第2、3字節(jié)存放的是柱面號(hào)和扇區(qū)號(hào),其中,第2字節(jié)的
                                                    # 低6位存儲(chǔ)扇區(qū)號(hào),第2字節(jié)的高2位和第3字節(jié)的8位共同存儲(chǔ)
                                                    # 柱面號(hào)。之前找到的有效分區(qū)條目的起始地址是0x7be,它的前
                                                    # 4個(gè)字節(jié)的內(nèi)容如下:
                                                    #    0x00000000000007be : 0x80 0x01 0x01 0x00
                                                    # 表示的就是第0柱面第1磁頭第1扇區(qū)。此處將這兩個(gè)字節(jié)的內(nèi)容
                                                    # 存入cx,此時(shí)cpu主要寄存器的內(nèi)容如下:
                                                    #    rax: 0x00000000:00000000 rcx: 0x00000000:00000001
                                                    #    rdx: 0x00000000:00000180 rbx: 0x00000000:000007fe
                                                    #    rsp: 0x00000000:00007c00 rbp: 0x00000000:00000000
                                                    #    rsi: 0x00000000:ffff07be rdi: 0x00000000:00087c00
                                                    #    r8 : 0x00000000:00000000 r9 : 0x00000000:00000000
                                                    #    r10: 0x00000000:00000000 r11: 0x00000000:00000000
                                                    #    r12: 0x00000000:00000000 r13: 0x00000000:00000000
                                                    #    r14: 0x00000000:00000000 r15: 0x00000000:00000000
                                                    #    rip: 0x00000000:00000652
                                                    #    eflags 0x00000097
        movw $LOAD,%bx       # Transfer buffer      # 把bios初始加載引導(dǎo)代碼的地址0x7c00賦給bx
                                                    # 至此已基本完成使用0x13中斷的0x02功能讀入磁盤扇區(qū)的準(zhǔn)備,
                                                    # 即cx存放柱面號(hào)和扇區(qū)號(hào),dh存放磁頭號(hào),dl存放磁盤號(hào),
                                                    # es:bx指向用于存放讀入的扇區(qū)數(shù)據(jù)的緩沖區(qū)地址。不過在決定
                                                    # 使用0x13中斷的0x02功能之前,此處要先嘗試是否能使用0x13
                                                    # 中斷的0x42功能讀入相應(yīng)的扇區(qū)數(shù)據(jù)。在無法使用0x42功能的
                                                    # 情況下才會(huì)到"main.7:"去使用0x02功能。
        testb $FL_PACKET,flags      # Try EDD?      # 判斷是否需要嘗試BIOS Enhanced Disk Drive Services。
                                                    # "flags:"標(biāo)號(hào)在本文尾端定義,位于緊鄰分區(qū)表之前的一個(gè)字節(jié),
                                                    # 內(nèi)容為FLAGS,這個(gè)宏在/sys/boot/i386/mbr/Makefile中定義為
                                                    # BOOT_MBR_FLAGS,即0x80。BOOT_MBR_FLAGS在本文開始處定義為0x80。
        jz main.7            # No.                  # 若上述標(biāo)志的設(shè)置決定不去判斷能否使用EDD功能讀入扇區(qū),則跳轉(zhuǎn)
                                                    # 至"main.7"使用0x13中斷的0x02功能讀入扇區(qū)。由于到此為止的
                                                    # 判斷尚未對(duì)cx和bx進(jìn)行壓棧,所以可以直接跳轉(zhuǎn)至"main.7:",
                                                    # 而后續(xù)判斷中發(fā)現(xiàn)無法使用EDD功能時(shí),由于已經(jīng)對(duì)cx、bx進(jìn)行了
                                                    # 壓棧和修改,則需跳轉(zhuǎn)至"main.6:"先恢復(fù)cx、bx的內(nèi)容再到
                                                    # "main.7:"處使用0x13中斷的0x02功能。
        pushw %cx            # Save %cx             # 測試是否支持EDD擴(kuò)展功能,中斷號(hào)0x13,入?yún)h存放功能號(hào)0x41,
        pushw %bx            # Save %bx             # bx存放幻數(shù)0x55aa。部分返回結(jié)果需要寫入cx,因此先保存cx、bx。
        movw $0x55aa,%bx     # Magic
        movb $0x41,%ah       # BIOS: EDD extensions
        int $0x13            #  present?
        jc main.6            # No.                  # CF為1表示不支持
        cmpw $0xaa55,%bx     # Magic ok?            # 回寫至bx的幻數(shù)應(yīng)為0xaa55
        jne main.6           # No.                  # 幻數(shù)不正確則跳轉(zhuǎn)至"main.6:"
        testb $0x1,%cl       # Packet mode present? # 返回值cl第1位表示是否使用packet結(jié)構(gòu)訪問設(shè)備
        jz main.6            # No.                  # 不使用packet結(jié)構(gòu)則跳轉(zhuǎn)至"main.6:"
        popw %bx             # Restore %bx          # 恢復(fù)bx。此時(shí)cpu主要寄存器的內(nèi)容如下:
                                                    #    rax: 0x00000000:00003000 rcx: 0x00000000:00000007
                                                    #    rdx: 0x00000000:00000180 rbx: 0x00000000:00007c00
                                                    #    rsp: 0x00000000:00007bfe rbp: 0x00000000:00000000
                                                    #    rsi: 0x00000000:ffff07be rdi: 0x00000000:00087c00
                                                    #    r8 : 0x00000000:00000000 r9 : 0x00000000:00000000
                                                    #    r10: 0x00000000:00000000 r11: 0x00000000:00000000
                                                    #    r12: 0x00000000:00000000 r13: 0x00000000:00000000
                                                    #    r14: 0x00000000:00000000 r15: 0x00000000:00000000
                                                    #    rip: 0x00000000:00000673
                                                    #    eflags 0x00000002
        pushl $0x0           # Set the LBA
        pushl 0x8(%si)       #  address
        pushw %es            # Set the address of
        pushw %bx            #  the transfer buffer
        pushw $0x1           # Read 1 sector
        pushw $0x10          # Packet length        # 準(zhǔn)備使用0x13中斷的0x42功能以擴(kuò)展方式從磁盤讀入扇區(qū),
                                            # 這一組壓棧指令就是在棧上構(gòu)造磁盤地址包(Disk Address Packet)。
                                            # 壓棧完成之后,cpu主要寄存器的內(nèi)容如下:
                                            #    rax: 0x00000000:00004200 rcx: 0x00000000:00000007
                                            #    rdx: 0x00000000:00000180 rbx: 0x00000000:00007c00
                                            #    rsp: 0x00000000:00007bee rbp: 0x00000000:00000000
                                            #    rsi: 0x00000000:ffff7bee rdi: 0x00000000:00087c00
                                            #    r8 : 0x00000000:00000000 r9 : 0x00000000:00000000
                                            #    r10: 0x00000000:00000000 r11: 0x00000000:00000000
                                            #    r12: 0x00000000:00000000 r13: 0x00000000:00000000
                                            #    r14: 0x00000000:00000000 r15: 0x00000000:00000000
                                            #    rip: 0x00000000:00000685
                                            #    eflags 0x00000002
                                            # sp寄存器指向0x7bee,此時(shí)棧頂附近16字節(jié)的內(nèi)容如下:
                                            #    0x0000000000007bee : 0x10 0x00 0x01 0x00 0x00 0x7c 0x00 0x00
                                            #    0x0000000000007bf6 : 0x3f 0x00 0x00 0x00 0x00 0x00 0x00 0x00
                                            # 第0字節(jié)表示DAP的大小,此處為0x10,即16字節(jié),第1字節(jié)未使用,應(yīng)填0,
                                            # 這兩個(gè)字節(jié)是由"pushw $0x10"指令壓入的。第2字節(jié)表示需要讀入的扇區(qū)數(shù)目,
                                            # 此處為0x01,只讀入1個(gè)扇區(qū),第3字節(jié)未使用,應(yīng)填0,這兩個(gè)字節(jié)是由
                                            # "pushw $0x1"指令壓入的。第4到7字節(jié)是以"segment: offset"的形式給出的
                                            # 用于存放讀入的扇區(qū)數(shù)據(jù)的緩沖區(qū)的地址,此處是0x0000:7c00,這實(shí)際上
                                            # 就是bios初始加載主引導(dǎo)記錄的地址,即本段代碼被搬移到0x600區(qū)域之前
                                            # 所在的位置,這4個(gè)字節(jié)是由"pushw %es"和"pushw %bx"指令壓入的。
                                            # 第8到15字節(jié)表示的是讀入操作的起始扇區(qū)號(hào)(從0開始計(jì)算),此處是
                                            # 0x000000000000003f,本次讀入的是第63扇區(qū),這8個(gè)字節(jié)是由
                                            # "pushl $0x0"和"pushl 0x8(%si)"指令壓入的,si指向的是之前在分區(qū)表中
                                            # 找到的活動(dòng)分區(qū)條目,它的第8到11字節(jié)存放的就是該分區(qū)的起始扇區(qū)號(hào):
                                            #    0x00000000000007be : 0x80 0x01 0x01 0x00 0xa5 0x0f 0xff 0xff
                                            #    0x00000000000007c6 : 0x3f 0x00 0x00 0x00 0xa1 0xff 0x7f 0x00
        movw %sp,%si         # Packer pointer       # 在棧上完成DAP的構(gòu)造之后,將其起始地址賦給si
        movw $0x4200,%ax     # BIOS:    LBA Read from disk    # 寫入功能號(hào)0x42
        jmp main.8           # Skip the CHS setup   # 跳轉(zhuǎn)到"main.8:"調(diào)用0x13中斷
main.6: popw %bx             # Restore %bx          # 若不支持EDD功能,則與此恢復(fù)之前壓棧的bx和cx,壓棧之前cx
                                                    # 存放的是柱面號(hào)和扇區(qū)號(hào),bx存放的是用于存放讀入的扇區(qū)數(shù)據(jù)的
                                                    # 緩沖區(qū)地址,都是0x13中斷的0x02功能所需的入?yún)ⅰ?br />         popw %cx             # Restore %cx
main.7: movw $0x201,%ax      # BIOS: Read from disk # 填寫0x13中斷的0x02功能所需的最后一點(diǎn)入?yún)。al存放需要讀入的
                                                    # 扇區(qū)數(shù)目,此處為1,只讀入一個(gè)扇區(qū)。ah存放功能號(hào)0x02。
main.8: int $0x13            # Call the BIOS        # 不管是使用0x02功能讀入,還是使用0x42功能讀入,至此已完成各自
                                                    # 入?yún)⒌脑O(shè)置,統(tǒng)一運(yùn)行至此執(zhí)行0x13中斷。
        movw %di,%sp         # Restore stack        # 將sp恢復(fù)至扇區(qū)拷貝之前的位置,即在"main.5:"處保存在di中的內(nèi)容
        jc err_rd            # If error             # CF為1表示讀入過程出錯(cuò)
#
# Now that we've loaded the bootstrap, check for the 0xaa55 signature.  If it
# is present, execute the bootstrap we just loaded.
#
                                                    # 至此已完成扇區(qū)的讀入,cpu主要寄存器的內(nèi)容如下:
                                                    #    rax: 0x00000000:00000000 rcx: 0x00000000:00000007
                                                    #    rdx: 0x00000000:00000180 rbx: 0x00000000:00007c00
                                                    #    rsp: 0x00000000:00007c00 rbp: 0x00000000:00000000
                                                    #    rsi: 0x00000000:ffff7bee rdi: 0x00000000:00087c00
                                                    #    r8 : 0x00000000:00000000 r9 : 0x00000000:00000000
                                                    #    r10: 0x00000000:00000000 r11: 0x00000000:00000000
                                                    #    r12: 0x00000000:00000000 r13: 0x00000000:00000000
                                                    #    r14: 0x00000000:00000000 r15: 0x00000000:00000000
                                                    #    rip: 0x00000000:00000692
                                                    #    eflags 0x00000002
        cmpw $MAGIC,0x1fe(%bx)      # Bootable?     # 前面已經(jīng)通過0x13中斷從磁盤讀入了一個(gè)512字節(jié)的扇區(qū)到
                                                    # 0x7c00區(qū)域,此處判斷該扇區(qū)的最后兩個(gè)字節(jié)是否為0xaa55,
                                                    # 以確定該扇區(qū)是否可引導(dǎo)。
        jne err_os           # No                   # 讀入扇區(qū)不可引導(dǎo)則報(bào)錯(cuò)
        jmp *%bx             # Invoke bootstrap     # 跳轉(zhuǎn)至0x7c00執(zhí)行剛讀入的bootstrap代碼
#
# Various error message entry points.
#
err_pt: movw $msg_pt,%si     # "Invalid partition
        jmp putstr           #  table"

err_rd: movw $msg_rd,%si     # "Error loading
        jmp putstr           #  operating system"

err_os: movw $msg_os,%si     # "Missing operating
        jmp putstr           #  system"
#
# Output an ASCIZ string to the console via the BIOS.
#
putstr.0: movw $0x7,%bx      # Page:attribute
        movb $0xe,%ah        # BIOS: Display
        int $0x10            #  character
putstr: lodsb                # Get character
        testb %al,%al        # End of string?
        jnz putstr.0         # No
putstr.1: jmp putstr.1       # Await reset

msg_pt: .asciz "Invalid partition table"
msg_rd: .asciz "Error loading operating system"
msg_os: .asciz "Missing operating system"

        .org PT_OFF-1,0x90
flags:  .byte FLAGS          # Flags

partbl: .fill 0x10,0x4,0x0   # Partition table
        .word MAGIC          # Magic number   



[ 本帖最后由 雨絲風(fēng)片 于 2008-6-27 17:17 編輯 ]

評(píng)分

參與人數(shù) 1可用積分 +5 收起 理由
gvim + 5 精品文章

查看全部評(píng)分

論壇徽章:
1
榮譽(yù)版主
日期:2011-11-23 16:44:17
2 [報(bào)告]
發(fā)表于 2008-06-27 18:09 |只看該作者
嘿嘿 我剛裝完FreeBSD7.0 就看到了這個(gè)文章 學(xué)習(xí)啦

論壇徽章:
1
寅虎
日期:2013-09-29 23:15:15
3 [報(bào)告]
發(fā)表于 2008-06-27 19:41 |只看該作者

論壇徽章:
0
4 [報(bào)告]
發(fā)表于 2008-06-27 20:46 |只看該作者
過幾天考完試我發(fā)個(gè)netbsd/algor或loongson的

論壇徽章:
2
亥豬
日期:2014-03-19 16:36:35午馬
日期:2014-11-23 23:48:46
5 [報(bào)告]
發(fā)表于 2008-06-30 09:25 |只看該作者
這個(gè)mbr.s只是一個(gè)開始

論壇徽章:
2
丑牛
日期:2013-09-29 09:47:222015七夕節(jié)徽章
日期:2015-08-21 11:06:17
6 [報(bào)告]
發(fā)表于 2008-06-30 11:38 |只看該作者
原帖由 gvim 于 2008-6-30 09:25 發(fā)表
這個(gè)mbr.s只是一個(gè)開始

期待中

論壇徽章:
0
7 [報(bào)告]
發(fā)表于 2008-06-30 13:03 |只看該作者
原帖由 gvim 于 2008-6-30 09:25 發(fā)表
這個(gè)mbr.s只是一個(gè)開始


從BSD源代碼的角度來講,這句話是正確的。

論壇徽章:
2
亥豬
日期:2014-03-19 16:36:35午馬
日期:2014-11-23 23:48:46
8 [報(bào)告]
發(fā)表于 2008-07-01 11:38 |只看該作者
為什么是 0x0600?
這個(gè)地址是必須的(dedicated)還是約定上(convenient)的?

論壇徽章:
0
9 [報(bào)告]
發(fā)表于 2008-07-01 12:14 |只看該作者
原帖由 gvim 于 2008-7-1 11:38 發(fā)表
為什么是 0x0600?
這個(gè)地址是必須的(dedicated)還是約定上(convenient)的?


不是必須的,算是約定的。

因?yàn)?mbr.S 不能直接加載內(nèi)核,所以需要加載其他的引導(dǎo)程序,為了方便起見通常將新的引導(dǎo)程序加載到 0x7c00 處,所以要把自己拷貝到另外一個(gè)地方。

BIOS加載 mbr 之后只有分散的幾片空間可以用,最初的人在這幾片空間中選擇了 0x600,后續(xù)也就沒有再做修改。

論壇徽章:
2
亥豬
日期:2014-03-19 16:36:35午馬
日期:2014-11-23 23:48:46
10 [報(bào)告]
發(fā)表于 2008-07-01 13:51 |只看該作者
原帖由 abutter 于 2008-7-1 12:14 發(fā)表


不是必須的,算是約定的。

因?yàn)?mbr.S 不能直接加載內(nèi)核,所以需要加載其他的引導(dǎo)程序,為了方便起見通常將新的引導(dǎo)程序加載到 0x7c00 處,所以要把自己拷貝到另外一個(gè)地方。

BIOS加載 mbr 之后只有分 ...


大概看了看lilo和grub,對(duì)比BSD的mbr,發(fā)現(xiàn)mbr本身的移動(dòng)也只是為了方便
lilo和bsd一樣,都會(huì)搬移到0x600
而grub的處理就是另一種模樣:


[url]http://blog.sina.com.cn/s/reader_4c1810e0010009je.html
[/url]


果然還是過了2月沒更新了。。。囧rz。。。
這篇也是剛好學(xué)校論壇上有人在討論grub然后寫的。。。就放這里算備份一下吧。。。-ω-

聲明:以下內(nèi)容部分整理部分我扯。。。出了問題我不負(fù)責(zé)。。。=v=b CNLAS 07.08.18

以下所說的過程和代碼以grub0.97版為例。。。grub2和1的啟動(dòng)過程有點(diǎn)區(qū)別。。。后面再說。。。給出的路徑大部分是指源代碼包的

1、BIOS啟動(dòng)sc80t說了。。。但是注意一點(diǎn)BIOS是參與內(nèi)存編址的。。。所以不存在讀入物理內(nèi)存這個(gè)概念

2、BIOS將0頭0道1扇區(qū)也就是MBR讀入內(nèi)存地址0x7c00處。。。然后檢查0x7dfe是否等于0xaa55(WORD)確認(rèn)是有效MBR后開始執(zhí)行

3、Grub安裝好后0頭0道1扇區(qū)就是stage1(/stage1/stage1.s)。。。其實(shí)stage1的任務(wù)非常的單純。。。去讀取0頭0道2扇區(qū)然后閃人。。。XD
0頭0道2扇區(qū)的內(nèi)容就是源代碼里\stage2\start.s編譯后也是一個(gè)512字節(jié)。。。stage1將start.s讀入內(nèi)存地址0x8000然后跳過去執(zhí)行

4、start.s就是stage1.5 or stage2的入口。。。一般情況下stage2還是放在需要具體的文件系統(tǒng)下的。。。這個(gè)時(shí)候需要讀取stage1.5。。。但是注意。。。這里的stage1.5不是/boot目錄下的那些文件。。。你都能讀取/boot目錄了還要stage1.5干嘛。。。
所以這里的stage1.5是將/boot目錄對(duì)應(yīng)的分區(qū)格式的stage1.5文件復(fù)制到了0頭0道3扇區(qū)開始向后的位置。。。stage1.5文件一般就10幾k。。。夠放了。。。


root (hdx,x)/xxx/xxxx

setup (hdx)

當(dāng)你執(zhí)行這些指令的時(shí)候grub就知道自己裝在哪里了。。。然后把對(duì)應(yīng)分區(qū)格式的stage1.5復(fù)制一份到0頭0道3扇區(qū)開始的位置。。。而且grub的安裝目錄就是一個(gè)根分區(qū)下的/boot/grub/。。。這是由源代碼決定的。。。 root指令對(duì)應(yīng)的函數(shù)是builtins.c中的root_func (char *arg, int flags) setup指令對(duì)應(yīng)的函數(shù)是同一個(gè)文件下的setup_func (char *arg, int flags) 這個(gè)文件里還有一個(gè)struct stage1_5_map stage1_5_map[]存放各種文件系統(tǒng)對(duì)應(yīng)的stage1.5的文件名


5、這樣就可以順利的識(shí)別文件系統(tǒng)然后轉(zhuǎn)入stage2的運(yùn)行了。。。stage2的入口在asm.S
(我最早看grub的時(shí)候就是研究這個(gè)文件。。。實(shí)模式保護(hù)模式的轉(zhuǎn)換。。。GDT初始化。。。C語言運(yùn)行環(huán)境初始化。。。都是由這部分代碼完成的。。。也就是說這部分代碼完成了從匯編語言向C語言的進(jìn)化。。。XD)

然后仔細(xì)看asm.s的代碼會(huì)看到

VARIABLE(config_file)

#ifndef STAGE1_5

.string "/boot/grub/menu.lst"

#else /* STAGE1_5 */

.long 0xffffffff

.string "/boot/grub/stage2"

#endif /* STAGE1_5 */

這下知道怎么找到menu.lst了吧。。。

6、asm.s將運(yùn)行環(huán)境都初始化好了之后就進(jìn)入c語言部分。。。這時(shí)轉(zhuǎn)向stage2.c文件的cmain函數(shù)然后grub_open()函數(shù)(disk_io.c)去打開config_file。。。然后由print_entries等等函數(shù)吧菜單顯示出來。。。不管是選了菜單選項(xiàng)還是輸入 grub命令。。。最后都交給comline.c文件里的find_command()函數(shù)去builtin.c文件里的struct builtin *builtin_table[]變量找指令。。。然后執(zhí)行對(duì)應(yīng)指令的xxx_func()函數(shù)(builtin.c)。。。

7、然后grub利用它自己在disk_io.c提供的一些函數(shù)去吧linux的內(nèi)核加載進(jìn)來。。。最后執(zhí)行boot指令。。。移交控制權(quán)。。。然后拍拍屁股走人咯。。。剩下的是linuxkernel的事情了。。。


——————————————LOLI飛過————————————

上面說的是以grub0.97為例的grub1的啟動(dòng)流程和代碼分析。。。
現(xiàn)在grub已經(jīng)開始開發(fā)2了。。。最新版本是1.95
在grub2里引入了kernel。。。而且還有module。。。還真做成miniOS了。。。囧。。。

在grub2里就沒有stage*了。。。
/boot/i386/pc/boot.S對(duì)應(yīng)stage1.s完成stage1的功能。。。去讀取0頭0道2扇區(qū)的內(nèi)容
而在0頭0道2扇區(qū)開始存放的就是grub2里的kernel。。。編譯之后的core.img文件才20幾k對(duì)chs模式的0頭0道64扇區(qū)(32k)來說都放的下。。。而這個(gè)20多k的小東西將完成stage1.5(10幾k)+stage2(100多k)的功能
/kern/i386/pc/startup.s完成gurb1里asm.s的任務(wù)。。。然后轉(zhuǎn)到c語言。。。
/kern/i386/pc/init.c完成kernel的初始化然后轉(zhuǎn)交給/kern/main.c調(diào)用grub_load_modules()加載模塊完成剩下的任務(wù)。。。

暑假實(shí)在是太短了。。。只有一個(gè)星期了。。?诤鷡~~~

[ 本帖最后由 gvim 于 2008-7-1 13:52 編輯 ]
您需要登錄后才可以回帖 登錄 | 注冊

本版積分規(guī)則 發(fā)表回復(fù)

  

北京盛拓優(yōu)訊信息技術(shù)有限公司. 版權(quán)所有 京ICP備16024965號(hào)-6 北京市公安局海淀分局網(wǎng)監(jiān)中心備案編號(hào):11010802020122 niuxiaotong@pcpop.com 17352615567
未成年舉報(bào)專區(qū)
中國互聯(lián)網(wǎng)協(xié)會(huì)會(huì)員  聯(lián)系我們:huangweiwei@itpub.net
感謝所有關(guān)心和支持過ChinaUnix的朋友們 轉(zhuǎn)載本站內(nèi)容請注明原作者名及出處

清除 Cookies - ChinaUnix - Archiver - WAP - TOP