اینو دارم دقیقا 7 دقیقه و 25 ثانیه و 15 میلی ثانیه بعد از پارت اول مینویسم😎😂 (ولی فردا یا پس فرداش منتشر میشه)
چونکه سیستم عاملمون قراره با قابلیت دیباگ و اینا باشه باید بیایم یک فایل سیستم بسازیم و بندازیم توی کدامون.
اگه از فایل سیستم استفاده نکنیم، برنامه هایی مثل rufus نمیتونن بخوننش و نمیتونن کپی کنن روی یو اس بی.
چند تا فایل سیستم بود مثل Fat و exFat و Refs و Ntfs و من تصمیم گرفتم از Fat16 استفاده کنم که بهترین انتخاب برای 16 بیتیه، چون محاسباتش 16 بیتیه.

گفته بودم بایوس میاد 512 بایت اول رو میخونه، توی بوت سکتور میایم داده های fat16 رو میریزیم و یک مدیریت فایل خیلی بهینه و کوچیک که قراره بره کرنل رو از مسیر خاصی لود کنه.
مثلا مسیرمون کرنلمون این باشه:
X:/Inous/kernel.sys
اون 512 بایت میاد میره توی پوشه Inous و فایل kernel.sys رو میندازه تو رم و بعد جامپ میکنه روش!
اگه فایل سیستم رو نزنیم، مثل این میمونه توی شهر لس انجلس با یک نقشه کاغذی مسیریابی کنی. باید ادرس کرنل رو بصورت CHS و همچنین سایز رو بدیم تا بیاد اونو لود کنه. حالا دردسر LBA به CHS هم به کنار.

سه بایت اول که قراره جامپ کنه به اون 448 بایت باقی و فاصله شون دیتا هایی هست که ما باید پر کنیمشون که تقریبا میشن 59 بایت داده، چونکه ما بصورت 16 بیتی داریم به قبل از 255 جامپ میکنیم، دو بایت میشه جامپمون، اون یکی رو باید با nop پر کنیم، در اخر هم کد جادویی بوت 0xaa55 رو میزاریم.
پس این میشه فایل جدید boot.asm:
use16 org 0x7c00 jmp boot nop BOOT_SIZE equ 512 BPB Fat16 boot: cli hlt rb BOOT_SIZE - ($-$$) - 2 dw 0xaa55
اینم فایل جدید به اسم fat.asm:
use16 OEMID equ 'INOUS ' BYTES_PER_SECTOR equ 512 SECTORS_PER_CLUSTER equ 1 RESERVED_SECTORS equ 1 NUMBER_FAT_COPIES equ 2 NUMBER_ROOT_ENTRIES equ 512 SMALL_NUMBER_SECTORS equ 2 * 80 * 18 MEDIA_DESCRIPTOR equ 0xf0 SECTORS_PER_FAT equ 12 SECTORS_PER_TRACK equ 18 NUMBER_HEADS equ 2 HIDDEN_SECTORS equ 0 LARGE_NUMBER_SECTORS equ 0 DRIVE_NUMBER equ 0 RESERVED_NT equ 0 EXT_BOOT_SIG equ 0x29 VOLUME_SERIAL equ 0x57694123 VOLUME_LABEL equ 'LOCAL DISK ' FILESYSTEM_TYPE equ 'FAT16 ' struc Fat16 { .OEMID db OEMID .BYTES_PER_SECTOR dw BYTES_PER_SECTOR .SECTORS_PER_CLUSTER db SECTORS_PER_CLUSTER .RESERVED_SECTORS dw RESERVED_SECTORS .NUMBER_FAT_COPIES db NUMBER_FAT_COPIES .NUMBER_ROOT_ENTRIES dw NUMBER_ROOT_ENTRIES .SMALL_NUMBER_SECTORS dw SMALL_NUMBER_SECTORS .MEDIA_DESCRIPTOR db MEDIA_DESCRIPTOR .SECTORS_PER_FAT dw SECTORS_PER_FAT .SECTORS_PER_TRACK dw SECTORS_PER_TRACK .NUMBER_HEADS dw NUMBER_HEADS .HIDDEN_SECTORS dd HIDDEN_SECTORS .LARGE_NUMBER_SECTORS dd LARGE_NUMBER_SECTORS .DRIVE_NUMBER db DRIVE_NUMBER .RESERVED_NT db RESERVED_NT .EXT_BOOT_SIG db EXT_BOOT_SIG .VOLUME_SERIAL dd VOLUME_SERIAL .VOLUME_LABEL db VOLUME_LABEL .FILESYSTEM_TYPE db FILESYSTEM_TYPE }
برای ساختار داده fat16 یکدونه struc ساختیم که مثلا وقتی زدیم:
BPB Fat16 mov bx, [BPB.BYTES_PER_SECTOR]
به درستی کار کنه، و داده های خود بوت با داده های فت 16 با هم دیگه قاطی نشن، در اینجا BPB به معنی (BIOS Parameter Block ) هست، حالا میرسیم به قسمت سخت ماجرا، ما باید همزمان سه بخش از فلاپی رو کنترل کنیم، یکدونه خود FAT یکدونه هم Root Entry و اون یکی منطقه داده یا (Data Region) هست.
در ساختار bpb ما اومدیم یکسری اطلاعات پایه رو اوکیش کردیم، دقت داشته باشید VOLUME_SERIAL باید 32 بیتی باشه و رندوم باشه، منم یک چیز رندوم زدم😅

الان باید فایل kernel.asm رو اسمبل کنیم و بزاریمش توی سه ناحیه ای که گفتم، اینجا دیگه نمیشه از اسمبلی استفاده کرد، باید از زبان جمع و جور خود fasm در طول اسمبل استفاده کنیم.
باید در اینجا کار با ویرچوال رو بلد باشین، چون:
برای FAT باید سایز فایل رو بدونم
برای سایز فایل باید data رو include کنم
ولی data بعد از FAT میاد 😐
و چون اسمبلر خطی میره جلو و seek نمیکنه باید از ویرچوال استفاده کنیم!
پس ما اول بریم fat رو اوکی کنیم، خود fat دو کلستر رو رزرو کرده، که اونام 0 و 1 هستن.

اول میایم کرنل رو توی ویرچوال میزاریم و حجمشو حساب میکنیم و بعد یک حلقه ایجاد میکنیم و میگیم توش ایا این اخرین کلستر هست یا نه، اگه بود 0xffff میزاره، در غیر اینصورت میاد شماره کلستر بعدی رو میفرسته.

میایم فایل build.asm:
format binary as 'img' use16 org 0x0000 FLOPPY_SIZE equ 2 * 80 * 18 * 512 include 'fat.asm' include 'boot.asm' org 0x7d00 ; ========== FAT Region ========== virtual at 0 file_start: include 'kernel.asm' file_end: end virtual clusters_size = BYTES_PER_SECTOR * SECTORS_PER_CLUSTER rept NUMBER_FAT_COPIES i:1 { current_pos = $ FAT#i#_ENTRY1: db 0xff, MEDIA_DESCRIPTOR FAT#i#_ENTRY2: dw 0xffff file_size = file_end - file_start file_clusters = (file_size + clusters_size - 1) / clusters_size if file_clusters = 0 dw 0xffff else repeat file_clusters if file_clusters = % dw 0xffff else dw (% + 2) end if end repeat end if rb (SECTORS_PER_FAT * BYTES_PER_SECTOR) - ($-current_pos) } ; ======== END FAT Region ======== rb FLOPPY_SIZE - ($-$$) - 1 db 0
الان اومدیم فایل کرنل رو لود کردیم و کاراشو انجام دادیم البته فقط بخش fat، اخر سر میایم یک پیمایش لیستی برای بقیه فایل ها میزاریم. الان باید بریم root region.

توی این ساختار فقط میشد 8 کاراکتر نام انتخاب کرد و 3 کاراکتر پسوند ( فقط حروف انگلیسی و اعداد و یکسری علامت )، بیشتر از اون نمیشد نام انتخاب کرد، اگه نام هم کوچیک بود و یا پسوند نداشت با space (0x20) میومدن پدینگ میزدن، اما بعدش یک ساختار دیگه هم بهش اضافه شد، به نام LFN ( Long File Name ) که میتونستی نام طولانی بزاری ( با پشتیبانی یونیکد ) که 13 کاراکتر یونیکد قبول میکنه! ( پسوند هم میتونه طولش متفاوت باشه).
یعنی اگه گوشی قدیمی دارین، هر فایل بصورت دو نام ذخیره شده.

Ordinal field که برای ترتیب و شمارش و دو تا فلگ هست.
بقیش که معلومه غیر از check sum که میاد اولین کاراکتر نام (8.3) رو میندازه تو یک متغیر، بعد شیفت میده یکی به سمت راست و بعد کاراکتر بعدی رو اضافه میکنه، 8 بیت کم ارزش رو نگه میداره، بعد میره همینجوری تا کاراکتر اخر.
بقیش رو چون خستم پارت بعدی میزارم، همینجوریشم این پارت به اندازه کافی عقب افتاده😂😅