Tvůrce webu je i pro tebe! Postav třeba web. Bez grafika. Bez kodéra. Hned.
wz

Lineární zaváděcí sektor

Lineární zaváděcí sektor umožňuje zavedení systému nebo aplikace lineárně ze sektorů následujících bezprostředně za zaváděcím sektorem. Disk nepoužívá žádný souborový systém. Lineární zaváděcí sektor je vhodný např. pro jednoúčelové aplikace jako jsou řídicí systémy nebo herní automaty.

Vytvořte soubor BOOT.ASM, který bude obsahovat zdrojový kód zaváděcího sektoru. Po vytvoření kódu provedete překlad příkazem "NASM16.EXE -o BOOT.BIN BOOT.ASM".

; ----------------------------------------------------------------------------
;             Start of the boot sector (starting at 0000:7C00)
; ----------------------------------------------------------------------------

SECTION		.text

		org	7C00h		; booting address of boot sector

Start:		jmp	Init		; jump to starting routine

; ------------- Setup data (this can be set by the installator)

SectRead	dw	1		; 3: number of sectors to read
Disk		db	0		; 5: system disk (0=A:, 80h=C:)
Heads		db	2		; 6: number of heads
Sectors		db	18		; 7: number of sectors per track
DestSegm	dw	80h		; 8: destination segment
; Warning: Due to architecture of DMA controller sector buffer cannot overlap
; 64 KB boundary. Therefore use destination segment 60h, 80h, 0A0h etc.

Message		db	"Error loading system.",13,10
		db	"Press any key...",13,10,0

DiskTab		times 11 db 0		; disk table (11 bytes)

; ------------- Init temporary stack (for calling int 12h)
	
Init:		cli			; disable interrupts
		xor	ax,ax		; AX <- 0
		mov	ds,ax		; DS <- 0 this segment
		mov	si,7C00h	; SI <- offset of the boot sector
		mov	ss,ax		; SS <- 0
		mov	sp,si		; SP <- end of stack
		sti			; enable interrupt

; ------------- Determining top of memory (usualy 0A000h)

		int	12h		; AX <- get memory size in 1 KB blocks
		mov	cl,6		; number of rotations
		shl	ax,cl		; segment address of the top of memory
		sub	ax,7E0h		; correction of the segment address

; ------------- Init stack (lies below new beginning of the boot sector)

		cli			; disable interrupts
		mov	ss,ax		; SS <- destination segment
		mov	es,ax		; ES <- destination segment

; ------------- Moving loader high

		mov	di,si		; DI <- offset of the boot sector
		mov	cx,100h		; CX <- 256 length of sector in words
		cld			; direction up
		rep	movsw		; moving sector up

; ------------- Jump to new boot sector

		push	es		; segment of far jump
		push	word Continue	; offset of far jump
		retf			; jump to new sector

; ------------- Load disk param table

Continue:	mov	bx,4*1eh	; address of INT 1Eh vector
		lds	si,[bx]		; DS:SI <- address of disk param table
		push	ds		; push old address DS of table
		push	si		; push old address SI of table
		mov	cl,11		; CX <- length of disk param table
		mov	di,DiskTab	; DI <- buffer for disk param table
		rep	movsb		; load disk param table

; From this point DS:SI (original disk param table) is pushed in the stack!!!
		
; ------------- Set address of new disk param table

		mov	ds,cx		; DS <- 0		
		mov	word [bx],DiskTab; offset of new disk table
		mov	[bx+2],es	; segment of new disk table

; ------------- Set new parameters of disk param table

		mov	ds,ax		; DS <- this segment
		mov	al,[Sectors]	; number of sectors per track
		mov	[di-7],al	; number of last sector on track (offset 4)
		mov	byte [di-2],15	; start-up time for floppy (offset 9)
		sti			; enable interrupt

; ------------- Reset disk system

		xor	ax,ax		; AX <- 0
		mov	dl,[Disk]	; DL <- disk to reset
		int	13h		; reset disk system

; ------------- Prepare to read system

		mov	bx,[DestSegm]	; BX <- start segment to read system to
		mov	si,[SectRead]	; Sectors to read
		mov	cx,2		; CL <- 2 sector, CH <- 0 cylinder
		mov	dh,0		; DH <- 0 head

; ------------- Determine number of sectors in one read

Read:		mov	di,3		; DI <- 3 error counter
		mov	ah,0		; AH <- 0
		mov	al,[Sectors]	; AL <- number of sectors per track
		inc	ax		; AL = number of sectors + 1
		sub	al,cl		; AL = sectors to the end of track
      		cmp	ax,si		; compare to sectors to read
		jbe	Read1		; number of sectors is OK
		mov	ax,si		; limit number of sectors

; ------------- Limit number of sectors to not overlap 64 KB boundary

Read1:		mov	ah,al		; AH <- number of sectors to read
		mov	bp,bx		; BP <- destination segment
		shl	bp,1
		shl	bp,1
		shl	bp,1
		shl	bp,1		; BP * 16 (offset)
		mov	al,0		; AL <- sector counter
Read2:		inc	ax		; increase number of sectors
		add	bp,512		; add 1 sector
		jc	Read3		; next sector will be behind 64 KB
		cmp	al,ah		; will there be next sector?
		jb	Read2		; test next sector

; ------------- Push registers

Read3:		push	ax		; push AX (number of sectors to read)
		push	bx		; push BX (destination segment)
		push	cx		; push CX (sector and cylinder)
		push	dx		; push DX (head)
		push	si		; push SI (sectors to read)
		push	di		; push DI (error counter)

; ------------- Read group of sectors (AL=num, CH=cyl, CL=sect, DH=head, BX=seg)

		mov	ah,2		; function to read sectors
		mov	dl,[Disk]	; DL <- disk to read from
		mov	es,bx		; ES <- destination segment
		xor	bx,bx		; BX <- 0 destination offset
		int	13h		; read sectors

; ------------- Pop register

		pop	di		; pop DI (error counter)
		pop	si		; pop SI (sectors to read)
		pop	dx		; pop DX (head)
		pop	cx		; pop CX (sector and cylinder)
		pop	bx		; pop BX (destination segment)
		pop	ax		; pop AX (number of sectors to read)
		jc	Error		; error

; ------------- Test first data sector

		cmp	bx,[DestSegm]	; is it first data sector?
		jne	Read4		; it is not first data sector
		cmp	word [es:3],8A25h ; test identifier
		jne	ErrorLast	; error, invalid sector

; ------------- Count sectors

Read4:		mov	ah,0		; AX = number of sectors in one read
		sub	si,ax		; SI <- decrement number of sectors
		jz	AllOK		; all sectors are loaded

; ------------- Increase sector number

		add	cl,al		; CL = new sector number

; ------------- Increase destination segment

		push	cx		; push CX
		mov	cl,5		; CL <- rotations
		shl	ax,cl		; AX = segment shift
		add	bx,ax		; BX = increase segment address
		pop	cx		; pop CX

; ------------- Next sectors

		cmp	cl,[Sectors]	; is it last sector on track?
		jbe	Read		; there are another sectors on track
		mov	cl,1		; CL <- 1 sector of next track
		inc	dh		; DH = next head
		cmp	dh,[Heads]	; overflow number of heads?
		jb	Read		; number of head is OK
		mov	dh,0		; head on next track
		inc	ch		; CH = next cylinder
		jmp	short Read	; read next sectors

; ------------- ALL OK: Return old disk param table

AllOK:		xor	ax,ax		; AX <- 0
		mov	ds,ax		; DS <- 0
		pop	ax		; AX <- offset of old disk param table
		mov	[4*1Eh],ax	; pop offset of old disk param table
		pop	ax		; AX <- segmnet of old disk param table
		mov	[4*1Eh+2],ax	; pop segment of old disk param table

; ------------- Jump to system in memory

		push	word [cs:DestSegm]; segment of new system
		push	ds		; 0 offset of new system
		retf			; jump to new system

; ------------- ERROR: next attempt

Error:		dec	di		; error counter
		jz	ErrorLast	; it was last error

; ------------- Reset disk and try again

		push	ax		; push AX (number of sectors)
		push	dx		; push DX (head)
		xor	ax,ax		; AX <- 0
		mov	dl,[Disk]	; DL <- disk to reset
		int	13h		; reset disk system
		pop	dx		; pop DX (head)
		pop	ax		; pop AX (number of sectors)
		jmp	short Read3	; next attempt

; ------------- Return old disk param table

ErrorLast:	xor	ax,ax		; AX <- 0
		mov	ds,ax		; DS <- 0
		pop	ax		; AX <- offset of old disk param table
		mov	[4*1Eh],ax	; pop offset of old disk param table
		pop	ax		; AX <- segmnet of old disk param table
		mov	[4*1Eh+2],ax	; pop segment of old disk param table

; ------------- ERROR: Display error message

		push	cs		; push CS
		pop	ds		; DS <- this segment
		mov	si,Message	; information message
NextChar:	cld			; set direction up
		lodsb			; AL <- load next character from DS:SI
		or	al,al		; AL == 0? (is it end of text?)
		jz	KeyPress	; end of text
		mov	ah,0eh		; AH <- function code		
		mov	bx,7		; BL <- color of text, BH <- page 0
		push	si		; push SI
		int	10h		; print character
		pop	si		; pop SI
		jmp	short NextChar	; next character

; ------------- ERROR: Waiting for a key

KeyPress:	mov	ah,0		; AH <- function code
		int	16h		; waiting for a key

; ------------- ERROR: Repeat booting

		int	19h		; repeat booting

; ------------- Align to sector size

		times 512 - 2 - ($ - Start) db	0

		dw	0aa55h		; Boot sector magic
	

Zaváděcí sektor je do paměti zaveden od adresy 0000:7C00h (tj. segment 0, offset 7C00h), na tuto adresu BIOS předá řízení. Zaváděcí sektor načte to paměti sektory počínaje sektorem 2, strana 0, stopa 0, tedy sektory následující za zaváděcím sektorem. Počet sektorů k načtení je dán položkou v záhlaví zaváděcího sektoru, tuto položku nastaví instalační program podle velikosti instalovaného souboru. Kromě počtu sektorů by měl instalační program nastavit ještě položku disku, ze kterého bude zavádění systému probíhat, počet hlav disku (u disket 2 strany) a počet sektorů na stopu.

Systém se načítá od segmentu 80h (uvedeného též v záhlaví sektoru). Starší verze DOS používaly segment 60h, ale z důvodu překryvu s daty BIOS začal být používán segment 70h. Při načítání sektorů z disku vyžaduje řadič DMA, aby buffer sektorů neležel přes hranici paměti 64 KB. Zaváděcí sektor zavádí systém po více sektorech, aby maximálně urychlil zavedení systému do paměti. Přitom řeší překryvy přes 64 KB volbou počtu načítaných sektorů. Neumí ale ošetřit případ, kdy jeden sektor leží přes hranici 64 KB. Z toho důvodu musí být počáteční zaváděcí segment násobkem 20h (tj. velikost sektoru vyjádřená v segmentech), vyhovující nejbližší vyšší segment je tedy 80h.

Aby zaváděcí sektor mohl zavést systém od segmentu 80h, musí se nejdříve přemístit na vrchol paměti, jinak by přepsal sám sebe načítanými daty. Velikost paměti systému (do rozsahu 640 KB) lze zjistit přímým čtením adresy 0000:0413. V tomto zaváděcím sektoru použijeme doporučený způsob - funkci INT 12h, ale v případě nedostatku místa lze přejít na přímé čtení paměti. Před vyvoláním funkce INT 12h musíme nejdříve inicializovat ukazatel zásobníku. Funkce INT 12h navrací v registru AX velikost paměti v KB do rozsahu 640 KB. Údaj převedeme na segmenty a posuneme počáteční adresu tak, aby konec přesunutého zaváděcího sektoru (se zachováním původních offsetů) dosáhl konce paměti. Poté přesuneme celý zaváděcí sektor na konec paměti a provedeme skok do kopie sektoru.

