• <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>
            隨筆-80  評論-24  文章-0  trackbacks-0
            本篇主要將boot程序所做的工作做一筆記。
            先看代碼吧:

              1 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
              2 ; 該文件主要用于加載loader和kernel入內存,其中默認loader和kernel是被壓縮成System.Image
              3 ; 文件存放到軟盤的第二個扇區起始的地方,loader最大大小不應超過128KB,loader+kernel不應
              4 ; 超過512KB - 32KB = 480KB大小,否則系統將崩潰。
              5 
              6 ; Author :  
              7 ; v 0.01 2011/11/22
              8 ;
              9 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
             10 org 0x7c00
             11 jmp start
             12 
             13 ; loader和kernel映像一起被加載到
             14 ; 內存段基址:0x8000 (* 0x10)
             15 ; 即在1MB尋址范圍的正中間
             16 ; 將來還會從0xf0000地址起始處放置一些系統參數
             17 ; 因此loader+kernel大小不應超過512KB - 32KB = 480KB,如果
             18 ; 超過這個數字那么地址將回滾,系統崩潰
             19 LOADER_ADDR equ 0x8000
             20 
             21 start:
             22     mov ax, cs
             23     mov ds, ax
             24     mov es, ax
             25     mov ss, ax
             26     mov sp, 0x7b00 ; 棧頂為0x7b00,向低地址延伸;其實boot中我們沒有用到棧,因此不需設置堆棧
             27     
             28     ; 清屏
             29     mov ax, 0x0600
             30     mov bx, 0x0700
             31     mov cx, 0
             32     mov dx, 0x184f
             33     int 0x10
             34 
             35     ; 設置光標位置
             36     mov ah, 0x02
             37     mov bh, 0x00
             38     mov dx, 0x0
             39     int 0x10
             40 
             41 get_disk_param:
             42     mov dl, 0x00 ; 讀軟盤
             43     mov ax, 0x0800 ; 獲取磁盤參數
             44     int 0x13
             45     jnc goon_get_disk_param ; 如果讀磁盤驅動器參數成功則保存相關參數
             46     mov dx, 0x0000 ; 出錯則將磁盤復位然后無限循環讀
             47     mov ax, 0x0000
             48     int 0x13
             49     jmp get_disk_param ; 出錯則將磁盤復位然后無限循環讀
             50 
             51 goon_get_disk_param:
             52     mov bl, cl
             53     and bl, 0x3f
             54     mov byte [SECTOR_PER_TRACK], bl ; SECTOR_PER_TRACK保存每磁道最大扇區數
             55     shr cx, 6
             56     mov word [TRACK_NUM], cx ; TRACK_NUM保存最大磁道號
             57 
             58     ; 獲取當前光標位置
             59     mov ah, 0x03
             60     xor bh, bh
             61     int 0x10
             62 
             63     ; 打印一些信息
             64     mov ax, cs
             65     mov es, ax
             66     mov cx, MSG1_LEN
             67     mov bx, 0x0007
             68     mov bp, MSG1 ; 顯示字符串"Loading System "
             69     mov ax, 0x1301
             70     int 0x10
             71 
             72 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
             73 ; 加載loader和kernel文件,存放位置在0x80000起始的地方
             74 ; loader+kernel大小不應超過480KB,否則由于在實模式下僅有
             75 ; 1MB的尋址能力,loader+kernel的存放空間將超過0x80000~0xf0000的大小
             76 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
             77 
             78 load_loader_and_kernel:
             79     mov ax, 0x00
             80     mov byte al, [LOADER_LEN]
             81     add word ax, [KERNEL_LEN]
             82     mov word [CUR_UNREAD_SECTOR], ax ; 初始化當前未加載的扇區數
             83     mov ax, LOADER_ADDR
             84     mov es, ax
             85     mov bx, 0x00 ; es:bx指向loader+kernel映像加載的位置:0x8000 * 0x10 + 0x0
             86 
             87 read_one_track:
             88     mov word ax, [CUR_TRACK]
             89     mov ch, al ; 當前讀到的磁道號的低8位
             90     shl ah, 0x06
             91     mov cl, ah
             92     mov byte al, [CUR_READ]
             93     inc al
             94     or cl, al ; cl寄存器高兩位為當前讀到的磁道號的高兩位,低六位為開始扇區號
             95     mov byte dh, [CUR_HEAD] ; 當前的磁頭號
             96     mov dl, 0x00 ; 驅動器號為0,代表是軟盤
             97     mov ah, 0x02 ; 讀扇區
             98     mov byte al, [SECTOR_PER_TRACK]
             99     sub byte al, [CUR_READ] ; 要讀取的扇區數量
            100     int 0x13
            101     mov byte cl, [SECTOR_PER_TRACK]
            102     sub byte cl, [CUR_READ]
            103     cmp al, cl
            104     jne die ; 如果實際讀出的扇區數比所請求的扇區數少,則報錯
            105     xor ah, ah
            106     sub word [CUR_UNREAD_SECTOR], ax ; 修改當前剩余的未讀扇區數
            107     jc finish_loading
            108     cmp word [CUR_UNREAD_SECTOR], 0x00
            109     je finish_loading ; 如果已經讀完loader和kernel,則跳出
            110     shl ax, 0x09 ; al * 512代表本次讀出的字節數
            111     add bx, ax
            112     jno no_overflow
            113     mov cx, es
            114     add cx, 0x1000
            115     cmp cx, 0xf000
            116     ja die ; es已經超過了1MB的界限,說明loader+kernel過大
            117     mov es, cx ; 修改es:bx緩沖區地址
            118 no_overflow:
            119     mov byte [CUR_READ], 0x0
            120     cmp byte [CUR_HEAD], 0x0
            121     je read_head_1
            122     add byte [CUR_TRACK], 0x01
            123     mov word ax, [TRACK_NUM]
            124     cmp word [CUR_TRACK], ax
            125     ja die
            126 read_head_1:
            127     add byte [CUR_HEAD], 0x01
            128     and byte [CUR_HEAD], 0x01 ; 磁頭號由0轉為1,或者由1轉為0
            129     jmp read_one_track
            130 
            131 die:
            132     ; 獲取當前光標位置
            133     mov ah, 0x03
            134     xor bh, bh
            135     int 0x10
            136 
            137     ; 打印一些信息
            138     mov ax, cs
            139     mov es, ax
            140     mov cx, MSG2_LEN
            141     mov bx, 0x0007
            142     mov bp, MSG2 ; 顯示字符串"The loader or kernel is too long "
            143     mov ax, 0x1301
            144     int 0x10
            145 
            146     xor ax, ax
            147     int 0x16
            148     int 0x19
            149     jmp $
            150 
            151 finish_loading:
            152     ; 關閉軟驅馬達
            153     mov dx, 0x03f2
            154     mov al, 0
            155     out dx, al
            156     nop
            157     
            158     ; 獲取當前光標位置
            159     mov ah, 0x03
            160     xor bh, bh
            161     int 0x10
            162 
            163     ; 打印一些信息
            164     mov ax, cs
            165     mov es, ax
            166     mov cx, MSG3_LEN
            167     mov bx, 0x0007
            168     mov bp, MSG3 ; 顯示字符串"Success to load the loader and kernel\n\nEntering loader "
            169     mov ax, 0x1301
            170     int 0x10
            171 
            172     jmp LOADER_ADDR:0 ; 跳轉到loader去執行
            173 
            174 ; 要顯示的字符串
            175 MSG1:                db 1310"Loading loader and kernel "1310
            176 MSG1_LEN            equ $ - MSG1
            177 MSG2:                db 1310"The loader or kernel is too long "1310
            178 MSG2_LEN            equ $ - MSG2
            179 MSG3:                db 1310"Entering loader "1310
            180 MSG3_LEN            equ $ - MSG3
            181 
            182 CUR_READ:            db 1 ; 當前磁道已經讀出的扇區數
            183 CUR_HEAD:            db 0 ; 當前的磁頭號
            184 CUR_TRACK:            dw 0 ; 當前讀到的磁道號
            185 CUR_UNREAD_SECTOR    dw 0 ; 當前剩余的未讀扇區數
            186 
            187 TRACK_NUM:            dw 0 ; 最大磁道號
            188 SECTOR_PER_TRACK:    db 0 ; 每磁道扇區數
            189 
            190 times 507 - ($ - $$) db 0 ; 填充剩余容量為0
            191 
            192 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
            193 ; 將loader文件的大小和kernel文件的大小都
            194 ; 放到boot文件oxaa55前的末尾
            195 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
            196 
            197 ; loader文件所占用的扇區數,loader不會大過
            198 2^8 * 512 = 128KB大小,這在短期內應該足夠了
            199 LOADER_LEN            db 0
            200 ; kernel文件所占用的扇區數,kernel不會大過
            201 2^16 * 512 = 32MB大小,這在用1.44MB大小的軟盤里足夠了
            202 KERNEL_LEN            dw 0
            203 
            204 dw 0xaa55

                  該文件是由BIOS自動從軟盤的第一個扇區加載進內存的0x0:0x7c00處的。因此必須將boot放到軟盤的第一個扇區,且要求該文件編譯出來必須是512字節,正好占用一個扇區大小。
                  boot中指定了loader+kernel被加載的位置:0x8000:0x0,也就是物理地址為0x80000的位置。另外將來loader還要在地址0xf000:0x0處放置一些系統參數,因此loader+kernel文件應該位于0x8000:0x0~0xf000:0x0之間,也就是不大于480KB的大小,超過這個大小系統崩潰,無法啟動。
                  該文件的核心操作就是從軟盤的第二個扇區開始將loader+kernel加載進內存,不過前提是應該已經使用proc_kernel和buildImage程序將boot+loader和kernel壓縮成一個System.Image文件,也就是說loader和kernel被一起放到軟盤的第二個扇區開始的位置,boot將連續讀磁道將loader+kernel加載到從0x8000:0x0起始的內存位置。
                  還有一個地方需要注意,boot文件可啟動的標志除了大小需要是512B外,最后兩個字節也必須是0xaa55。而且我們在緊挨著0xaa55的地方開辟了3個字節的空間用來記錄loader的大小和kernel的大小,都是以扇區數計量。其中loader大小占1個字節,因此說loader不得大于2^8 * 512B = 128KB,緊挨著是kernel大小,占用2個字節。這兩個值是為了加載loader+kernel做準備的,而且這兩個值不是boot或者loader寫入的,而是buildImage這個工具直接在獲取了loader文件和kernel文件的大小后直接寫入的。
                  核心的部分是將loader+kernel加載進內存,這個工作具體思想如下:boot先從自己的最后幾個字節位置獲取loader和kernel占用的扇區數量,然后再利用BIOS中斷獲取軟盤參數,最后加載對應數量的扇區,不過為了加快加載速度,這里學習了linux的做法,每次只要可以,就加載整個磁道。
            posted on 2011-11-22 19:31 myjfm 閱讀(736) 評論(0)  編輯 收藏 引用 所屬分類: 操作系統
            亚洲精品乱码久久久久久久久久久久 | 久久九九全国免费| 久久亚洲欧美日本精品| 久久天天躁狠狠躁夜夜av浪潮| 性做久久久久久免费观看| 97精品伊人久久久大香线蕉| www久久久天天com| 久久有码中文字幕| 99久久99久久精品免费看蜜桃| 久久婷婷久久一区二区三区| 色99久久久久高潮综合影院| 亚洲精品美女久久久久99| 国产福利电影一区二区三区久久老子无码午夜伦不 | 久久青青草原精品影院| 久久精品一区二区三区AV| 久久免费国产精品一区二区| 久久婷婷色综合一区二区| 国产日韩久久免费影院| 久久不见久久见免费视频7| 亚洲欧美一区二区三区久久| 韩国三级中文字幕hd久久精品| 精品多毛少妇人妻AV免费久久| 九九久久精品国产| 亚洲国产成人久久综合碰碰动漫3d | 久久久久久精品久久久久| 久久se精品一区二区影院| 久久精品成人免费看| 国产美女久久精品香蕉69| 色偷偷88888欧美精品久久久| 亚洲国产成人精品91久久久| 精品国产婷婷久久久| 91超碰碰碰碰久久久久久综合| 狠狠色丁香婷婷综合久久来| 久久国产免费观看精品3| 人妻精品久久无码专区精东影业| 久久人妻少妇嫩草AV蜜桃| 亚洲精品午夜国产va久久| 综合久久一区二区三区| 四虎影视久久久免费| 97精品伊人久久大香线蕉| 欧美日韩精品久久久免费观看|