Here I intend to explain the structure of a FAT12 floppy boot sector.
It needs to activate Unreal Mode, be compatible with DOS loading standards (loading image at 600h or 700h) so we can implement the skeleton of a DOS system with the intention to reuse code and known standards and load easily the second part of the system from there, while keeping a good deal of scalable capabilities at the DOS level for the booting stage.
With these simplifications, it will be very easy to start learning about the booting process from the simplest device (the floppy).
Being so tiny, this program can serve us as a model to pack concrete components that are directly related, and that aren't so apart that it would be difficult to describe them in a tutorial in a short time and space.
Look at how the program skeleton has a list of numbered comments that describe the exact order in which it must execute the different booting tasks. To complete it, you just need to include the equally-numbered pieces of actual code that will be presented in different posts containing explanations for these different specific tasks.
_________________________________________________________________________
_________________________________________________________________________
_________________________________________________________________________
_________________________________________________________________________
FAT12 Boot Sector Empty Skeleton
Code: Select all
BASEADDR equ 0h ;Change this to 0h or 7C00h for global start
BOOT_ADDR equ 7C00h
BASEADDR_SEG equ BOOT_ADDR>>4
org BASEADDR
%define resbytes 510-(unused-_00h_jmp)
_00h_jmp: db 0EBh ;jmps 003E
db 03Ch ;2 (2)
_02h_nop: nop ;1 (3)
_03h_OEMid db "OEMIdent" ;8 (11)
_0Bh_bytesPerSect dw 0200h ;2 (13)
_0Dh_sectsPerClust db 001h ;1 (14)
_0Eh_reservedSects dw 0001h ;2 (16)
_10h_numOfFATs db 002h ;1 (17)
_11h_numRootDirEntries dw 00E0h ;2 (19)
_13h_numSectors dw 0B40h ;2 (21)
_15h_mediaType db 0F0h ;1 (22)
_16h_numFATsectors dw 0009h ;2 (24)
_18h_sectorsPerTrack dw 0012h ;2 (26)
_1Ah_numHeads dw 0002h ;2 (28)
_1Ch_numHiddenSects dd 00000000h ;4 (32)
_20h_numSectorsHuge dd 00000000h ;4 (36)
_24h_driveNumber db 00h ;1 (37)
_25h_reserved db 00h ;1 (38)
_26h_signature db 29h ;1 (39)
_27h_volumeID db "????" ;4 (43)
_28h_volumeLabel db "VolumeLabel" ;11 (54)
_36h_FSType db "FAT12 " ;8 (62)
;INIT: 448 free bytes
;INIT: 448 free bytes
;INIT: 448 free bytes
;1. Code to configure CS:IP here:
;;
;2. Code to load GDT and enable Protected Mode here:
;;
;3. Load registers with GDT selectors, disable Protected Mode and
; set up stack and Un/Real Mode segment registers:
;;
;4. Enable A20 Line here:
;;
;5. Reenable interrupts here:
;;
;6. Configure program disk parameter information here:
;;
;7. Search 8.3 file name in root directory:
;;
;8. Read file contents:
;;
;9. Jump to the 16-bit Real Mode bootup image
; (it's intended to jump to 70h:0000h or 700h physical):
;;
;10. read_sectors BIOS-based function:
;;
;11. 8.3 bootup file name:
;;
;12. GDT table with 3 selectors (null, code, data) here:
;;
;13. Program variables here:
;;
unused: times resbytes db 0x55
;END: 448 free bytes
;END: 448 free bytes
;END: 448 free bytes
_1F_55AA_signature dw 0xAA55 ;2 (512)
_________________________________________________________________________
_________________________________________________________________________
_________________________________________________________________________
_________________________________________________________________________
Major Components
Once we know the structure of the boot sector skeleton, we need to perform the following tasks:
1. Enable line A20.
2. Enable Unreal Mode.
3. Finding the binary file to run, loading and searching the root directory 1 sector at a time.
4. Read the file directly to its final memory location, 1 cluster at a time (typically 1 sector per cluster).
5. Jump to the binary file to run it.