cpu 8086 org 0x7c00 ;Jump to the code jmp start ;Padding nop ;OEM label db "ETTINOS " %ifdef F1440 ;1.44 MB 3.5" floppy disk BPB (enable with the argument -d F1440) sectorsize dw 0x200 ;bytes clustersize db 0x1 ;sectors reservedsectors dw 0x1 fats db 0x2 rootentries dw 0xe0 logicalsectors dw 0xb40 mediadescriptor db 0xf0 sectorsperfat dw 0x9 sectorspertrack dw 0x12 heads dw 0x2 %else ;360 KiB 5.25" floppy disk BPB (default) sectorsize dw 0x200 ;bytes clustersize db 0x2 ;sectors reservedsectors dw 0x1 fats db 0x2 rootentries dw 0x70 logicalsectors dw 0x2d0 mediadescriptor db 0xfd sectorsperfat dw 0x2 sectorspertrack dw 0x9 heads dw 0x2 %endif ;Setup ;Set the segments start: mov ax, 0x0 mov ds, ax mov ss, ax mov es, ax ;Set the stack cli mov sp, 0x0 sti ;Store the boot drive number mov [drive], dl ;Calculate and store variables not found in the BPB ;Start of the root mov ah, 0x0 mov al, [fats] mul word [sectorsperfat] add ax, [reservedsectors] mov [rootstart], ax ;Size of the root in sectors mov ax, [rootentries] mov dx, 0x20 mul dx mov dx, 0x0 div word [sectorsize] mov [rootsectors], ax ;Start of data add ax, [rootstart] mov [datastart], ax ;Load the root ;Set the source mov ax, [rootstart] ;Set the destination mov si, buffer mov bx, si ;Set the size mov cx, [rootsectors] ;Store the source and the loop counter in the stack loadrootsector: push ax push cx ;Set the source call calcsource ;Set the size mov al, 0x1 ;Load a sector mov ah, 0x2 int 0x13 ;Load the loop counter and the source from the stack pop cx pop ax ;Set the next sector add ax, 0x1 add bx, word [sectorsize] ;Load the next sector loop loadrootsector ;Search the root for the system entry ;Set DI to the root mov di, buffer ;Set the number of root entries mov cx, word [rootentries] ;Set the entry pointer mov ax, 0x0 ;Store the loop counter in the stack search: push cx ;Check for the system entry mov si, file mov cx, 0xb rep cmpsb je loadfat ;Set DI at the next entry add ax, 0x20 mov di, buffer add di, ax ;Load the loop counter from the stack pop cx ;Search the next entry loop search ;Print an error message and hang if the system is not found ;Set SI at the file error message mov si, filerrormsg ;Load a character printstr: lodsb ;Check for the string end cmp al, 0x0 je $ ;Print the character mov ah, 0xe int 0x10 ;Print the next character jmp printstr ;Load the FAT ;Load CX from the stack loadfat: pop cx ;Store the address of the first cluster mov ax, [di + 0xf] mov [cluster], ax ;Set the source mov ax, [reservedsectors] call calcsource ;Set the destination mov bx, buffer ;Set the size mov ax, [sectorsperfat] ;Load the FAT mov ah, 0x2 int 0x13 ;Load a cluster loadcluster: ;Set the source mov ax, word [cluster] sub ax, 0x2 mul byte [clustersize] add ax, [datastart] ;Set the destination mov bx, word [pointer] ;Set the size mov ch, 0x0 mov cl, byte [clustersize] ;Store the loop counter in the stack loadclustersector: push cx ;Set the source call calcsource ;Set the size push ax mov al, 0x1 ;Load a sector mov ah, 0x2 int 0x13 pop ax ;Set the next sector add ax, 0x1 add bx, [sectorsize] ;Load the loop counter from the stack pop cx ;Load the next sector loop loadclustersector ;Calculate the next cluster ;Check if the cluster is even or odd mov ax, [cluster] mov dx, 0x0 mov bx, 0x3 mul bx mov bx, 0x2 div bx mov si, buffer add si, ax mov ax, word [si] or dx, dx jz even ;If the cluster is odd shift out the first four bits times 0x4 shr ax, 0x1 jmp contcalc ;If the cluster is even mask out the final four bits even: and ax, 0xfff contcalc: ;Check for the file end cmp ax, 0xff8 jge boot ;Store the address of the next cluster mov word [cluster], ax ;Set the destination of the next cluster mov ax, [sectorsize] mul word [clustersize] add word [pointer], ax ;Load the next cluster jmp loadcluster ;Boot the system ;Pass the boot drive number to the system boot: mov dl, byte [drive] ;Boot the system jmp 0x0:0x500 ;Data drive db 0x0 rootstart dw 0x0 rootsectors dw 0x0 datastart dw 0x0 file db "SYSTEM BIN" filerrormsg db "System not found", 0xd, 0xa, 0x0 cluster dw 0x0 pointer dw 0x500 ;*** ;Calculate the source arguments for loading data from the disk calcsource: ;Store AX and BX in the stack push ax push bx ;Calculate the cylinder, head, and sector ;Store the logical sector in BX mov bx, ax ;Calculate the sector mov dx, 0x0 div word [sectorspertrack] add dl, 0x1 mov cl, dl ;Load the logical sector from BX mov ax, bx ;Calculate the head and cylinder mov dx, 0x0 div word [sectorspertrack] mov dx, 0x0 div word [heads] mov dh, dl ;Head mov ch, al ;Cylinder ;Load the boot drive number mov dl, byte [drive] ;Load BX and AX from the stack pop bx pop ax ;Return ret ;*** ;Padding times 0x1fe-($-$$) db 0x0 ;Boot signature dw 0xaa55 ;File system buffer buffer: