Testovací zaváděcí sektor
Testovací zaváděcí sektor je prvním nejjednodušším pokusem při zavádění systému. Slouží k vyzkoušení základních principů zavedení sektoru do paměti, jeho spuštění a také způsobu jak takový sektor uložit na disketu.
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 sectorStart: jmp Init ; jump to starting routine Message db "My system loaded OK!",13,10 db "Press any key...",13,10,0 ; ------------- Init stack (lies below beginning of the boot sector) Init: cli ; disable interrupts xor ax,ax ; AX <- 0 mov ds,ax ; DS <- 0 this segment mov ss,ax ; SS <- 0 mov sp,7C00h ; SP <- end of stack sti ; enable interrupts ; ------------- Display information message 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 int 10h ; print character jmp short NextChar ; next character ; ------------- Waiting for a key KeyPress: mov ah,0 ; AH <- function code int 16h ; waiting for a key ; ------------- Continue booting with next device int 19h ; continue 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í. Podmínkou platnosti zaváděcího sektoru je, že musí končit magickým slovem 0AA55h, jinak ho BIOS ignoruje a pokračuje v zavádění systému z dalšího zařízení. Další podmínkou, kterou mnoho BIOSů (a také MBR sektorů) testuje, je instrukce JMP na začátku zaváděcího sektoru - buď se musí jednat o instrukci JMP NEAR (3 bajty) nebo instrukci JMP SHORT (2 bajty) následovanou instrukcí NOP (1 bajt).
Prvním úkonem, který by měl zaváděcí sektor vždy provést, je nastavení ukazatele zásobníku. Přestože instrukce "mov ss,ax" zajistí přechodný zákaz přerušení pro následující instrukci "mov sp,7C00h" je obvyklé zakázat přerušení během operace ještě explicitně.
Druhou operací, kterou testovací zaváděcí sektor provádí, je výpis informačního textu. Text se načítá po znacích z ukazatele DS:SI (až po koncový bajt 0) a zobrazuje se na displeji pomocí BIOS služby INT 10h. Po zobrazení informačního textu čeká zavaděč na stisk klávesy a poté pokračuje opakováním zavádění systému pomocí přerušení INT 19h. Není-li disketa vyjmuta, znovu dojde k zavedení tohoto sektoru, jinak BIOS pokračuje dalšími diskovými jednotkami.
Zaváděcí sektor je zakončen makrem, které zajistí vyplnění zbytku sektoru až do 510 bajtů. Za vyplňovacím prostorem je magické slovo 0AA55h, které BIOS kontroluje po načtení zaváděcího sektoru do paměti.
Po překladu zaváděcího sektoru vznikne soubor BOOT.BIN, který musí být velký 512 bajtů. Tento soubor je nyní potřeba zapsat do prvního sektoru diskety v mechanice A:. Musí být použita zformátovaná disketa, na její velikosti ani souborovém systému nezáleží. K zápisu sektoru na disketu vytvořte zdrojový soubor INSTALL.ASM, který přeložíte příkazem "NASM16.EXE -o INSTALL.COM INSTALL.ASM".
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 code (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 ah,9 ; AH <- function code
mov dx,FoundErr ; DX <- error message
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
; ------------- Write boot sector
mov si,3 ; number of attempts
WriteAgain: push si ; push attempt counter
mov ax,301h ; AH <- function, AL <- num. of sectors
mov cx,1 ; CH <- cylinder, CL <- sector
xor dx,dx ; DH <- 0 head, DL <- 0 disk A:
mov bx,[Sector] ; BX <- buffer with sector
push ds ; push DS to stack
pop es ; ES <- DS
int 13h ; write BOOT sector
pop si ; pop attempt counter
jnc WriteOK ; operation OK
; ------------- Reset of disk (e.g. disk change report)
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
WriteOK: int 20h ; end of program
; ------------- Messages
FoundErr db "ERROR: File BOOT.BIN not found!",13,10,"$"
WriteErr db "ERROR: Cannot write to disk!",13,10,"$"
Message db "Insert disk into A: and press any",13,10
db "key to continue or Esc to abort...",13,10,"$"
StartText db "Writing sector...",13,10,"$"
; ------------- File with boot sector
Filename db "BOOT.BIN",0
; ------------- Buffer of boot sector
Sector dw Buffer
Buffer:
Program INSTALL.COM je určený pro operační systém DOS nebo Windows. Sektor je na disketu zapisován BIOS funkcí INT 13h. Z důvodu architektury řadiče DMA je nutné, aby sektor neležel na hranici 64 KB absolutní adresy paměti. Z toho důvodu je na začátku programu korigována adresa bufferu, do kterého bude zaváděcí sektor načten - pokud absolutní adresa přetéká přes 64 KB, použije se následující adresa.
Další část programu zajistí otevření souboru BOOT.BIN pro čtení, jeho načtení do bufferu a poté uzavření souboru. Následuje zobrazení výzvy uživateli a čekání na klávesu - při stusku klávesy Esc je program přerušen, jinak pokračuje zápisem sektoru na disketu. Při zápisu sektoru je použita BIOS funkce INT 13h. Pokud operace zápisu neproběhne úspěšně, provede se reset disku a zápis se opakuje, to celkem 3x než se ohlásí chyba. Důvodem k opakování zápisu může být nejen vadný disk (příp. aktivovaná ochrana proti zápisu na disketu), ale i výměna diskety (návratový kód 6) - v tom případě je resetem diskety příznak výměny nulován a následující zápis proběhne již úspěšně.
Download zdrojových textů testovacího zaváděcího sektoru.