日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

os引导程序boot从扇区拷贝os加载程序loader文件到内存(boot copy kernel to mem in the same method)

發布時間:2023/12/3 编程问答 33 豆豆
生活随笔 收集整理的這篇文章主要介紹了 os引导程序boot从扇区拷贝os加载程序loader文件到内存(boot copy kernel to mem in the same method) 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

【0】README

  • 0.1) 本代碼旨在演示 在boot 代碼中,如何 通過 loader文件所在根目錄條目 找出該文件的 在 軟盤所有全局扇區號(簇號),并執行內存中的 loader 代碼;
  • 0.2) 此代碼非常重要,關系到bootloader的加載和運行(打印字母 L)(干貨)
  • 0.3) source code from orange’s implemention of a os and for complete code , please visit https://github.com/pacosonTang/Orange-s-OS/blob/master/boot.asm
  • 0.4) 就本os而言,即orange’s os ,”從扇區copy os加載程序 loader 到內存0x09000:0100“這個任務 是在 引導扇區中的引導程序boot 中完成的,而且在 boot 完成本任務之前,引導程序boot還完成 ”在根目錄區尋找 加載程序loader 對應的根目錄條目“的任務,注意這與linux 是不同的;
  • 0.5)即是說,orange’s os 中的啟動程序boot 執行了兩個任務: os引導程序boot 在根目錄區尋找os加載程序文件loader 對應的根目錄條目 + os引導程序boot 從扇區拷貝os加載程序loader文件到內存(boot copy kernel to mem in the same method)
  • Attention)
    • A1) loader文件所在根目錄條目 是由 p109.asm 得到的, 在查找完文件名稱且匹配后,di 指向文件名的后一個字節,但di還存在于當前匹配成功的 根目錄條目中;
    • A2) 要死死記住 根目錄條目的數據結構存儲的是:(文件名 + 文件屬性 + 最后一次寫入時間 + 最后一次寫入日期 + 此條目對應的開始簇號 + 文件大小)

【1】SOURCE CODE

LABEL_FILENAME_FOUND: ; 找到 LOADER.BIN 后便來到這里繼續

mov ax, RootDirSectors ; RootDirSectors=14and di, 0FFE0h ; di -> 當前條目的開始,每個條目=32字節,0ffe0==1111 1111 1110 0000add di, 01Ah ; di -> 首 Sector ,條目數據結構中,開始簇號的offset=26字節;mov cx, word [es:di]push cx ; 保存此 Sector 在 FAT 中的序號 ,cx等于loader文件的開始簇號(在數據區)add cx, axadd cx, DeltaSectorNo ; cl <- LOADER.BIN的起始扇區號(0-based); 這里加完之后,cx=該loader 文件相對于0號扇區的扇區號(也即相對于整個軟盤而言)mov ax, BaseOfLoadermov es, ax ; es <- BaseOfLoadermov bx, OffsetOfLoader ; bx <- OffsetOfLoadermov ax, cx ; ax <- Sector 號LABEL_GOON_LOADING_FILE:push ax ; `.push bx ; | es:bp 是串地址,CX=串長度,ah= ,al= '.' 打印什么東西, bh=頁號,bl=黑底紅字mov ah, 0Eh ; | 每讀一個扇區就在 "Booting " 后面mov al, '.' ; | 打一個點, 形成這樣的效果:mov bl, 0Fh ; | Booting ...... int 10h ; | | 一句話說完,以上對register的初始化,都是為觸發10h 號中斷做準備工作的, pop bx ; |pop ax ; /mov cl, 1

call ReadSector ; 這個ReadSector非常重要,目的就是讀取cl個扇區到 es:bx中,而bx 每次都自增512字節;(這是讀軟盤某扇區到內存中的關鍵步驟)

pop ax ; cur_line=154, 取出此 Sector 在 FAT 中的序號(ax <- cx),line133 push cx 已壓入棧, cx=Loader文件在數據區的開始簇號;

call GetFATEntry ; 找到序號為 ax 的 Sector 在 FAT 中的條目, 結果放在 ax 中

cmp ax, 0FFFhjz LABEL_FILE_LOADED ; 相等,則說明 該簇號是最后一個簇號push ax ; 保存 Sector 在 FAT 中的序號mov dx, RootDirSectorsadd ax, dxadd ax, DeltaSectorNo ; DeltaSectorNo equ 17add bx, [BPB_BytsPerSec] ; bx加上一個扇區的字節數,即跳轉到下一個扇區;因為讀取地址是 es:bxjmp LABEL_GOON_LOADING_FILE LABEL_FILE_LOADED:mov dh, 1 ; "Ready." 加載完畢 call DispStr ; 顯示字符串;

jmp BaseOfLoader:OffsetOfLoader; 這一句正式跳轉到已加載到內, 開始執行loader 代碼;
; 存中的 LOADER.BIN 的開始處,
; 開始執行 LOADER.BIN 的代碼。
; Boot Sector 的使命到此結束**



GetFATEntry Source Code
;—————————————————————————-
; 函數名: GetFATEntry
;—————————————————————————-
; 作用:
; 找到序號為 ax 的 Sector 在 FAT 中的條目, 結果放在 ax 中
; 需要注意的是, 中間需要讀 FAT 的扇區到 es:bx 處, 所以函數一開始保存了 es 和 bx

GetFATEntry:push espush bxpush ax ; cur_line=269, ax 存儲該文件在FAT中的開始簇號(又FAT的第0和第1項不使用,所以FAT條目的開始簇號起步價為2,且數據區的第一個簇的簇號是2)mov ax, BaseOfLoader; `.sub ax, 0100h ; | 在 BaseOfLoader 后面留出 4K 空間用于存放 FAT; | 因為每個扇區=512B,FAT=8個扇區=4k;mov es, ax ; /pop ax ; ax恢復line269 push ax 的值,(current line=273)mov byte [bOdd], 0 ; bOdd db 0 ; 奇數(value=1)還是偶數(value=0)mov bx, 3mul bx ; dx:ax = ax * 3mov bx, 2div bx ; dx:ax / 2 ==> ax <- 商, dx <- 余數cmp dx, 0jz LABEL_EVENmov byte [bOdd], 1 ; 奇數(value=1)偶數(value=0) LABEL_EVEN:;偶數; 現在 ax 是 FATEntry 在 FAT 中的偏移量,下面來; 計算 FATEntry 在哪個扇區中(FAT占用不止一個扇區); 因為 FATEntry 占用12位,解釋了line276 line278 的 乘3 和 除2 操作;cur_line=285xor dx, dx mov bx, [BPB_BytsPerSec] ; div bx ; dx:ax / BPB_BytsPerSec; ax <- 商 (FATEntry 所在的扇區相對于 FAT 的扇區號 , FAT共有9個扇區 ); dx <- 余數 (FATEntry 在扇區內的偏移)push dx ; FATEntry 在扇區內的偏移mov bx, 0 ; bx <- 0 于是, es:bx = (BaseOfLoader - 100):00add ax, SectorNoOfFAT1 ; 此句之后的 ax 就是 FATEntry 所在的扇區號(全局); SectorNoOfFAT1 equ 1 ; FAT1 的第一個扇區號 = BPB_RsvdSecCntmov cl, 2 call ReadSector ; 讀取 FATEntry 所在的扇區, 一次讀兩個, 避免在邊界; 發生錯誤, 因為一個 FATEntry 可能跨越兩個扇區; ReadSector 從第 ax 個 Sector 開始, 將 cl 個 Sector 讀入 es:bx 中, es:bx = (BaseOfLoader - 100):00pop dx ; 將 FATEntry 在扇區內的偏移(line292) 出棧,cur_line=300 add bx, dx ; 因為bx=0,偏移量 -> bxmov ax, [es:bx] ; es:bx = (BaseOfLoader - 100):00+dx( FATEntry 在扇區內的偏移)cmp byte [bOdd], 1 ; 奇數(value=1)偶數(value=0)jnz LABEL_EVEN_2 ; 偶數shr ax, 4 ; 注意,FATEntry=12bit,占用1.5Byte, 這里很好理解 LABEL_EVEN_2:and ax, 0FFFhLABEL_GET_FAT_ENRY_OK:pop bxpop esret

【2】Conclusion(本代碼繼p109 后,接著擺)

  • 2.0)寫在前面:假設這里有個內核,loader加載該內核到內存,而且內核開始執行的時候肯定已經在保護模式下了。所以loader需要做的事情有兩件:

    • 2.0.a)加載內核入內存;
    • 2.0.b)跳入保護模式;
  • 2.1)下面演示 以上代碼的執行步驟:
    step1)計算該文件起始簇號對應的全局扇區號:
    從根目錄條目中抽取出 該文件的起始簇號(FAT專門用于存儲文件在數據區的簇號,簇號等于一個或多個扇區),該簇號是相對于數據區的簇號,(因為本FAT12文件系統中,一個簇號==一個扇區,所以簇號就等于扇區的說法,但是不管怎么,知道簇號,我就可以知道扇區號,這些設置是在 FAT12 的引導扇區中定義好了的)所以,我們要算出該簇號對應的 全局簇號(扇區號),因為第一個和第2個FAT不使用,所以全局簇號最后還要減2。

    step2)從軟盤上 讀取該扇區到內存地址 es:bx=9000:1000處,以便進行數據分析;(當然,每次循環后,偏移地址要增加512字節,也即連續讀取該文件的扇區內容到 起始位置0x9000:1000處);
    step3)找出 step1 中算出扇區號在 FAT中的條目:

    • step3.1)首先,算出該扇區在FAT的 對應條目 FATentry 在 FAT中的偏移量(一個條目= 12bits = 1.5Bytes);(注意,這里的條目是FAT條目,不是根目錄區條目,不要搞混了)
    • step3.2)然后算出該偏移量在哪個扇區,以及在該扇區的偏移量;
    • step3.3)讀取對應FAT條目所在扇區和相鄰扇區(也即讀2個扇區,因為條目占1.5個字節,可能跨扇區存儲)到 es:bx= (9000h-100h): 00 處;
    • step3.4)在es:bx處 對兩個扇區求出 該扇區對應的 FAT條目值(即12位值);

    step4)比較FAT條目值 是否 == fffh:

    • step4.1)如果相等,則證明該條目是最后一個條目,即over了;
    • step4.2)如果不等,將該FAT條目壓棧(因為它是一個鏈條,不斷壓棧,直到 fffh 出現),然后更新該文件的下一個全局扇區號(ax+RootDirSectors+DeltaSectorNo),然后再代入step2)進行循環;最后就可以找出該文件所對應的所有FAT條目,即該文件所占用的所有簇,也即所有扇區了,即是是壓棧形成的那個鏈條值;

    step5)找到該文件占用的所有扇區后,跳轉到es:bx的地址,即 jmp BaseOfLoader:OffsetOfLoader ,該 loader文件 僅僅是 打印了 字符 ‘L’ ,(該文件內容,就是剛才step2步驟中把軟盤扇區中的內容讀入內存 es:bx 的內容),(因為正如step2所說的那樣,在上述循環過程中,程序已經把該文件的所有扇區內容讀取到起始地址為 BaseOfLoader:OffsetOfLoader=0x90000:1000 的內容空間中去了)


jmp BaseOfLoader:OffsetOfLoader ; 這一句正式跳轉到已加載到內 ; 存中的 LOADER.BIN 的開始處, ; 開始執行 LOADER.BIN 的代碼。 ; Boot Sector 的使命到此結束

Attntion)其實你發現: 這個 BaseOfLoader : OffsetOfLoader 處的內容,是 LABEL_GOON_LOADING_FILE 標識符后的 ReadSector函數每次讀一個扇區讀進去的,而每次的起始扇區號由 GetFATEntry 函數 提供的,而 GetFATEntry 函數的作用:找到序號為 ax 的 Sector 在 FAT 中的條目, 結果放在 ax 中。就這樣 ReadSector函數 + GetFATEntry 函數配合起來就把loader文件從 軟盤的扇區讀到了 起始內存地址 es:bx=9000h:0100 (每次循環后,偏移地址自增512字節);

Complementary)FAT的作用:當文件size 大于 512B,則FAT是找出該文件所占用的全部簇(簇:一個或多個扇區,引導扇區的BPB_SecPerClus記錄該數字)

創作挑戰賽新人創作獎勵來咯,堅持創作打卡瓜分現金大獎

總結

以上是生活随笔為你收集整理的os引导程序boot从扇区拷贝os加载程序loader文件到内存(boot copy kernel to mem in the same method)的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。