Abychom mohli provádět vícesektorové čtení z diskety, musíme upravit tabulku parametrů diskety - nastavit počet sektorů na stopu. BIOS při vícesektorovém čtení při dosažení posledního sektoru na stopě pokračuje načítáním sektorů z další hlavy. Budeme načítat data pouze z jedné strany, proto musíme nastavit počet sektorů stejný nebo větší než skutečný. Adresu tabulky diskových parametrů zjistíme z adresy vektoru INT 1Eh. Vytvoříme kopii tabulky, nastavíme adresu INT 1Eh na tuto kopii a upravíme parametry tabulky. Nesmíme si přitom zapomenout uchovat adresu původní tabulky abychom ji mohli později vrátit.

Po obvyklém resetu disku si připravíme ukazatele pro čtení (čítač sektorů, ukládací adresu, číslo sektoru, hlavy a strany) a můžeme načítat první sektory. Sektory budeme načítat po pokud možno velkých úsecích. Nejdříve počet sektorů omezíme na jednu stopu - tj. "poslední stopa - první stopa". Nezapomeňte, že sektory se počítají od 1 (do 63), zatímco hlavy a válce od 0. Po omezení počtu sektorů do konce stopy omezíme počet sektorů tak, aby buffer nepřekryl hranici 64 KB. Pro ten účel převedeme nejdříve cílový segment na offset (tj. vnitřní část 64 KB, horní 4 bity nás nezajímají). Postupně počítáme sektory a přičítáme velikost sektoru. V okamžiku přetečení víme, že konec sektoru dosáhl přesně hranice 64 KB (počáteční ukládací segment je násobkem velikosti sektoru) a příští sektor je již za touto hranicí.

Nyní již můžeme načíst skupinu sektorů. Nastane-li chyba, provedeme reset disku a pokusíme se o čtení znovu - zkusíme to 3x než ohlásíme chybu. Chyba čtení může být způsobena nejen vadným diskem, ale i výměnou diskety v mechanice - v tom případě funkce navrátí chybový kód 6, reset disku tento příznak vynuluje a následující čtení proběhne již úspěšně. V případě neúspěšného čtení ohlásíme chybu a po stisku klávesy předáme řízení opět zavaděči BIOS.

V případě úspěšného načtení provedeme v případě prvního sektoru systému (tj. ukládací adresa se doposud nezměnila) kontrolu sektoru podle magického slova, které jsme si uložili na začátek zaváděného systému (tedy přesněji za počáteční instrukci skoku). Tato minimální kontrola je velmi užitečná. Pokud zavedeme do paměti nesmyslná data a předáme jim řízení, může takový nesmyslný program způsobit mnoho škody včetně poškození hardware počítače.

Po načtení skupiny sektorů musíme posunout čítače a ukazatele. Počet sektorů odečteme od čítače sektorů, zvýšíme ukládací adresu a posuneme ukazatele čísla sektoru, hlavy a válce. Protože zavádíme systém od válce 0 a systém nebude mít nikdy více než 640 KB vystačíme si s počtem válců do 256, jinak bychom museli počítat s nejvyššími 2 bity čísla válce, které jsou ve stejném registru jako číslo sektoru. Takto můžeme v budoucnu zaváděcí sektor zdokonalit - nezavádět systém od válce 0, ale v záhlaví sektoru uchovat instalačním programem počáteční sektor, hlavu a válec a při zvyšování ukazatelů počítat s 10-bitovým číslem válce popř. s adresováním v LBA módu. To umožní použít zaváděcí sektor i jako vnitřní sektor v partition disku, která nezačíná na začátku disku.

Jsou-li všechny sektory systému zavedeny, navrátíme nejdříve původní tabulku diskových parametrů (vektor INT 1Eh) a poté předáme řízení na začátek zavedeného programu.

Nyní se budeme zabývat systémem, který necháme zavést. Pro první testy si připravíme miniaturní testovací program, který pouze vypíše hlášení. Vytvořte zdrojový soubor PROGRAM.ASM a přeložte jej 2 příkazy: "NASM16.EXE -o PROGRAM.BIN PROGRAM.ASM" a "NASM16.EXE -d DOS -o PROGRAM.COM PROGRAM.ASM".

; ----------------------------------------------------------------------------
;             Start of program at 0080:0000 (or CS:0100 if COM program)
; ----------------------------------------------------------------------------

SECTION		.text

%ifdef DOS
		org	100h
%else
		org	0
%endif

; ------------- Identification

Start:		jmp	Init

Ident		dw	8A25h		; identification word

; ------------- Display message

Init:		push	cs		; push CS
		pop	ds		; DS <- CS
		mov	si,Message	; message to display
NextChar:	cld			; set direction up
		lodsb			; AL <- load next character from DS:SI
		or	al,al		; AL == 0? (is it end of text?)
		jz	KeyPress	; end of text
		mov	ah,0eh		; AH <- function code		
		mov	bx,7		; BL <- color of text, BH <- page 0
		push	si		; push SI
		int	10h		; print character
		pop	si		; pop SI
		jmp	short NextChar	; next character

; ------------- Waiting for a key

KeyPress:	mov	ah,0		; AH <- function code
		int	16h		; waiting for a key

; ------------- Repeat booting/End program

%ifdef	DOS
		int	20h
%else
		int	19h		; repeat booting
%endif

; ------------- Message to display

Message		db	">>> Here I am! <<<",13,10,0

Jde skutečně o jednoduchý program. Po překladu vzniknou 2 soubory, PROGRAM.BIN a PROGRAM.COM. Soubor BIN je připraven pro isntalaci na disketu a soubor COM je DOS program, který můžete spustit k vyzkoušení funkce programu. Zdrojový text programu se přizpůsobuje BIN nebo COM verzi - počáteční adresa v paměti (0 nebo 100h) a způsob ukončení (INT 20h nebo INT 19h).

Začátek programu obsahuje magické slovo, které je kontrolováno zaváděcím sektorem. Poté program vypíše text a po stisku klávesy se ukončí (resp. opakuje zavádění systému).

Pro uložení souborů BOOT.BIN a PROGRAM.BIN si vytvoříme instalační program. Jeho zdrojový kód INSTALL.ASM následuje, program přeložíte příkazem "NASM16.EXE -o INSTALL.COM INSTALL.ASM".

; ------------- Setup parameters

DISK		EQU	0		; booting disk (0=diskette A:)
HEADS		EQU	2		; number of heads
SECTORS		EQU	18		; number of sectors per track
DESTSEGM	EQU	80h		; destination segment

; ------------- Start of program

SECTION		.text

		org	100h		; start of COM program

; ------------- Prepare address of disk buffer (cannot overlap 64 KB boundary)

Start:		mov	ax,ds		; AX <- program segment
		shl	ax,1
		shl	ax,1
		shl	ax,1
		shl	ax,1		; AX * 16
		add	ax,[Sector]	; add current buffer offset
		add	ax,200h		; test buffer overlapping
		jnc	BufferOK	; buffer is OK
		mov	ax,[Sector]	; AX <- current buffer address
		add	ax,200h		; move over boundary
		mov	[Sector],ax	; new buffer address

; ------------- Open file with boot sector

BufferOK:	mov	ax,3d00h	; AX <- function (open for reading)
		mov	dx,Filename	; DX <- name of file with boot sector
		int	21h		; open file for reading
		jnc	OpenOK		; file open OK

; ------------- Error - file not found

		mov	dx,FoundErr	; DX <- error message
Error:		mov	ah,9		; AH <- function code
		int	21h		; display error message
		int	20h		; end of program

; ------------- Read file into memory (AX=file identifier)

OpenOK: 	mov	bx,ax		; BX <- file identifier
		mov	cx,512		; CX <- length of boot sector
		mov	dx,[Sector]	; DX <- buffer for reading sector
		mov	ah,3fh		; AH <- function code
		int	21h		; read sector into memory

; ------------- Close file

		mov	ah,3eh		; AH <- function code
		int	21h		; close file

; ------------- Displays prompt text for user

		mov	ah,9		; AH <- function code
		mov	dx,Message	; DX <- message to display
		int	21h		; display message

; ------------- Waiting for a key

		mov	ax,0c08h	; AX <- function code
		int	21h		; waiting for a key
		cmp	al,27		; is it Esc key?
		jne	InitDisk	; it is not Esc, start write
		int	20h		; end of program

; ------------- Display message - Writing sector

InitDisk:	mov	ah,9		; AH <- function code
		mov	dx,StartText	; DX <- text to display
		int	21h		; display message

; ------------- Open file with program

		mov	ax,3d00h	; AX <- function (open for reading)
		mov	dx,Filename2	; DX <- name of file with boot sector
		int	21h		; open file for reading
		mov	dx,FoundErr2	; DX <- error message
		jc	Error		; error - file not found
		mov	bx,ax		; BX <- file identifier

; ------------- Determine file size
		
		mov	ax,4202h	; AX <- function (seek to end of file)
		xor	cx,cx		; CX <- 0 offset HIGH
		xor	dx,dx		; DX <- 0 offset LOW
		int	21h		; determine file size -> DX:AX

; ------------- Convert file size to number of sectors (multiple of 512 Bytes)

		add	ax,511		; round up to nearest sector
		adc	dx,0		; overflow
		mov	al,ah		; AL <- file size / 256 (LOW)
		mov	ah,dl		; AH <- file size / 256 (HIGH)
		shr	ax,1		; AX = file size in sectors
		mov	si,[Sector]	; SI <- buffer

; ------------- Filling up setup parameters

		mov	[si+3],ax	; number of sectors to read
		mov	byte [si+5],DISK ; booting disk
		mov	byte [si+6],HEADS ; number of heads
		mov     byte [si+7],SECTORS ; number of sectors per track
		mov	word [si+8],DESTSEGM ; destination segment

; ------------- Write boot sector

		call	Write		; write boot sector

; ------------- Reset file pointer

		push	ax		; push AX
		mov	ax,4200h	; AH <- function (seek to begin of file)
		xor	cx,cx		; CX <- 0 offset HIGH
		xor	dx,dx		; DX <- 0 offset LOW
		int	21h		; reset file pointer
		pop	ax		; pop AX

; ------------- Read next sector of program

CopyProg:	push	ax		; push AX (number of sectors)
		mov	cx,512		; CX <- length of boot sector
		mov	dx,[Sector]	; DX <- buffer for reading sector
		mov	ah,3fh		; AH <- function code
		int	21h		; read sector into memory
		pop	ax		; pop AX (number of sectors)

; ------------- Write sector of program

		call	Write		; write sector of program
		dec	ax		; number of sectors
		jnz	CopyProg	; copy next sector of program

; ------------- Close file

		mov	ah,3eh		; AH <- function code
		int	21h		; close file

; ------------- All OK

		mov	ah,9		; AH <- function code
		mov	dx,AllOKText	; DX <- message "All OK"
		int	21h		; display message
		int	20h		; end of program

; ----------------------------------------------------------------------------
;                   Procedure - write 1 sector
; ----------------------------------------------------------------------------

; ------------- Push registers

Write:		push	ax		; push AX
		push	bx		; push BX
		push	cx		; push CX
		push	dx		; push DX
		push	si		; push SI
		
; ------------- Prepare registers

		mov	si,3		; number of attempts
WriteAgain:	mov	cl,[WriteSector] ; CL <- write sector
		mov	dh,[WriteHead]	; DH <- write head
		mov	ch,[WriteTrack]	; CH <- write track
		mov	dl,DISK		; DL <- disk
		mov	bx,[Sector]	; BX <- buffer with sector
		mov	ax,301h		; AH <- function, AL <- num. of sectors
		push	ds		; push DS to stack
		pop	es		; ES <- DS data segment
		push	si		; push attempt counter
		int	13h		; write sector
		pop	si		; pop attempt counter
		jnc	Write2		; operation OK

; ------------- Error - reset disk and try again (maybe disk change)

		mov	ah,0		; AH <- function code
		int	13h		; reset disk system
		dec	si		; attempt counter
		jnz	WriteAgain	; next attempt

; ------------- Error - cannot write to a floppy

		mov	ah,9		; AH <- function code
		mov	dx,WriteErr	; DX <- error message
		int	21h		; display error message
		add	sp,6*2		; delete registers and return address
		int	20h		; end of program

