<span id="mktg5"></span>

<i id="mktg5"><meter id="mktg5"></meter></i>

        <label id="mktg5"><meter id="mktg5"></meter></label>
        最新文章專題視頻專題問答1問答10問答100問答1000問答2000關鍵字專題1關鍵字專題50關鍵字專題500關鍵字專題1500TAG最新視頻文章推薦1 推薦3 推薦5 推薦7 推薦9 推薦11 推薦13 推薦15 推薦17 推薦19 推薦21 推薦23 推薦25 推薦27 推薦29 推薦31 推薦33 推薦35 推薦37視頻文章20視頻文章30視頻文章40視頻文章50視頻文章60 視頻文章70視頻文章80視頻文章90視頻文章100視頻文章120視頻文章140 視頻2關鍵字專題關鍵字專題tag2tag3文章專題文章專題2文章索引1文章索引2文章索引3文章索引4文章索引5123456789101112131415文章專題3
        問答文章1 問答文章501 問答文章1001 問答文章1501 問答文章2001 問答文章2501 問答文章3001 問答文章3501 問答文章4001 問答文章4501 問答文章5001 問答文章5501 問答文章6001 問答文章6501 問答文章7001 問答文章7501 問答文章8001 問答文章8501 問答文章9001 問答文章9501
        當前位置: 首頁 - 科技 - 知識百科 - 正文

        FreeBSD啟動扇區代碼分析(ver5.2.1)

        來源:懂視網 責編:小采 時間:2020-11-09 15:42:07
        文檔

        FreeBSD啟動扇區代碼分析(ver5.2.1)

        FreeBSD啟動扇區代碼分析(ver5.2.1):FreeBSD啟動扇區代碼分析(ver5.2.1) 2007-04-27 來源:cnfug 作者: 關鍵詞: FreeBSD代碼BSD扇區分析 FreeBSD完整的內核代碼在FreeBSD的/sys目錄下。其中,FreeBSD 的 Boot Manager代碼是 sys/boot/i386/boot0/boot0.s,
        推薦度:
        導讀FreeBSD啟動扇區代碼分析(ver5.2.1):FreeBSD啟動扇區代碼分析(ver5.2.1) 2007-04-27 來源:cnfug 作者: 關鍵詞: FreeBSD代碼BSD扇區分析 FreeBSD完整的內核代碼在FreeBSD的/sys目錄下。其中,FreeBSD 的 Boot Manager代碼是 sys/boot/i386/boot0/boot0.s,

        FreeBSD啟動扇區代碼分析(ver5.2.1) 2007-04-27 來源:cnfug 作者: 關鍵詞: FreeBSD代碼BSD扇區分析 FreeBSD完整的內核代碼在FreeBSD的/sys目錄下。其中,FreeBSD 的 Boot Manager代碼是 sys/boot/i386/boot0/boot0.s,它是FreeBSD自帶的Boot Manager,其功

        FreeBSD啟動扇區代碼分析(ver5.2.1)

        2007-04-27 來源:cnfug 作者:

        關鍵詞: FreeBSD 代碼 BSD 扇區 分析

        FreeBSD完整的內核代碼在FreeBSD的 “/sys”目錄下。其中,FreeBSD 的 Boot Manager代碼是 sys/boot/i386/boot0/boot0.s,它是FreeBSD自帶的Boot Manager,其功能雖然不如Linux的lilo和Grub功能強大,但它只需按一個鍵就可以引導,界面直觀。小小的512字節,可以給你一個簡單明 了的啟動選擇界面,還能記住你上次的選擇。以下,就對此代碼進行詳細分析:

        當我們打開計算機電源時,計算機嘰嘰嘎嘎進行設備和內 存檢測過后就讀取硬盤或者軟盤的引導扇區,這個扇區只有512字節,顯然這512字節不能夠有多大作用,這512字節的代碼被BIOS放在地址從 0x0000:0x7c00開始處。然后直接跳轉到0x0000:0x7c00處去執行。以上工作是BIOS 干的,你什么也不用作。操作系統需要通過這個引導扇區代碼再裝載操作系統的其他部分。 在還沒有跳轉到這段代碼之前,也就是BIOS把磁盤的引導扇區讀入到內存之后,其DL和ES、SI寄存器的內容如下: DL:表示啟動設備,例如,如果計算機是從軟盤啟動的則DL=0,若是從IDE的C、D盤(嚴格來說是物理磁盤一和物理磁盤二,而不是邏輯磁盤分區)啟動 的則DL分別為0x80和0x81。如果是從硬盤啟動的話,ES:SI是指向BIOS中的硬盤分區表存放的地址。

        好了,我們現在已經知道,計算機的BIOS已經把引導扇區的512字節的內容讀入到了0:0x7c00處,然后就跳轉到0:0x7C00處去執行,也就是執行引導扇區代碼,引導扇區代碼boot0執行代碼dump如下(它很有用,以后我們還不時回頭來看):

        560)this.style.width=560;'' onmousewheel = ''javascript:return big(this)'' height=517 alt="" src="http://images.51cto.com/files/uploadimg/20051027/104330627.gif" width=590 border=0>

        上圖中的4x16個字節是保留的4個分區信息

        下面,我們對FreeBSD啟動扇區代碼boot0.s進行逐步分析。boot0.s代碼如下:

        #
        # Copyright (c) 1998 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.
        #
        以上的Coyright就不用翻譯了。

        # $FreeBSD: src/sys/boot/i386/boot0/boot0.s,v 1.27 2003/11/20 20:28:18 jhb Exp $
        以上供版本管理軟件使用
         

        # A 512-byte boot manager.

        .set NHRDRV,0x475 # Number of hard drives
        .set ORIGIN,0x600 # Execution address
        .set FAKE,0x800 # Partition entry
        .set LOAD,0x7c00 # Load address

        .set PRT_OFF,0x1be # Partition table

        .set TBL0SZ,0x3 # Table 0 size
        .set TBL1SZ,0xb # Table 1 size

        .set MAGIC,0xaa55 # Magic: bootable
        .set B0MAGIC,0xbb66 # Identification

        .set KEY_ENTER,0x1c # Enter key scan code
        .set KEY_F1,0x3b # F1 key scan code
        .set KEY_1,0x02 # #1 key scan code
        #
        # Addresses in the sector of embedded data values.
        # Accessed with negative offsets from the end of the relocated sector (%ebp).
        #
        .set _NXTDRV,-0x48 # Next drive
        .set _OPT,-0x47 # Default option
        .set _SETDRV,-0x46 # Drive to force
        .set _FLAGS,-0x45 # Flags
        .set _TICKS,-0x44 # Timeout ticks
        .set _FAKE,0x0 # Fake partition entry
        .set _MNUOPT,0xc # Menu options
         

        以上是定義相關的參數值,例如“.set NHRDRV,0x475”類似于C語言中的“#define NHRDRV 0x475”

        .globl start # Entry point
        .code16 # This runs in real mode

        #
        # Initialise segments and registers to known values.
        # segments start at 0.
        # The stack is immediately below the address we were loaded to.
        #
        start:
        cld # String ops inc
        xorw %ax,%ax # Zero
        movw %ax,%es # Address
        movw %ax,%ds # data
        movw %ax,%ss # Set up
        movw $LOAD,%sp # stack
         

        以上代碼:
        1)首先使用“cld”指令清除方向標志,使得以下的進行“rep”操作時SI和DI的值遞增。
        2)使ax清零,并使除代碼段cs外的另外兩個數據段寄存器es、ds和堆棧段ss清零。當然,此時cs
        由于reset或初始上電已經為零了。
        3)BIOS已經把引導扇區的512字節的內容讀入到了0:0x7c00處,movw $LOAD,%sp 使得堆棧指針指向扇區
        代碼(或曰本段代碼 0:0x7c00)的頂部。雖然堆棧向下生長可能會影響代碼的內容,但下面我
        們馬上就把位于0:7c00處代碼移到其他地方去執行。
         

        #
        # Copy this code to the address it was linked for
        #
        movw %sp,%si # Source
        movw $start,%di # Destination
        movw $0x100,%cx # Word count
        rep # Relocate
        movsw # code

        把位于0:7c00處的代碼搬移到0:0x600處。注意,此時由于代碼連接的重定向,$start=0x600。

        #
        # Set address for variable space beyond code, and clear it.
        # Notice that this is also used to point to the values embedded in the block,
        # by using negative offsets.
        movw %di,%bp # Address variables
        movb $0x8,%cl # Words to clear
        rep # Zero
        stosw # them

        通過以上一段代碼的執行,本代碼已被搬移到0:0x600處,此時si=di=0x600+0x100,以上代碼
        把di的值保存到bp,bp此時指向本程序搬移后的未用的空間的首部,且把此bp所指的16字節空間
        清零。以上過程如下圖所示:

        ┏>0:0x600 ┏━━━━━┓
        ┃ ┃ ┃
        ┃ ┃ 搬 ┃
        ┃ ┃ 移 ┃
        ┃ ┃ 之 ┃
        ┃ ┃ 后 ┃
        ┃ ┃ 的 ┃
        ┃ ┃ 代 ┃
        ┃ ┃ 碼 ┃
        ┃ ┃ ┃
        ┃ 0:0x7ff ┣━━━━━┫
        ┃ ┃ 0 ┃<-bp指向這里(0:0x800),以此開始的16字節被清零。
        ┃ ┣━━━━━┫以下所稱的fake partition entry就是指這里。
        ┃ ┃ 0 ┃
        ┃ ┣━━━━━┫
        ┃ ┃ 0 ┃
        ┃ ┣━━━━━┫
        ┃ ┃ 0 ┃
        ┃ ┣━━━━━┫
        ┃ ┃ 0 ┃
        ┃ ┣━━━━━┫
        ┃ ┃ 0 ┃
        ┃ ┣━━━━━┫
        ┃ ┃ 0 ┃
        ┃ ┣━━━━━┫
        ┃ ┃ 0 ┃
        ┃ ┣━━━━━┫
        ┃ ┃ 0 ┃
        ┃ ┣━━━━━┫
        ┃ ┃ 0 ┃
        ┃ ┣━━━━━┫
        ┃ ┃ 0 ┃
        ┃ ┣━━━━━┫
        ┃ ┃ 0 ┃
        ┃ ┣━━━━━┫
        ┃ ┃ 0 ┃
        ┃ ┣━━━━━┫
        ┃ ┃ 0 ┃
        ┃ ┣━━━━━┫
        ┃ ┃ 0 ┃
        ┃ ┣━━━━━┫
        ┃ ┃ 0 ┃
        ┃ ┗━━━━━┛
        0:0x7c00 ┏━━━━━┓ ┛
        ┃ ┃
        ┃ 搬 ┃
        ┃ 移 ┃
        ┃ 之 ┃
        ┃ 前 ┃
        ┃ 的 ┃
        ┃ 代 ┃
        ┃ 碼 ┃
        ┃ ┃
        0:0x7dff ┗━━━━━┛

        圖(二)
        #
        # Relocate to the new copy of the code.
        #
        incb -0xe(%di) # Sector number
        jmp main-LOAD+ORIGIN # To relocated code

        把以上清零的16字節的第二個字節置為1,表示我們已經讀取了一個分區。然后跳轉到搬
        移之后的新代碼的main處執行。

        #
        # Check what flags were loaded with us, specifically, Use a predefined Drive.
        # If what the bios gives us is bad, use the ''0'' in the block instead, as well.
        #
        main:
        testb $0x20,_FLAGS(%bp) # Set number drive?
        jnz main.1 # Yes
        testb %dl,%dl # Drive number valid?
        js main.2 # Possibly (0x80 set)
        main.1:
        movb _SETDRV(%bp),%dl # Drive number to use
        上面說過,BIOS把磁盤的引導扇區讀入到內存之后,其dl的內容表示啟動設備,但我們安裝好FreeBSD
        之后,我們可以改變此引導扇區的內容,其中的一個改變就是可以使我們可以“手動指定”我們實際安
        裝FreeBSD的分區,如果我們希望指定FreeBSD所在的boot分區,那么我們在bp-0x45處的位置
        (即_FLAGS(%bp)處)的bit 0x20置1,那么上面的“movb _SETDRV(%bp),%dl”一句中movb
        _SETDRV(%bp),%dl(即bp-0x46)即指向我們“手動指定”FreeBSD所在分區代碼,例如,IDE的C、D
        盤(嚴格來說是第一個物理磁盤的第一個和第二個分區)的代碼分別為 0x80和0x81。如果沒有“手動指
        定”啟動分區,那么,我們缺省使用機器當前啟動的分區,上面說過,機器當前啟動的分區代碼放在dl中。

        因為FreeBSD Boot Manager 不可能安裝到軟盤(如果從軟盤啟動則dl為0),所以,使用testb %dl,%dl
        來判斷驅動器代碼是否合法(volid)。

        有關_FLAGS(%bp)中其他bit位表示的意義,在隨后的代碼分析中慢慢給你道來。

        #
        # Whatever we decided to use, now store it into the fake
        # partition entry that lives in the data space above us.
        #
        main.2:
        movb %dl,_FAKE(%bp) # Save drive number
        callw putn # To new line
        pushw %dx # Save drive number

        以上第一句把FreeBSD啟動分區的代碼保存到_FAKE(%bp)(bp-0)處,也就是說,上圖(二)的bp
        處保存的是FreeBSD啟動分區的代碼(_FAKE=0)。

        “callw putn”一句在屏幕上打印“回車”和“換行”,“pushw %dx”一句把啟動分區
        的值壓入堆棧。
        #
        # Start out with a pointer to the 4th byte of the first table entry
        # so that after 4 iterations it''s beyond the end of the sector.
        # and beyond a 256 byte boundary and has overflowed 8 bits (see next comment).
        # (remember that the table starts 2 bytes earlier than you would expect
        # as the bootable flag is after it in the block)
        #
        movw $(partbl+0x4),%bx # Partition table (+4)
        xorw %dx,%dx # Item number

        以上代碼首先把%bx指向分區表partbl的的第四個字節,這里存放的是分區類型,如82表示
        Linux Native分區83表示Linux Swap 分區,有關分區表的細節請詳見本文的尾部。然后dx清零,
        此后,dx將作為遍歷磁盤分區的列舉代號使用。啟動分區代碼dl的原來的值在上面已經壓入
        了堆棧保存。

        #
        # Loop around on the partition table, printing values until we
        # pass a 256 byte boundary. The end of loop test is at main.5.
        #
        main.3:
        movb %ch,-0x4(%bx) # Zero active flag (ch == 0)
        btw %dx,_FLAGS(%bp) # Entry enabled?
        jnc main.5 # No
        上面首先使得第一個分區的活動標志為0,標志它不為活動標志,因為ch的值為0。至
        于第二句“btw %dx,_FLAGS(%bp)”中的_FLAGS(%bp)是上面我們說到的“手動指定我們
        實際安裝FreeBSD的分區代碼”。其中的bit 0x20我們在上面已經提到過。_FLAGS(%bp)
        中的其他位表示是否我們需要檢查相應的磁盤分區。缺省情況下,我們需要檢查所有
        的磁盤分區。檢查磁盤分區看是否有可以啟動的磁盤分區,例如,可能磁盤上的某個
        分區為WindowsXP或者是Linux等。如果我們沒有改變在磁盤上該處的值,則相應的bit
        位的值為0,表示所有的分區都要檢查(因為此時_FLAGS(%bp)中的值為0),否則,
        只針對FLAGS(%bp)中相應的bit位未被設置為1的分區進行檢查。

        大家知道,FreeBSD Manager啟動時可能出現以下的提示:

        F1 FreeBSD
        F2 ??
        F3 BSD
        F4 ??
        Default F1

        其中,上面的提示中出現了令人討厭的“??”,為了避免出現“??”的提示,我們可以設置相應的
        第一分區和第四分區不檢查,就需要正確設置_FLAGS(%bp)中的bit位。設置好后,屏幕可能
        出現以下的提示:

        F1 FreeBSD
        F2 BSD
        Default F1

        #
        # If any of the entries in the table are
        # the same as the ''type'' in the slice table entry,
        # then this is an empty or non bootable partition. Skip it.
        #
        movb (%bx),%al # Load type
        movw $tables,%di # Lookup tables
        movb $TBL0SZ,%cl # Number of entries
        repne # Exclude
        scasb # partition?
        je main.5 # Yes
        我們從上面已經知道起始(%bx)指向的是MBR中分區信息1(16字節)的位置(見圖(三)),
        以上代碼在“忽略的分區類型$tables”中查找看是否本分區是不可啟動的或者不合法的分區。
        不可啟動的或者不合法的分區類型有3($TBL0SZ=3)個,它們是“0x0, 0x5, 0xf”,見下面的
        $tables處。如果是不可啟動的或者不合法的分區類型則跳轉到main.5,進行下一輪循環。

        #
        # Now scan the table of known types
        #
        movb $TBL1SZ,%cl # Number of entries
        repne # Known
        scasb # type?
        jne main.4 # No
        #
        # If it matches get the matching element in the
        # next array. if it doesn''t, we are already
        # pointing at its first element which points to a "?".
        #
        addw $TBL1SZ,%di # Adjust
        main.4:
        movb (%di),%cl # Partition
        addw %cx,%di # description
        callw putx # Display it
        上面檢查看所檢查的分區類型是否為我們知道的分區類型,知道的分區類型有11($TBL1SZ=0xb)
        個,它們是:“0x1, 0x4, 0x6, 0xb, 0xc, 0xe, 0x83,0x9f, 0xa5, 0xa6, 0xa9”,見
        下面的$tables處。如果不是以上的類型,則跳轉到main.4。那么,(%di)所指的字串是“??”,
        如果分區類型是“0x1, 0x4, 0x6, 0xb, 0xc, 0xe, 0x83,0x9f, 0xa5, 0xa6, 0xa9”
        之一,則(%di)所指的字串是“DOS”、“Linux”、“FreeBSD”或“BSD”等。
        見下面的“os_misc”、“os_dos”、“os_linux”、“os_freebsd”、“os_bsd”等
        標記。

        callw putx調用putx函數,在屏幕上打印:“Fx XXX”。其中XXX為DOS”、“Linux”、
        “FreeBSD”或“BSD”等。

        main.5:
        incw %dx # Next item
        addb $0x10,%bl # Next entry
        jnc main.3 # Till done
        遍歷磁盤分區的舉代號dx加1,重復下一輪循環查找。bl加上0x10(0x10=16)表示尋址到下
        一個分區信息(加16字節)入口。循環直到255字節邊界。

        #
        # Passed a 256 byte boundary..
        # table is finished.
        # Add one to the drive number and check it is valid,
        #
        popw %ax # Drive number
        subb $0x80-0x1,%al # Does next
        cmpb NHRDRV,%al # drive exist? (from BIOS?)
        jb main.6 # Yes
        “popw %ax”把上面壓入堆棧的bx(當前的啟動扇區)值彈出到ax中。例如,如果計算機是從軟盤
        啟動的則dl=0,若是從IDE的C、D盤啟動的則dl分別為 0x80和0x81。然而,FreeBSD的Boot Manerger不能夠
        安裝到軟盤上,所以,dl只能為0x80、0x81,0x82...等。
        在計算機的BIOS地址0:0x475處存放的是計算機的硬盤的數目,“subb $0x80-0x1,%al”一句等于“sub
        $0x79,%al”,例如,即當前驅動器如果是C盤,則al的值是ox80-0x79=1,然后再與計算機的硬盤的數目比
        較,如果當前所在硬盤不是最后一個硬盤,則直接跳轉到main.6。如果當前所在硬盤是最后一個硬盤,則繼
        續執行。

        # If not then if there is only one drive,
        # Don''t display drive as an option.
        #
        decw %ax # Already drive 0?
        jz main.7 # Yes
        如果只有一個硬盤,則直接跳轉到main.7,這樣,本計算機只有一個硬盤,所以不用顯示其他
        磁盤相關的提示。

        # If it was illegal or we cycled through them,
        # then go back to drive 0.
        #
        xorb %al,%al # Drive 0

        下面的內容表示多于一個磁盤的情況。此時“al”清0,與磁盤列舉相關。
        #
        # Whatever drive we selected, make it an ascii digit and save it back
        # to the "next drive" location in the loaded block in case we
        # want to save it for next time.
        # This also is part of the printed drive string so add 0x80 to indicate
        # end of string.
        #
        main.6:
        addb $''0''|0x80,%al # Save next
        movb %al,_NXTDRV(%bp) # drive number
        movw $drive,%di # Display
        callw putx # item
        首先,在_NXTDR(%bp)處置入“0字符高位置1”的字符,以代表第二個驅動器,
        然后在屏幕上顯示“Fx Drive”,表示更換另外的磁盤啟動。注意,在調用
        putx之前,di中保存的是下面字串“Drive ”的首地址。dl中存放的是當前
        遍歷的到的可啟動的或者合法的分區類型遞增序數,al與dl是不同的,al是ASCII碼,
        dl是“Fx”中的x值。

        #
        # Now that we''ve printed the drive (if we needed to), display a prompt.
        # Get ready for the input byt noting the time.
        #
        main.7:
        movw $prompt,%si # Display
        callw putstr # prompt
        movb _OPT(%bp),%dl # Display
        decw %si # default
        callw putkey # key
        xorb %ah,%ah # BIOS: Get
        int $0x1a # system time
        movw %dx,%di # Ticks when
        addw _TICKS(%bp),%di # timeout
        上面的代碼首先在屏幕上打印出字符串“Default: ”,缺省啟動的磁盤號放在
        “_OPT(%bp)”中,這里有個小小的技巧,在執行“decw %si”和“callw putkey”
        兩句后屏幕會顯示“Fx”,x是_OPT(%bp)的ASCII。

        然后取得當前的tickes放到%di中,等待用戶按鍵超時的時間從_TICKS(%bp)中取出,
        加到當前的tickes即是最后超時時間到的tickes。

        #
        # Busy loop, looking for keystrokes but
        # keeping one eye on the time.
        #
        main.8:
        movb $0x1,%ah # BIOS: Check
        int $0x16 # for keypress
        jnz main.11 # Have one
        xorb %ah,%ah # BIOS: Get
        int $0x1a # system time
        cmpw %di,%dx # Timeout?
        jb main.8 # No
        等待用戶按下“Fx”鍵,同時檢查當前等待是否超時,如果有用戶按鍵則跳轉到main.11,
        如果超時時間不到則繼續等待。

        #
        # If timed out or defaulting, come here.
        #
        main.9:
        movb _OPT(%bp),%al # Load default
        jmp main.12 # Join common code
        超時時間到,此時表示用戶使用缺省分區啟動,把缺省的啟動分區號置入al中,然后跳轉
        到main.12。

        #
        # User''s last try was bad, beep in displeasure.
        # Since nothing was printed, just continue on as if the user
        # hadn''t done anything. This gives the effect of the user getting a beep
        # for all bad keystrokes but no action until either the timeout
        # occurs or the user hits a good key.
        #
        main.10:
        movb $0x7,%al # Signal
        callw putchr # error
        用戶輸入錯誤,只是響鈴提示,其他什么也不發生。

        #
        # Get the keystroke.
        #
        main.11:
        xorb %ah,%ah # BIOS: Get
        int $0x16 # keypress
        movb %ah,%al # Scan code
        用戶按下了一個鍵,把鍵值掃描碼放到al中。

        #
        # If it''s CR act as if timed out.
        #
        cmpb $KEY_ENTER,%al # Enter pressed?
        je main.9 # Yes
        如果用戶按下“Enter”鍵,和超時等同處理,這樣,就啟動缺省的boot分區。

        #
        # Otherwise check if legal
        # If not ask again.
        #
        subb $KEY_F1,%al # Less F1 scan code
        cmpb $0x4,%al # F1..F5?
        jna main.12 # Yes
        subb $(KEY_1 - KEY_F1),%al # Less #1 scan code
        cmpb $0x4,%al # #1..#5?
        ja main.10 # No
        如果是除“Enter”鍵外其他的鍵,則檢查是不是F1...F5鍵,如果不是,
        表示輸入不合法,跳回到main.10處理。

        #
        # We have a selection.
        # but if it''s a bad selection go back to complain.
        # The bits in MNUOPT were set when the options were printed.
        # Anything not printed is not an option.
        #
        main.12:
        cbtw # Option
        btw %ax,_MNUOPT(%bp) # enabled?
        jnc main.10 # No
        如果是F1...F5鍵,則檢查是否在我們提示的范圍內,其中,_MNUOPT(%bp)的相應
        bit位為1,表示是一個合法的選項,如果不是,跳回到 main.10處理。

        #
        # Save the info in the original tables
        # for rewriting to the disk.
        #
        movb %al,_OPT(%bp) # Save option
        把我們按下的F1...F5鍵保存到_OPT(%bp)位置。

        movw $FAKE,%si # Partition for write
        movb (%si),%dl # Drive number
        把原來的啟動分區代碼取回到dl中。

        movw %si,%bx # Partition for read
        cmpb $0x4,%al # F5 pressed?
        pushf # Save
        je main.13 # Yes
        如果我們按下的是F5鍵則直接跳轉到main.13處理。

        shlb $0x4,%al # Point to
        addw $partbl,%ax # selected
        xchgw %bx,%ax # partition
        movb $0x80,(%bx) # Flag active
        上面,我們從按鍵Fx選擇中得到圖(三)中的我們選擇的四個分區信息中的某一分區信息,
        上面計算出的bx為我們選擇的分區信息的首地址,我們把此選擇到的分區信息的第一個
        個字節置為0x80表示它是當前的活動分區。
        #
        # If not asked to do a write-back (flags 0x40) don''t do one.
        #
        main.13:
        pushw %bx # Save
        testb $0x40,_FLAGS(%bp) # No updates?
        jnz main.14 # Yes
        movw $start,%bx # Data to write
        movb $0x3,%ah # Write sector
        callw intx13 # to disk
        檢查回寫標志_FLAGS(%bp)的bit位0x40為,如果設置的是可回寫,則把當前選擇到的boot
        分區作為下次缺省的啟動分區。

        main.14:
        popw %si # Restore
        popf # Restore

        #
        # If going to next drive, replace drive with selected one.
        # Remember to un-ascii it. Hey 0x80 is already set, cool!
        #
        jne main.15 # If not F5
        恢復上面保存的si和標志寄存器的內容。如果不是按鍵F5,則直接跳轉到main.15去執行。

        movb _NXTDRV(%bp),%dl # Next drive
        subb $''0'',%dl # number

        否則的話,我們選擇下一個驅動器作為啟動盤。
        #
        # load selected bootsector to the LOAD location in RAM.
        # If it fails to read or isn''t marked bootable, treat it
        # as a bad selection.
        # XXX what does %si carry?
        #
        main.15:
        movw $LOAD,%bx # Address for read
        movb $0x2,%ah # Read sector
        callw intx13 # from disk
        jc main.10 # If error
        把我們上面選擇到的分區讀到0x7c00處,就象我們剛剛才加電啟動一樣,只是活動分區改變
        了而已。如果發生讀錯誤則直接跳轉到main.10。使用戶重新選擇啟動分區。

        cmpw $MAGIC,0x1fe(%bx) # Bootable?
        jne main.10 # No
        判斷引導扇區的最后兩個字節是否是“0x55AA”,如果不是,則表示此扇區是不可引導的,或
        不合法的引導扇區則直接跳轉到main.10。使用戶重新選擇啟動分區。

        pushw %si # Save
        movw $crlf,%si # Leave some
        callw puts # space
        popw %si # Restore

        打印“回車”和“換行”。

        jmp *%bx # Invoke bootstrap

        跳轉到我們選擇的引導扇區去執行。整個Boot Manager代碼到此執行完畢。

        #
        # Display routines
        #

        putkey:
        movb $''F'',%al # Display
        callw putchr # ''F''
        movb $''1'',%al # Prepare
        addb %dl,%al # digit
        jmp putstr.1 # Display the rest
        “putkey”函數在屏幕上打印“F1”、“F2”或“F3”等。如果dl為0則打印“F1”,
        如果dl為1則打印“F2”,如果dl為3則打印“F3”。和調用“putstr”在屏幕上打印
        es:si指向的以最高位置1為結束字符的字符串。
        #
        # Display the option and note that it is a valid option.
        # That last point is a bit tricky..
        #
        putx: #首先,把_MNUOPT(%bp)的第dx位(bit)置1,表示此菜單選項被顯示。然后在
        屏幕上打印空格和es:di指向的以最高位置1為結束字符的字符串。
        btsw %dx,_MNUOPT(%bp) # Enable menu option
        movw $item,%si # Display
        callw putkey # key
        movw %di,%si # Display the rest

        puts: #調用“putstr”在屏幕上打印es:si指向的以最高位置1為結束字符的字符串。
        callw putstr # Display string

        putn: #“putn”打印“回車/換行”后在屏幕上打印es:si指向的以最高位置1為結束字符的字符串。
        movw $crlf,%si # To next line

        putstr: #“putstr”在屏幕上打印es:si指向的以最高位置1為結束字符的字符串。
        lodsb # Get byte
        testb $0x80,%al # End of string?
        jnz putstr.2 # Yes
        putstr.1:
        callw putchr # Display char
        jmp putstr # Continue
        putstr.2:
        andb $~0x80,%al # Clear MSB

        putchr:
        pushw %bx # Save
        movw $0x7,%bx # Page:attribute
        movb $0xe,%ah # BIOS: Display
        int $0x10 # character
        popw %bx # Restore
        retw # To caller
        “putchr”在屏幕上顯示“al”中的字符。
        # One-sector disk I/O routine

        intx13:
        movb 0x1(%si),%dh # Load head
        movw 0x2(%si),%cx # Load cylinder:sector
        movb $0x1,%al # Sector count
        pushw %si # Save
        movw %sp,%di # Save
        testb $0x80,_FLAGS(%bp) # Use packet interface?
        jz intx13.1 # No
        pushl $0x0 # Set the
        pushl 0x8(%si) # LBA address
        pushw %es # Set the transfer
        pushw %bx # buffer address
        push $0x1 # Block count
        push $0x10 # Packet size
        movw %sp,%si # Packet pointer
        decw %ax # Verify off
        orb $0x40,%ah # Use disk packet
        intx13.1:
        int $0x13 # BIOS: Disk I/O
        movw %di,%sp # Restore
        popw %si # Restore
        retw # To caller

        # Menu strings

        item:
        .ascii " "; .byte '' ''|0x80
        prompt:
        .ascii "/nDefault:"; .byte '' ''|0x80
        crlf:
        .ascii "/r"; .byte ''/n''|0x80

        # Partition type tables

        tables:
        #
        # These entries identify invalid or NON BOOT types and partitions.
        #
        .byte 0x0, 0x5, 0xf
        #
        # These values indicate bootable types we know the names of
        #
        .byte 0x1, 0x4, 0x6, 0xb, 0xc, 0xe, 0x83
        .byte 0x9f, 0xa5, 0xa6, 0xa9
        #
        # These are offsets that match the known names above and point to the strings
        # that will be printed.
        #
        .byte os_misc-. # Unknown
        .byte os_dos-. # DOS
        .byte os_dos-. # DOS
        .byte os_dos-. # DOS
        .byte os_dos-. # Windows
        .byte os_dos-. # Windows
        .byte os_dos-. # Windows
        .byte os_linux-. # Linux
        .byte os_bsd-. # BSD/OS
        .byte os_freebsd-. # FreeBSD
        .byte o
        (完)


        聲明:本網頁內容旨在傳播知識,若有侵權等問題請及時與本網聯系,我們將在第一時間刪除處理。TEL:177 7030 7066 E-MAIL:11247931@qq.com

        文檔

        FreeBSD啟動扇區代碼分析(ver5.2.1)

        FreeBSD啟動扇區代碼分析(ver5.2.1):FreeBSD啟動扇區代碼分析(ver5.2.1) 2007-04-27 來源:cnfug 作者: 關鍵詞: FreeBSD代碼BSD扇區分析 FreeBSD完整的內核代碼在FreeBSD的/sys目錄下。其中,FreeBSD 的 Boot Manager代碼是 sys/boot/i386/boot0/boot0.s,
        推薦度:
        標簽: 代碼 啟動 分析
        • 熱門焦點

        最新推薦

        猜你喜歡

        熱門推薦

        專題
        Top
        主站蜘蛛池模板: 久久最新免费视频| 国产在线精品观看免费观看| 3344免费播放观看视频| 亚洲成AV人片在线观看| 亚洲春色在线观看| 免费毛片毛片网址| yy6080亚洲一级理论| 亚洲va在线va天堂va四虎| 13小箩利洗澡无码视频网站免费| 嫩草视频在线免费观看| 亚洲精品国精品久久99热一| 青柠影视在线观看免费高清| 亚洲AV午夜成人片| 国产妇乱子伦视频免费| 亚洲人成自拍网站在线观看| 国产成人青青热久免费精品| 永久免费精品影视网站| 69式国产真人免费视频| 亚洲国产AV无码一区二区三区| 免费A级毛片无码专区| 国产成人亚洲综合| 日韩免费电影网址| 亚洲人成无码www久久久| 免费视频一区二区| 精品亚洲一区二区三区在线观看| 抽搐一进一出gif免费视频| 亚洲国产人成网站在线电影动漫 | 亚洲AV综合色一区二区三区| 热re99久久6国产精品免费| 亚洲综合色一区二区三区| 免费A级毛片av无码| 亚洲欧洲专线一区| 亚洲国产另类久久久精品黑人| 四虎永久在线观看免费网站网址 | 国产免费爽爽视频免费可以看| 久久www免费人成精品香蕉| 亚洲字幕在线观看| 中文字幕亚洲不卡在线亚瑟| 国产在线a免费观看| 成人一区二区免费视频| 亚洲一线产区二线产区精华|