nasmc++ 读取FAT12文件系统
FAT12文件系統
基本結構
-
FAT文件系統把存儲介質看成一位的數組,基本單位是簇。
-
一個簇包含一個扇區,大小為512B
-
存儲介質劃分為3個區域:boot,FAT,directory and data area
引導扇區BOOT
| BS_OEMName | 3 | 8 | 廠商名 | ‘ZGH’ |
| BPB_BytesPerSec | 11 | 2 | 每扇區字節數(Bytes/Sector) | 0x200 |
| BPB_SecPerClus | 13 | 1 | 每簇扇區數(Sector/Cluster) | 0x1 |
| BPB_ResvdSecCnt | 14 | 2 | Boot記錄占用多少扇區 | ox1 |
| BPB_NumFATs | 16 | 1 | 共有多少FAT表 | 0x2 |
| BPB_RootEntCnt | 17 | 2 | 根目錄區文件最大數 | 0xE0 |
| BPB_TotSec16 | 19 | 2 | 扇區總數 | 0xB40 |
| BPB_Media | 21 | 1 | 介質描述符 | 0xF0 |
| BPB_FATSz16 | 22 | 2 | 每個FAT表所占扇區數 | 0x9 |
| BPB_SecPerTrk | 24 | 2 | 每磁道扇區數(Sector/track) | 0x12 |
| BPB_NumHeads | 26 | 2 | 磁頭數(面數) | 0x2 |
| BPB_HiddSec | 28 | 4 | 隱藏扇區數 | 0 |
| BPB_TotSec32 | 32 | 4 | 如果BPB_TotSec16=0,則由這里給出扇區數 | 0 |
| BS_DrvNum | 36 | 1 | INT 13H的驅動器號 | 0 |
| BS_Reserved1 | 37 | 1 | 保留,未使用 | 0 |
| BS_BootSig | 38 | 1 | 擴展引導標記(29h) | 0x29 |
| BS_VolID | 39 | 4 | 卷序列號 | 0 |
| BS_VolLab | 43 | 11 | 卷標 | ‘ZGH’ |
| BS_FileSysType | 54 | 8 | 文件系統類型 | ‘FAT12’ |
| 引導代碼及其他內容 | 62 | 448 | 引導代碼及其他數據 | 引導代碼(剩余空間用0填充) |
| 結束標志0xAA55 | 510 | 2 | 第510字節為0x55,第511字節為0xAA | 0xAA55 |
FAT-File Allocation Table
-
FAT1和FAT2互為備份。
-
每12位成為一個FAT項(FATEntry),代表一個簇。所以2個FAT項會占用3個字節
-
數據區起始于簇2,why?
-在1.44M軟盤上,FAT前三個字節的值是固定的0xF0、0xFF、0xFF,用于表示這是一個應用在1.44M軟盤上的FAT12文件系統。本來序號為0和1的FAT表項應該對應于簇0和簇1,但是由于這兩個表項被設置成了固定值,簇0和簇1就沒有存在的意義.
-
FAT項的值代表文件的下一個簇號
- 值為0xFF7,表示壞簇
- 值大于或等于0xFF8,表示當前簇是本文件的最后一個簇
根目錄區
- 根目錄區由目錄項組成,一個目錄項占32個字節。
g++與nasm混合編程
-
環境ubuntu64,安裝g++,nasm
-
my_print.asm負責輸出,1.cpp為主文件
-
1.cpp中首先聲明函數
extern "C" void my_print(char *, int, int); -
my_print.asm定義函數,注意用global my_print聲明函數名。
-
命令
$ nasm -f elf32 my_print.asm $ g++ -o fat -m32 1.cpp my_print.o $ ./fat
如何讀取FAT12文件?
Steps
讀取Boot,得到必要的參數:
- BPB_BytsPerSec 每扇區字節數
- BPB_SecPerClus 每簇扇區數
- BPB_RsvdSecCnt Boot記錄占用的扇區數
- BPB_NumFATs FAT表個數
- BPB_RootEntCnt 根目錄最大文件數
- BPB_TotSec16 FAT扇區數,如果該值為0,則BPB_FATSz32為FAT扇區數
- BPB_HiddSec
計算每簇的字節數,每個區域的初始位置的偏移量。
- 每簇字節數=每簇扇區數*每扇區字節數。
- fatBase=Boot記錄占用的扇區數*每扇區字節數
- fileRootBase=(Boot記錄占用的扇區數+FAT表個數* FAT扇區數)*每扇區字節數
- dataBase=(Boot記錄占用的扇區數+FAT表個數* FAT扇區數+(根目錄最大文件數* 32+每扇區字節數-1)/每扇區字節數)*每扇區字節數。
數據區的偏移量又乘又除是不是吃飽了撐的0.0?可不可以等于fileRootBase+根目錄最大文件數*32?不闊以!
dataBase初始位置=FileRootBase最后一個簇的結束位置。如果根目錄沒有填滿最后一個簇,數據區也是從下一個簇開始的,而不是默認于最后一個根目錄的結束位置開始。
用 (根目錄最大文件數 32+每扇區字節數-1)/每扇區字節數* 可以得到根目錄區占用的真正扇區數。
廣搜遍歷Fat12文件系統
- 首先讀取根目錄區
-
判斷文件屬性
-
目錄項的屬性記錄了該項是文件夾or文件
- 用DIR_Attr&0x10判斷,結果為0是文件,否則為文件夾。
-
處理文件夾
-
得到下一層目錄的數據區初始位置,首先需要FAT號。文件夾的目錄項中DIR_FstClus記錄了文件夾FAT號(num),其內容即為所需FAT號。
-
FAT項大小為12位。
-
從fatBase + num ***** 3 / 2讀取2個字節(16位)。結合存儲的小尾順序和FAT項結構可以得到。num為偶去掉高4位,num為奇去掉低4位。
-
(num & 1) ? (bytes >> 4) : (bytes & ((1 << 12) - 1))為下一個FAT號
-
-
用FAT號計算在數據區中的位置。
- startByte = dataBase + (fat號- 2) ***** BytsPerClus;
-
-
-
處理普通文件
- 如果文件在數據區中需要多個簇,那么用上面的辦法讀取數據。
-
廣搜遍歷
- 分層遍歷
- 每一層的文件夾放進隊列。
- 隊列為空則停止
用文件名查詢特定文件
制作FAT鏡像
創建新的軟盤鏡像
mkfs.fat -C a.img 1440掛載點,可以創建一個新的目錄
mkdir 文件名將鏡像掛載到掛載點
sudo mount a.img 文件名掛載后,就可以通過操作./mount文件夾,來向a.img加入和查看文件。可使用系統自帶的資源管理器類似 GUI工具,或者使用命令行操作。
我的呆碼👉click
支持ls,cat 文件名,ls -l[lll] [文件名],ls [文件名] -l[lll] .
reference
https://blog.csdn.net/qq_39654127/article/details/88429461#main-toc
https://blog.csdn.net/judyge/article/details/52373751
https://blog.csdn.net/yxc135/article/details/8769086
總結
以上是生活随笔為你收集整理的nasmc++ 读取FAT12文件系统的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: MIP影视模板泛站程序万能模板
- 下一篇: 转(js幻灯片,jQuery幻灯,js焦