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).