CPU 8086 ORG 0x7c00 jmp start nop ;Disk description tables %ifdef F1440 ;1.44 MB 3.5" floppy disk (enable with the argument -d F1440 when building) oemlabel db "ETTINOS " sectorsize dw 0x200 ;bytes clustersize db 0x1 ;sectors bootsectors dw 0x1 fats db 0x2 rootentries dw 0xe0 logicalsectors dw 0xb40 mediadescriptor db 0xf0 sectorsperfat dw 0x9 sectorspertrack dw 0x12 sides dw 0x2 hiddensectors dd 0x0 largesectors dd 0x0 driveid dw 0x0 drivesignature db 0x29 volumeid dd 0x0 volumelabel db "ETTINOS " filesystem db "FAT12 " %else ;360 KiB 5.25" floppy disk (default) oemlabel db "ETTINOS " sectorsize dw 0x200 ;bytes clustersize db 0x2 ;sectors bootsectors dw 0x1 fats db 0x2 rootentries dw 0x70 logicalsectors dw 0x2d0 mediadescriptor db 0xfd sectorsperfat dw 0x2 sectorspertrack dw 0x9 sides dw 0x2 hiddensectors dd 0x0 largesectors dd 0x0 driveid dw 0x0 drivesignature db 0x29 volumeid dd 0x0 volumelabel db "ETTINOS " filesystem db "FAT12 " %endif start: ;Setup ;Set up the data, stack, and extra segments mov ax, 0x0 mov ds, ax mov ss, ax mov es, ax ;Set up the stack cli mov sp, stack add sp, 0x100 sti ;Store the boot device number mov [bootdev], dl ;Load the root ;Set the source mov ah, 0x0 mov al, [fats] mul word [sectorsperfat] add ax, [bootsectors] push ax call calcsource ;Set the destination mov si, 0x7f00 mov bx, si ;Set the size push dx mov ax, [rootentries] mov dx, 0x20 mul dx mov dx, 0x0 div word [sectorsize] pop dx push ax ;Load mov ah, 0x2 int 0x13 ;Search the root for the system ;Set DI to the root mov di, 0x7f00 ;Initialise the search loop mov cx, word [rootentries] mov ax, 0x0 search: ;Store CX in the stack push cx ;Check for the system FAT mov si, sysfile mov cx, 0xb rep cmpsb je loadfat ;Set DI to the next entry add ax, 0x20 mov di, 0x7f00 add di, ax ;Load CX from the stack pop cx loop search ;Load the system entry loadfat: ;Load CX from the stack pop cx ;Store the first cluster mov ax, word [es:di+0xf] mov word [cluster], ax ;Set the source mov ax, 0x1 call calcsource ;Set the destination mov di, 0x7f00 mov bx, di ;Set the size mov ax, [sectorsperfat] ;Load mov ah, 0x2 int 0x13 ;Load the system file ;Load a cluster loadcluster: ;Set the source pop cx pop bx mov ax, word [cluster] sub ax, 0x2 mul byte [clustersize] add ax, bx add ax, cx push bx push cx call calcsource ;Set the destination mov bx, word [pointer] ;Set the size ;mov al, 0x1 mov al, [clustersize] ;Load mov ah, 0x2 int 0x13 ;Calculate the next cluster mov ax, [cluster] mov dx, 0x0 mov bx, 0x3 mul bx mov bx, 0x2 div bx mov si, 0x7f00 add si, ax mov ax, word [ds:si] or dx, dx jz even odd: shr ax, 1 shr ax, 1 shr ax, 1 shr ax, 1 jmp contcalc even: and ax, 0xfff contcalc: mov word [cluster], ax cmp ax, 0xff8 jge boot mov ax, [sectorsize] mul word [clustersize] add word [pointer], ax jmp loadcluster ;Boot the system boot: jmp 0x0:0x500 ;Data bootdev db 0x0 sysfile db "SYSTEM BIN" cluster dw 0x0 pointer dw 0x500 ;Calculate the source arguments for loading data from the disk calcsource: push ax push bx mov bx, ax mov dx, 0x0 div word [sectorspertrack] add dl, 0x1 mov cl, dl mov ax, bx mov dx, 0x0 div word [sectorspertrack] mov dx, 0x0 div word [sides] mov dh, dl mov ch, al pop bx pop ax mov dl, byte [bootdev] ret ;Pad the binary to a full sector and make the disk bootable ;Padding times 0x1fe-($-$$) db 0x0 ;Boot signature dw 0xaa55 stack: