Day2 彙編語言學習與Makefile入門html
本文僅帶着思路,研究源碼裏關於文件系統的參數linux
關於day2主程序部分及更多內容,請看《30天自制操做系統》筆記架構
導航ide
day1代碼(只簡單地使用DB DW DD RESB指令) 工具
1 ; hello-os 2 ; TAB=4 3 4 ; 標準FAT12格式軟盤專用的代碼 Stand FAT12 format floppy code 5 6 DB 0xeb, 0x4e, 0x90 7 DB "HELLOIPL" ; 啓動扇區名稱(8字節) 8 DW 512 ; 每一個扇區(sector)大小(必須512字節) 9 DB 1 ; 簇(cluster)大小(必須爲1個扇區) 10 DW 1 ; FAT起始位置(通常爲第一個扇區) 11 DB 2 ; FAT個數(必須爲2) 12 DW 224 ; 根目錄大小(通常爲224項) 13 DW 2880 ; 該磁盤大小(必須爲2880扇區1440*1024/512) 14 DB 0xf0 ; 磁盤類型(必須爲0xf0) 15 DW 9 ; FAT的長度(必??9扇區) 16 DW 18 ; 一個磁道(track)有幾個扇區(必須爲18) 17 DW 2 ; 磁頭數(必??2) 18 DD 0 ; 不使用分區,必須是0 19 DD 2880 ; 重寫一次磁盤大小 20 DB 0,0,0x29 ; 意義不明(固定) 21 DD 0xffffffff ; (多是)卷標號碼 22 DB "HELLO-OS " ; 磁盤的名稱(必須爲11字?,不足填空格) 23 DB "FAT12 " ; 磁盤格式名稱(必??8字?,不足填空格) 24 RESB 18 ; 先空出18字節 25 26 ; 程序主體 27 28 DB 0xb8, 0x00, 0x00, 0x8e, 0xd0, 0xbc, 0x00, 0x7c 29 DB 0x8e, 0xd8, 0x8e, 0xc0, 0xbe, 0x74, 0x7c, 0x8a 30 DB 0x04, 0x83, 0xc6, 0x01, 0x3c, 0x00, 0x74, 0x09 31 DB 0xb4, 0x0e, 0xbb, 0x0f, 0x00, 0xcd, 0x10, 0xeb 32 DB 0xee, 0xf4, 0xeb, 0xfd 33 34 ; 信息顯示部分 35 36 DB 0x0a, 0x0a ; 換行兩次 37 DB "hello, world" 38 DB 0x0a ; 換行 39 DB 0 40 41 RESB 0x1fe-$ ; 填寫0x00直到0x001fe 42 43 DB 0x55, 0xaa 44 45 ; 啓動扇區之外部分輸出 46 47 DB 0xf0, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00 48 RESB 4600 49 DB 0xf0, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00 50 RESB 1469432
如下是day2代碼(使用了真正的彙編指令,編譯出來的文件和day1的徹底一致,我用二進制文件對比工具對比過了)oop
1 ; hello-os 2 ; TAB=4 3 4 ORG 0x7c00 ; 指明程序裝載地址 5 6 ; 標準FAT12格式軟盤專用的代碼 Stand FAT12 format floppy code 7 8 JMP entry 9 DB 0x90 10 DB "HELLOIPL" ; 啓動扇區名稱(8字節) 11 DW 512 ; 每一個扇區(sector)大小(必須512字節) 12 DB 1 ; 簇(cluster)大小(必須爲1個扇區) 13 DW 1 ; FAT起始位置(通常爲第一個扇區) 14 DB 2 ; FAT個數(必須爲2) 15 DW 224 ; 根目錄大小(通常爲224項) 16 DW 2880 ; 該磁盤大小(必須爲2880扇區1440*1024/512) 17 DB 0xf0 ; 磁盤類型(必須爲0xf0) 18 DW 9 ; FAT的長度(必??9扇區) 19 DW 18 ; 一個磁道(track)有幾個扇區(必須爲18) 20 DW 2 ; 磁頭數(必??2) 21 DD 0 ; 不使用分區,必須是0 22 DD 2880 ; 重寫一次磁盤大小 23 DB 0,0,0x29 ; 意義不明(固定) 24 DD 0xffffffff ; (多是)卷標號碼 25 DB "HELLO-OS " ; 磁盤的名稱(必須爲11字?,不足填空格) 26 DB "FAT12 " ; 磁盤格式名稱(必??8字?,不足填空格) 27 RESB 18 ; 先空出18字節 28 29 ; 程序主體 30 31 entry: 32 MOV AX,0 ; 初始化寄存器 33 MOV SS,AX 34 MOV SP,0x7c00 35 MOV DS,AX 36 MOV ES,AX 37 38 MOV SI,msg 39 putloop: 40 MOV AL,[SI] 41 ADD SI,1 ; 給SI加1 42 CMP AL,0 43 JE fin 44 MOV AH,0x0e ; 顯示一個文字 45 MOV BX,15 ; 指定字符顏色 46 INT 0x10 ; 調用顯卡BIOS 47 JMP putloop 48 fin: 49 HLT ; 讓CPU中止,等待指令 50 JMP fin ; 無限循環 51 52 msg: 53 DB 0x0a, 0x0a ; 換行兩次 54 DB "hello, world" 55 DB 0x0a ; 換行 56 DB 0 57 58 RESB 0x7dfe-$ ; 填寫0x00直到0x001fe 59 60 DB 0x55, 0xaa 61 62 ; 啓動扇區之外部分輸出 63 64 DB 0xf0, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00 65 RESB 4600 66 DB 0xf0, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00 67 RESB 1469432
注意:RESB 0x7dfe-$ ; 填寫0x00直到0x001fe這一行沒有錯,編譯出來的二進制的確能和day一致post
因此咱們要研究出:day2與day1彙編代碼對應關係,如MOV AX,0是怎麼表達成二進制的學習
首先是這個ORG 0x7c00,對比後面的測試
0x7dfe-$居然和0x1fe-$同樣,並且7dfe與1fe恰好差了7c00,結合註釋,推斷這個ORG規定了在內存中被開始加載的地址url
ORG 0x7c00 就是讓主板從內存0x7c00處開始加載咱們寫的helloos.img。
能夠猜得出,day1版本是用了相對地址,在源碼中 把helloos.img的開頭用0x0000表示,因此實際在哪一個內存地址被加載 應該是由彙編編譯器或主板BIOS決定的,
而day2用了絕對地址,指定helloos.img要在內存0x7c00處加載。
↑↑↑上半部分源碼, 下半部分源碼↓↓↓
這個0xeb 0x4e 0x90是什麼意思咱們還不知道,他就用匯編改了,因此有重點,搜索一下發現了一篇:
file allocation table - 16bit: http://www.beginningtoseethelight.org/fat16/index.htm 以及
FAT32中文版分析+補充(1) 和 FAT32中文版分析+補充(2)
這裏引用這篇文章裏的 BS_jmpBoot (跳轉指令),如圖
因此helloos可能不能在非Intel x86架構的主板上工做?
好了,看完資料,咱們發現書中的啓動區源碼是爲FAT12格式軟盤服務的,因此若是之後咱們要作fat32(甚至須要主板驅動支持的exfat、NTFS),就須要本身去找對應分區格式的啓動區參數。
從day1的啓動區開始吧,再貼一次圖片,方便對比
Day1的helloOS.nas前半部分
後半部分(程序主體、信息顯示部分、啓動扇區之外部分輸出)
開頭的 eb 4e 90,結合fat啓動區分區分析圖,能夠知道在Intel x86裏這就是JMP 0x4e,而3e到4f是都是零,4e恰好位於程序主體前面的兩個0x00。那這裏4e能不能寫成3e到50裏任意hex呢?用改img文件的十六進制就能夠測試。
day2裏面把程序主體寫做entry,因此源碼裏的JMP entry就和0xeb 0x4e 0x90做用相同了:
Ps.做者在書裏解釋說是JMP 0x7c50
而JMP entry下面的東西是fat12的分區扇區參數。(分區扇區參數的都是計算機行業規定,通常不能本身隨便改的),如圖(引用自FAT32中文版分析+補充(1) )
恰好就對應着咱們的
0x00到0x10(0x0F是15,0x10就是16,偏移量16就是0x10)
|
零扇區BPB[BIOS Parameter Block]從下面內容能夠看出它的做用,即儲存了文件系統的參數信息
偏移量 | 零扇區BPB | helloos裏的值 | 大小 | helloos值的說明 |
0xB | BPB_BytesPersec(每扇字節數) | 512 | 2bits | 可填512,1024,2048,4096, 因爲書裏用的軟盤,因此是512 |
0xC | BPB_SecPerClus(每簇扇區數) | 1 | 1bit | 2^n, (n>=0) |
0xD | BPB_RsvdSecCnt(保留扇區數) | 1 | 2bits | FAT12/16硬性規定爲1,FAT32爲32 |
0x10 | BPB_NumFATs(FAT副本數) | 2 | 1bit | FAT 建議寫2 |
從0x11到20
偏移量 | helloos裏的值 | 大小 | helloos值的說明 | |
0x11 | BPB_RootEntCnt(根目錄項數) | 224 | 2bits | FAT12/16爲32的偶數倍,FAT32必須爲0 |
0x13 | BPB_TotSec16(總扇區數) | 2880 | 2bits | FAT12/16填總扇區數 |
0x15 | BPB_Media(媒體描述符) | 0xf0 | 1bit | 可移動存儲介質常用0xF0 |
0x16 | BPB_FATSz16(每FAT扇區數) | 9 | 2bits | FAT12/16一個FAT表所佔的扇區數 |
0x18 | BPB_SecPerTrk(每磁道扇區數) | 18 | 2bits | 每磁道扇區數,這個數用於BIOS中斷0x13 |
0x1A | BPB_NumHeads(磁頭數) | 2 | 2bits | 磁頭數,也用於0x13中斷 |
0x1C | BPB_HiddSec(隱藏扇區數) | 0 | 4bits | FAT分區以前所隱藏的扇區數, 調用0x13中斷可獲得, 對於沒有分區的儲存介質,此域必須爲0, 具體使用什麼由操做系統決定 |
0x20 | BPB_TotSec32(總扇區數) | 2880 | 4bits | FAT12/16中,如果總扇區>=10000(64KB) ,那麼此域就是總扇區 |
註解:這裏的磁頭數等東西指的是邏輯上的,若是沒有實體,那麼指的就是邏輯磁頭數。其餘參數同理
對比一下源碼,這下子就明明白白了
1 ; hello-os 2 ; TAB=4 3 4 ORG 0x7c00 ; 指明程序裝載地址 5 6 ; 標準FAT12格式軟盤專用的代碼 Stand FAT12 format floppy code 7 8 JMP entry 9 DB 0x90 10 DB "HELLOIPL" ; 啓動扇區名稱(8字節) 11 DW 512 ; 每一個扇區(sector)大小(必須512字節) 12 DB 1 ; 簇(cluster)大小(必須爲1個扇區) 13 DW 1 ; FAT起始位置(通常爲第一個扇區) 14 DB 2 ; FAT個數(必須爲2) 15 DW 224 ; 根目錄大小(通常爲224項) 16 DW 2880 ; 該磁盤大小(必須爲2880扇區1440*1024/512) 17 DB 0xf0 ; 磁盤類型(必須爲0xf0) 18 DW 9 ; FAT的長度(必??9扇區) 19 DW 18 ; 一個磁道(track)有幾個扇區(必須爲18) 20 DW 2 ; 磁頭數(必??2) 21 DD 0 ; 不使用分區,必須是0 22 DD 2880 ; 重寫一次磁盤大小 23 24 ; 以上部分就是表格裏描述的 25 ; 下面這部分還沒介紹,不急 26 DB 0,0,0x29 ; 意義不明(固定) 27 DD 0xffffffff ; (多是)卷標號碼 28 DB "HELLO-OS " ; 磁盤的名稱(必須爲11字?,不足填空格) 29 DB "FAT12 " ; 磁盤格式名稱(必??8字?,不足填空格) 30 RESB 18 ; 先空出18字節 31 32 ; 程序主體
剩餘部分的詳細說明在FAT32中文版分析+補充(2),固然也能夠看下圖的簡單說明:
此圖資料來自:【文件系統】FAT12文件系統簡介
Ps.其實還能夠用c語言來作一個文件系統寫入工具 (用結構體儲存分區信息)
最後搜了好久,發現百度百科也有一點記錄:https://baike.baidu.com/item/FAt12#ref_[1]_273750 ,維基百科應該有更詳細,惋惜英文版也被牆了....
經過蒐集資料,咱們如今再也不僅僅只能作FAT12,還能作FAT32的啓動甚至是exfat ext ntfs的
到這裏,咱們明白了總體
第一部分就是啓動區描述和文件系統(書中例子爲fat12)
第二部分纔是系統和程序(HelloWorld)
好,讓咱們把精力放在第二部分吧:《30天自制操做系統》筆記4 --- (Day2 下節)瞭解如何寫彙編HelloWorld程序
待續更新...