; ------------- Shift write pointers

Write2:		mov	al,[WriteSector] ; AL <- write sector
		inc	ax		; increase sector number
		cmp	al,SECTORS	; is it valid sector?
		jbe	Write4		; it is valid sector
		mov	al,1		; AL <- 1 new sector number
		mov	ah,[WriteHead]	; AH <- write head
		inc	ah		; increase head number
		cmp	ah,HEADS	; is it valid head?
		jb	Write3		; it is valid head
		mov	ah,0		; AH <- 0 new head number
		inc	byte [WriteTrack] ; new track number
Write3:		mov	[WriteHead],ah	; new write head
Write4:		mov	[WriteSector],al ; new write sector

; ------------- Pop registers

		pop	si		; pop SI
		pop	dx		; pop DX
		pop	cx		; pop CX
		pop	bx		; pop BX
		pop	ax		; pop AX
		ret

; ------------- Messages

FoundErr	db	"ERROR: File BOOT.BIN not found!",13,10,"$"
FoundErr2	db	"ERROR: File PROGRAM.BIN not found!",13,10,"$"
WriteErr	db	"ERROR: Cannot write to disk!",13,10,"$"

Message		db	"Insert formated disk into A: and press",13,10
		db	"any key to continue or Esc to abort...",13,10,"$"

StartText	db	"Writing sector...",13,10,"$"

AllOKText	db	"All OK",13,10,"$"

; ------------- Write pointers

WriteSector	db	1		; write sector
WriteHead	db	0		; write head
WriteTrack	db	0		; write track

; ------------- Files

Filename	db	"BOOT.BIN",0
Filename2	db	"PROGRAM.BIN",0

; ------------- Buffer of boot sector

Sector		dw	Buffer
Buffer:

Program INSTALL.COM, který po překladu vznikne, obsahuje v záhlaví několik konstant, které jsou ukládány do záhlaví zaváděcího sektoru. Použijeme-li disketu 1.44 MB, nemusíme tyto konstanty měnit.

Na začátku programu si opět musíme připravit adresu diskového bufferu tak, aby nepřesáhl přes hranici 64 KB paměti. Po přípravě bufferu otevřeme soubor BOOT.BIN a načteme ho do bufferu. Následuje výzva k uživateli a po stisku libovolné klávesy program pokračuje, v případě stisku klávesy Esc se ukončí.

Do záhlaví zaváděcího sektoru potřebujeme uložit počet sektorů, které mají být zavedeny. Musíme proto nejdříve zjistit velikost zaváděného programu. Otevřeme soubor PROGRAM.BIN a vystavením ukazatele na konec zjistíme velikost souboru. Navrácený údaj zaokrouhlíme nahoru na celý počet sektorů (přičtením čísla 511, tj. velikost sektoru - 1) a vydělením číslem 512 zjistíme počet sektorů, které musí zaváděcí sektor načíst. Počet sektorů spolu s ostatními údaji uložíme do záhlaví zaváděcího sektoru. Nakonec zaváděcí sektor zapíšeme na disk.

Po resetu ukazatele v souboru PROGRAM.BIN opět na začátek provedeme kopii dat ze souboru na cílový disk - soubor načítáme po 512 bajtech do bufferu sektoru a ihned ukládáme. Při instalaci oželíme nižší rychlost zápisu způsobenou jednosektorovým zápisem. Je-li vše v pořádku, uzavřeme soubor a ukončíme program.

Funkce pro zápis sektoru na disk používá ukazatele operace v proměnných na konci programu. Po načtení proměnných do registrů se provede zápis sektoru. V případě neúspěchu se provedou celkem 3 pokusy a poté se program ukončí s chybovým hlášením. Je-li zápis úspěšný, zvýší se ukazatele operace. Nepočítá se s instalací systému do partition disku, vystačí se proto se zjednodušeným adresováním s 256 válci (ignorují se nejvyšší 2 bity adresy válce, které jsou ve stejném registru jako číslo sektoru).

Download zdrojových textů lineárního zaváděcího sektoru (6 KB).

Zpět na zavaděče systému