Ideal model TINY P286 macro PrintAL MOV AH, 0EH MOV BL, 0FFH INT 10H endm DataSeg STACK_TOP = 7C00H SHIFT = 7C00H - 103H ; PSP = 100H bytes, JMP BOOT_BEGIN = 3 bytes FIRST_MODUL = 0700H ; Address that first modul is to load BUFF_SEG = 0000H ; Segment BUFF_OFS = 7C00H + 200H ; and offset of first memory block after boot record ; Here will be read sector with moduls' length & location ENTRY_SIZE = 32 ; 32 bytes each directory entry DIR_ADDR = 0500H ; Address for directory org 100h CodeSeg STARTUPCODE JMP BOOT_BEGIN ; The follow is the same as MS-DOS boot record (version 4.0 or higher) Boot_Start: JMP SHORT @@Start ; Jump over data NOP ; Near jump expected, short one used ; so we need one extra byte here VersionID db 'TUOX1.01' ; Company and version BytesPerSec dw 512 ; 512B per sector SectorsPerCluster db 1 ; Sectors per allocation unit ReservedSecs dw 1 ; Reserved sector count (boot record) FATCount db 2 ; Number of FATs RootSize dw 224 ; Root directory entries (32B each) TotalSectors dw 2880 ; Total sector number on the disk FormatID db 0F0H ; F0 = HD 1,44M (same as 1st byte in FAT) FATSize dw 9 ; Size of FAT in sectors SectorsPerCyl dw 18 ; Sectors per track (cylinder) Sides dw 2 ; Diskette -> 2 sides HiddenLow dw 0 ; Special reserved sectors ( < 32M ) HiddenHi dw 0 ; The same but for partition > 32MB TotalSectors32 dd ? ; 32bit TotalSectors DriveNo db 0 ; 0 = floppy Unused db 0 ; Reserved ExtSignature db ')' ; Extended boot record signature VolumeSerialNo db 1,0,1,0 ; Volume serial number 0001-0001 VolumeLabel db 'TUOXsysdisk' ; Volume label (max. 11 chars) Reserved db 'FAT12 ' ; 8 bytes ; Boot record end (total 62 bytes) ; Here come the variables that TUOX needs RAMDiskSize dw 8192 ; Size of memory block reserved for RAM disk ; in paragraphs (131072 bytes - enough?) ; This variables are used in boot code, not neccessary outside Head db ? ; Head number Sector db ? ; Cylinder's first sector to read (6 bits) Cylinder dw ? ; Cylinder (10 bits) SecsB4Dir dw ? ; Sectors before directory entries FirstDataSec dw ? ; First sector with data LoaderSize db ? ; Loader file size in sectors @@Start: CLI XOR AX, AX MOV SS, AX MOV SP, STACK_TOP ; Stack initiation MOV DS, AX MOV ES, AX STI ; Reset FDD MOV DL, [BYTE DriveNo + SHIFT] INT 13H ; Device reset (AH = 0) JC @@Boot_Failure ; Reset error ; Calculate first data sector MOV AX, [FATSize + SHIFT] MOV CL, [FATCount + SHIFT] MUL CL ADD AX, [ReservedSecs + SHIFT] ; Reserved & FATs MOV [SecsB4Dir + SHIFT], AX ; Directory begins from here MOV AX, [RootSize + SHIFT] XOR DX, DX MOV CX, ENTRY_SIZE MUL CX MOV BX, [BytesPerSec + SHIFT] DEC BX ADD AX, BX ADC DX, 0 INC BX DIV BX ADD AX, [SecsB4Dir + SHIFT] MOV [FirstDataSec + SHIFT], AX ; Look for file 'LOAD.COM' in directory MOV AX, [SecsB4Dir + SHIFT] CALL CalcSector MOV AL, 1 MOV BX, DIR_ADDR CALL ReadSector ; Read first directory sector JC @@Boot_Failure MOV DI, BX ; Pointer to first file name MOV CX, 11 ; File name length (8+3) MOV SI, OFFSET LoaderName + SHIFT REP CMPSB JZ @@Continue ; String 'LOAD COM' found in dir. entries ; Boot failed (read error, loader not found), message & try again @@Boot_Failure: MOV SI, OFFSET BootFailMsg + SHIFT CALL WriteString ; Print error message XOR AH, AH ; BIOS keyboard service INT 16H ; Wait for key stroke INT 19H ; Try to load boot sector again @@Continue: ; Calculate loader file size in sectors MOV AX, [DIR_ADDR + 1CH] ; File size in offset 1CH MOV DX, [DIR_ADDR + 1CH + 2]; We really need it? MOV BX, [BytesPerSec + SHIFT] DEC BX ADD AX, BX ADC DX, 0 INC BX DIV BX ; AX = (FileSize+BytesPerSec-1)/BytesPerSec MOV [BYTE LoaderSize + SHIFT], AL ; Size of LOAD.COM in sectors ; Now we'll read the loader from the first data sector MOV BX, FIRST_MODUL shr 4 MOV ES, BX XOR BX, BX ; First modul begins at 0070:0000 @@Read_Continue: MOV AX, [FirstDataSec + SHIFT] CALL CalcSector MOV AL, [SectorsPerCluster + SHIFT] XOR AH, AH PUSH AX CALL ReadSector ; We'll read a number of cluster ; 'cause disk type is FAT POP AX JC @@Boot_Failure SUB [LoaderSize + SHIFT], AL ; AL sectors OK JNA @@Load_Completed ADD [FirstDataSec + SHIFT], AX ; Next sector to read XOR DX, DX MUL [BytesPerSec + SHIFT] ADD BX, AX ; BX = new address to read to JMP SHORT @@Read_Continue @@Load_Completed: JMP FAR 0:FIRST_MODUL proc WriteString near ; Print an ASCIIZ string at DS:SI @@Write_Begin: LODSB ; Next character OR AL, AL JZ @@Write_End ; NUL = end of ASCIIZ string MOV AH, 0EH ; BIOS service - write character MOV BL, 0FFH ; Char's attribute INT 10H JMP SHORT @@Write_Begin @@Write_End: RET endp WriteString proc CalcSector near ; Calculates side, cylinder & abs. sector number from relative sector number ; Input: AX = relative sector ; Relative sector = Cyl# * SPC * HD + Head# * SPC + Sec# - 1 (zero base) ; Results are saved to Sector, Head and Cylinder variables ; Modified registers: AX, DX XOR DX, DX DIV [WORD SectorsPerCyl + SHIFT] INC DL MOV [Sector + SHIFT], DL XOR DX, DX DIV [WORD Sides + SHIFT] MOV [Cylinder + SHIFT], AX MOV [Head + SHIFT], DL RET endp CalcSector proc ReadSector near ; Read a number of sectors to memory at ES:BX ; Input: AL = sector count to read ; Other data from Sector, Head and Cylinder variables ; Modified registers: AX, CX, DX @@Read_Continue: MOV AH, 02H ; BIOS service - sector read MOV DX, [Cylinder + SHIFT] ; Cylinder# - 10 bits MOV CH, DL ; 8 lower bits ROR DH, 1 ROR DH, 1 AND DH, 11000000B ; Mask 2 highest bits MOV CL, [Sector + SHIFT] AND CL, 00111111B ; Sector# - 6 bits OR CL, DH ; 2 bits = Cylinder# 8th & 9th bit ; CX = Cylinder + Sector (16 bits) MOV DH, [Head + SHIFT] MOV DL, [BYTE DriveNo + SHIFT] INT 13H RET endp ReadSector BootFailMsg db 'Non-system disk or disk error',10,13 KeyPressMsg db 'Insert TUOX diskette and press any key...',10,13,0 LoaderName db 'LOAD COM' ; blank padded loader file name @@BootCode_End: BOOT_BEGIN: ; Write Boot sector to disk MOV SI, OFFSET Boot_Start MOV DI, OFFSET BootBuffer MOV CX, 510 / 2 REP MOVSW MOV AX, 0AA55H ; End of boot sector signature STOSW MOV DL, [BYTE DriveNo] MOV DH, 0 MOV CX, 0001H MOV AX, 0301H MOV BX, OFFSET BootBuffer INT 13H ; Write buffer to boot sector JNC @@Write_OK MOV SI, OFFSET WriteErrorMsg JMP SHORT @@Do_Write @@Write_OK: MOV SI, OFFSET WriteOKMsg @@Do_Write: CALL WriteString ; Write next sector that contains "directory" EXITCODE WriteErrorMsg db 'Boot Writing Error', 10, 13, 0 WriteOKMsg db 'Boot Successfully Written', 10, 13, 0 BootBuffer db 512 dup(0) ends end