Ładowanie pliku - FAT16

Odpowiedz Nowy wątek
2013-02-25 16:25
0

Pisze bootloader z obsługą FAT16.
Ma załadować jakiś plik i skoczyć do niego.
Dlaczego bootloader nie może znaleźć pliku z jądrem ???

org 0x7C00

mov si, M4
call print

    jmp start
    OEM_Name                    db  "MyOperatingSystem" ; nazwa systemu
    BytesPerSector              dw   0x0200 ; bajtow na sektor - 512
    SectorsPerCluster               db  0x04    ; sektorow na klaster - 4
    ReservedSectors             dw  0x0001  ; zarezerwowanych sektorow - 1
    FATCopies                   db  0x02        ; liczba kopii FAT - 2
    MaxRootDirEntries               dw  0x0200  ; liczba wpisow w katalogu glownym - 512
    NumberOfSectorsSmall        dw   0xFFF0 ; liczba sektorow dla malych partycji - 65520
    MediaDescriptor         db  0xF8        ; F8 - dysk twardy, F0 - dyskietka - 248
    SectorsPerFAT           dw   0x0040 ; liczba sektorow przypadajacych na jedna FAT - 64
    SectorsPerTrack         dw   0x0020 ; liczba sciezek - 32
    NumberOfHeads           dw   0x0040 ; liczba glowic - 64
    HiddenSectors           dd  0x00000000  ; liczba ukrytych sektorow - 0
    NumberSectorsHuge       dd  0x00000000  ; Liczba sektorow dla duzych dyskow 
                                                                        ;(NumberOfSectorsSmall jakby nie styklo) - 0
    LogicalDriveNumber      dw  0x0080  ; numer napedu - 128
    ExtendedSignature       db  0x29        ; sygnaturka - 41
    SerialNumber            dd  0x5678D47D; numer seryjny - 5667028
    VolumeName          db  "CursedOS   "; etykietka
    FATName             db  "FAT16   "  ; nazwa wersji fata

print:                  ; Funkcja sluzy wyswietlaniu
 .pisz:
    lodsb   
    or  al, al
    jz  .napisalem
    mov ah, 0x0E
    int 0x10
    jmp .pisz
 .napisalem:
    ret

start:      ; tu zaczynamy impreze
    cli                 ; wylaczamy obsluge przerwan - bedziemy ustawiac rejestry segmentowe
    push    word 0x0000     ; adres do naszego wykorzystania - OD - 0
    pop ss                  ; ustawiamy tam segment stosu
    push    word 0xFFF0     ; a wielkosc ustawiamy na najwieksza - DO - 65520
    pop sp                  ; ustawiamy wskażnik stosu
    mov ax, cs              ; tak
    mov ds, ax
    mov es, ax              ; ladujemy do dwoch rejestrow segmentowych
    mov fs, ax
    mov gs, ax
    sti                     ; i odpalamy obsluge przerwan

; W tym miejscu za pomoca przerwania 13h i funkcji 0x08h pobierzemy dane o dysku i zapiszemy je w pamieci
    mov ah, 0x08                        ; funkcja 0x08h przerwania numer 13
    mov dl, byte [LogicalDriveNumber]   ; numer dysku
    int 13h                             ; wywolanie przerwan

; te zamotanie to dlatego ze z byte musialem word zrobic                  
    inc ch                      ; zwiekszamy ch o 1
    xor ax, ax                  ; zerojemy AX
    mov al, ch                  ; przenosimy wartosc ch do al
    mov word [maxTrack], ax     ; wrzucamy tutaj parametry - ???
    inc dh                      ;
    mov al, dh                  ;
    mov word [maxHead], ax      ;
    mov al, cl                  ;
    mov word [maxSector], ax    ;

; Obliczamy wielkosc Root Directory i zapisujemy w CX zeby pasowalo do funkcji ReadSectors
    mov ax, 0x0020                  ; 32-bajtowy opis kazdego pliku w katalogu
    xor dx, dx                      ; czyscimy DX (DX:AX mul costam)
    mul word [MaxRootDirEntries]    ; mnozymy przez maksymalna liczbe wpisow otrzymujac wielkosc :)
    div word [BytesPerSector]       ; i dzielimy przez liczbe bajtow na sektor otrzymujac ilosc sektorow ktore to zajmuje
    xchg ax, cx                     ; wsadzamy do cx wartosc ax -  wymienia zawartości operandów między sobą

; Obliczamy polozenie Root Directory i zapisujemy w AX z tego samego powodu co wyzej ;)
    mov ax, word [SectorsPerFAT]    ; wrzucamy liczbe sektorow na jedna tablice FAT
    xor dx, dx                      ; zerowanie dx
    mul word [FATCopies]            ; mnozymy przez liczbe tablic FAT
    add ax, word [ReservedSectors]  ; dodajemy liczbe sektorow
    mov word [DataSector], ax       ; zapisujemy to w pamieci
    add word [DataSector], cx       ; i dodajemy wielkosc root dir otrzymujac poczatek sekcji z danymi

; Odczytujemy ten sztycht
    mov bx, 0x7E00          ; odczytujemy po 512 bajtow wiec zaczynamy impreze od 0x0000:0x7E00 (obszar zaraz za bootloaderem)
    call ReadSectors

; Tutaj zaczynamy szukac naszego pliku i sprawdzac czy wogole on tam jest
    mov cx, word [MaxRootDirEntries]    ; bedziemy odczytywac nie wiecej razy niz jest mozliwe. W CX jest licznik dla instrukcji loop
    xor di, di
    mov di, 0x7E00                      ; adres poczatku obszaru przeszukiwanego
    xor si, si
    mov si, KernelName                  ; adres nazwy do wyszukania

SearchForKernel:
    push cx                 ; zeby nam czasem licznik sie nie zepsul
    mov cx, 0xB             ; 11 znakow ma kernelek
    push di                 ; di / si jest zmieniane przez cmpsb to trzeba zachowac
    push si
    rep cmpsb               ; sprawdz ten sztycht - Opis : Porównuje bajt o adresie DS:SI lub DS:ESI z bajtem o adresie ES:DI lub ES:EDI 
                            ; i w zależności od wyniku ustawia odpowiednie flagi (takie same jak CMP ). 
                            ; Następnie, w zależności od DF (destination flag, wskaźnika kierunku) zmniejsza (gdy DF=1) lub zwiększa (gdy DF=0) SI i DI (lub ESI i EDI). 
    pop si                  ; polozylismy to podnosimy
    pop di

    je  LoadKernel          ; jesli nazwa pasuje to ladujemy kernela
    pop cx                  ; jesli nie to bierzemy licznik ktory schowalismy
    add di, 0x20            ; przestawiamy na nastepny wpis w RootDirectory (kazdy ma 32b)
    loop SearchForKernel    ; i patrzymy na nastepny
    jmp KernelNotFound      ; jesli nie ma no to skaczemy ze nie ma ;)

LoadKernel:

    mov si, M1
    call print

    mov ax, [di+0x1A]           ; na tej pozycji jest numer klastra gdzie lezy nasz kernelson
    mov word [cluster], ax      ; zapisujemy pierwszy klaster

; tutaj zaladujemy tablice FAT
    mov cx, word [SectorsPerFAT]    ; ladujemy do CX liczbe sektorow ktora zajmuje FAT
    mov ax, word [ReservedSectors]  ; a do ax poczatek
    mov bx, 0x7E00          ; ladujemy to zamiast wczesniej odczytanego RootDir - bo nam juz niepotrzebny
    call    ReadSectors

    push    word 0x0100         ; ustawiamy wartosc ES
    pop es

    mov ax, word [cluster]
    xor bx, bx              ; adres pod ktory wrzucamy (zaczynamy od 0x0100:0x0000)

FATLoop:
    call    ClusterToSector         ; zamieniamy numer klastra na adres
    mov cl, byte [SectorsPerCluster]    ; ilosc sektorow do odczytania
    call    ReadSectors         ; odczytujemy pierwszy sektor

    push    bx
    mov ax, word [cluster]
    shl ax, 1               ; mnozymy klaster razy 2 otrzymujac offset z ktorego odczytamy
    mov bx, ax              ; wrzucamy do bx
    mov ax, [bx+0x7E00]         ; odczytujemy wartosc z tablicy FAT
    mov word [cluster], ax      ; wrzucamy to do numeru klastra bez wzgledu na to co tam jest
    pop bx

    cmp ax, 0xFFFF          ; porownujemy wartosc odczytana, jesli jest 0xFFFF to znaczy ze to ostatni klaster pliku
    jne FATLoop             ; wiec jesli nie pasuje to czytamy nastepny

     mov si, M3
     call print

    jmp 0x0100:0x0000           ; i odpalamy odczytany kernel

KernelNotFound:

mov si, M2
call print

    jmp $

; --------
; Potrzebne funkcyjki
; --------

; --------
; ClusterToSector
; Funkcja przyjmuje numer klastra i przelicza go na adres pliku (w AX)
; --------

ClusterToSector:
    push    dx              ; kladziemy uzywane zmienne na stos
    push    cx
    sub ax, 2               ; odejmujemy 2
    xor dx, dx
    xor cx, cx
    mov cl, byte [SectorsPerCluster]    ; mnozymy przez liczbe sektorow na klaster
    mul cx
    add ax, word [DataSector]       ; i dodajemy miejsce poczatku sektora z danymi majac polozenie pliku
    pop cx
    pop dx              ; przywracamy zmienne
    ret

; --------
; SectorCHS - konwersja adresu w postaci numeru sektora liczac od poczatku na CHS (czyli cylinder head sector)
; Funkcja przyjmuje w rejestrze AX numer
; --------

SectorCHS:
    push    bx              ; kladziemy ax na stos
    push    ax
    xor bx, bx
    mov ax, word [maxSector]
    mul word [maxHead]
    xor dx, dx
    xchg    ax, bx              ; tu mamy obliczenie cylindra
    pop ax
    div bx
    mov byte [absoluteTrack], al
    mov ax, dx

    xor dx, dx              ; zerujemy do dzielenia. Dzielenie wyglada tak: (DX:AX div costam) stad musimy wyzerowac dx...
    div word [maxSector]        ; dzielimy przez maksymalna liczbe sektorow otrzymujac tym samym w ax numer glowicy a w dx sektor
    mov byte [absoluteHead], al     ; zapisujemy ;)
    inc dl
    mov byte [absoluteSector], dl
    pop bx
    ret                 ; i wracamy

;-------
; ReadSectors - odczytuje cx sektorow z dysku zaczynajac od ax pod adres es:bx
; Przyjmowane argumenty:
;   cx - liczba sektorow do odczytu
;   ax - poczatek obszaru do odczytu
;   es:bx - adres w pamieci pod ktory odbywa sie odczyt
;-------

ReadSectors:
    push    ax
    push    bx
    push    cx              ; zapisujemy je na stosie bo bedziemy zmieniac a sa nam potrzebne
    call    SectorCHS           ; zamieniamy adres na CHS
    mov ah, 0x02            ; czytanie sektorow z dysku
    mov al, 0x01            ; ilosc - 1
    mov ch, byte [absoluteTrack]    ; sciezka
    mov cl, byte [absoluteSector]   ; sektor
    mov dh, byte [absoluteHead]     ; glowica
    mov dl, byte [LogicalDriveNumber]   ; dysk
    int 13h             ; czytamy
    pop cx
    pop bx
    pop ax
    add bx, word [BytesPerSector]   ; przelaczamy sie na nastepny sektor
    inc ax
    loop    ReadSectors         ; i powtarzamy az sie nie skonczy ilosc sektorow do odczytania
    ret                 ; jesli koniec to wracamy

; -------
; Zmienne
; -------

absoluteTrack   db  0x00        ; sciezka (cylinder)
absoluteHead    db  0x00        ; glowica
absoluteSector  db  0x00        ; sektor
maxTrack    dw  0x0000
maxHead     dw  0x0000      ; miejsce na dane o nosniku
maxSector   dw  0x0000
DataSector  dw  0x0000      ; polozenie sektora z danymi (jego poczatku)
cluster     dw  0x0000

KernelName  db  "krenel.bin" ; nazwa szukanego pliku

M1 db "Ladowanie kernel'a...", 13, 10, 0
M2 db "Nie odnaleziono pliku...", 13, 10, 0
M3 db "Zaladowano poprawnie...", 13, 10, 0
M4 db "Szukam...", 13, 10, 0

times 510-($-$$) db 0x00
dw  0xAA55

Dodam jeszcze paczkę z plikami potrzebnymi po kompilacji

  • OS .rar (0,84 MB) - ściągnięć: 105

Jeśli mój post jest dowodem mojej niekompetencji, to trudno, ale po to pytam, żeby się czegoś dowiedzieć.
edytowany 2x, ostatnio: kacper546, 2013-02-25 16:37

Pozostało 580 znaków

2013-02-25 18:13
0

Dlatego że krenel.bin?

Pozostało 580 znaków

2013-02-25 18:32
0

Nie rozumiem ???
Chodzi Ci o nazwę - są takie same.


Jeśli mój post jest dowodem mojej niekompetencji, to trudno, ale po to pytam, żeby się czegoś dowiedzieć.
chodzi o prawdopodobną literówkę. - Azarien 2013-02-25 21:59

Pozostało 580 znaków

2013-02-25 18:33
0

Masz jakiekolwiek pojęcie o systemie FAT16?
Stricte - o tym, jak przechowywane są tam nazwy plików?


edytowany 1x, ostatnio: Patryk27, 2013-02-25 18:34

Pozostało 580 znaków

2013-02-25 20:27
0

Dopiero zacząłem naukę FAT16 więc mam pojęcie ogólne :).
Jeśli chodzi o kod to nie wiem gdzie jest błąd.


Jeśli mój post jest dowodem mojej niekompetencji, to trudno, ale po to pytam, żeby się czegoś dowiedzieć.

Pozostało 580 znaków

2013-02-26 06:46
1

nie wiem gdzie jest błąd.

Sprawdź, jak w FAT16 trzymane są nazwy plików...


Pozostało 580 znaków

2013-02-26 18:26
0

czy chodzi Ci o to że zamiast

KernelName db "krenel.bin" ; nazwa szukanego pliku
powinno być KernelName db "KRENEL BIN"


Jeśli mój post jest dowodem mojej niekompetencji, to trudno, ale po to pytam, żeby się czegoś dowiedzieć.

Pozostało 580 znaków

2013-02-26 18:29
1

Pomijając, że chyba masz na myśli plik kernel.bin, to w FAT (bez LFN (long file name)) jego nazwa brzmiałaby:
kernel bin (dwie spacje, bo cała nazwa pliku musi mieć 11 znaków (format 8+3)).
#Edit albo KERNEL BIN - dawno nie "bawiłem się" z FAT-em i nie wiem czy jest to zapisywane wielkimi, czy małymi literami.


edytowany 1x, ostatnio: Patryk27, 2013-02-26 18:40

Pozostało 580 znaków

2013-02-26 19:46
0

Spotkałem się z zapisem KERNEL BIN ale czytałem że FAT 16 nie rozróżnia wielkości liter i sprawdze ja dawałem tylko jedną spacje


Jeśli mój post jest dowodem mojej niekompetencji, to trudno, ale po to pytam, żeby się czegoś dowiedzieć.

Pozostało 580 znaków

2013-02-26 19:48
0

czytałem że FAT 16 nie rozróżnia wielkości liter

Zapewne chodzi o to, że Ty - jako programista - nie powinieneś zwracać uwagi na wielkość liter, a zapisane od środka może być nawet jako KeRnEL BIn.

ja dawałem tylko jedną spacje

Wtedy nazwa nie spełniałaby formatu 8+3 (8 znaków nazwy pliku, 3 znaki rozszerzenia).


Pozostało 580 znaków

2013-02-26 19:48
0

Niestety dalej nie znajduje pliku


Jeśli mój post jest dowodem mojej niekompetencji, to trudno, ale po to pytam, żeby się czegoś dowiedzieć.

Pozostało 580 znaków

Odpowiedz
Liczba odpowiedzi na stronę

1 użytkowników online, w tym zalogowanych: 0, gości: 1, botów: 0