Elektroda.pl
Elektroda.pl
X
Proszę, dodaj wyjątek www.elektroda.pl do Adblock.
Dzięki temu, że oglądasz reklamy, wspierasz portal i użytkowników.

Pisanie systemu operacyjnego.

tomek_programista 20 Mar 2010 17:19 2826 7
  • #1 20 Mar 2010 17:19
    tomek_programista
    Poziom 19  

    Witam
    Zacząłem pisać swój własny system operacyjny.
    Pierwszym krokiem było napisanie bootloadera.
    Zrobiłem wszystko według tego kursu: osprogramming.
    Niestety przy wpisywaniu komendy "copyboot hang.bin 0" program wywala mi

    Code:

    Zimmermann Boot Sector Copy  Version 1.00
    Copyright (C) Marc Zimmermann, 1994.  All rights reserved.

    Syntax :  COPYBOOT drive filespec option

    Options:  /R  Read boot sector and save to file.
              /W  Write boot sector from file.

    , a na dyskietce nic się nie zapisuje.
    Co robię źle?

    0 7
  • #3 20 Mar 2010 18:42
    tomek_programista
    Poziom 19  

    Teraz wyskakuje

    Code:


    Zimmermann Boot Sector Copy  Version 1.00
    Copyright (C) Marc Zimmermann, 1994.  All rights reserved.

    No disk drive specified!


    Flopa mam pod literom 'a';

    Dodano po 6 [minuty]:

    Wpisałem to:
    Code:

    copyboot /w boot.bin 0 a:

    Ale teraz wyskakuje mi taki komunikat:
    Code:

    Zimmermann Boot Sector Copy  Version 1.00
    Copyright (C) Marc Zimmermann, 1994.  All rights reserved.

    Unable to open disk file!

    0
  • #4 20 Mar 2010 19:14
    arnoldziq
    Moderator Programowanie

    Spróbuj zrobić dokładnie tak jak w opisie użycia tego programu :

    Code:
    COPYBOOT drive filespec option 

    Czyli coś takiego :
    Code:
    copyboot a: boot.bin /w 

    0
  • #5 20 Mar 2010 19:53
    tomek_programista
    Poziom 19  

    Udało się, działa. :D
    Teraz pisze tego:
    Link
    Niestety nie wiem, jak go poskładać, bo nie znam asemblera.
    Jeśli ktoś miał by czas i pomógł mi go poskładać, to bardzo dziękuje.

    0
  • #6 20 Mar 2010 20:10
    Urgon
    Poziom 36  

    AVE...

    Moja rada dla Ciebie: naucz się assemblera. Bez tego nie zrobisz bootloadera. Sensownego kernela też nie da się zrobić bez przynajmniej wstawek assemblerowych. Serio, są pewne rzeczy, których nie przeskoczysz. Wiem, że to trudne i żmudne, ale naprawdę najpierw trza się nauczyć chodzić, by móc biegać, jak mówi przysłowie...

    0
  • #7 20 Mar 2010 21:47
    Dżyszla
    Poziom 42  

    Tomku, nie chcę Cię demotywować, ale skoro nawet nie umiesz zastosować się do składni polecenia, przeczytać komunikatu, to odpuść sobie na jakiś czas zapał do pisania systemu. Można zrobić wiele, bardzo prostych, a przydatnych programików, ułatwić sobie codzienne obowiązki. Zacznij od tego. Potem przejdź do nauki assemblera, zrozum, jak powstaje kod procesora, zajmij się optymalizacją wydajnościową w swoim ulubionym kompilatorze podglądając wynikowy kod procesorowy. W ten sposób lepiej zrozumiesz i nieco się jeszcze poduczysz. Potem możesz zacząć myśleć o OSie. Jeśli jeszcze nie stwierdzisz do tego czasu, że lepiej będzie zrobić coś, na czym skorzystać by mogli wszyscy.

    0
  • #8 27 Mar 2010 17:11
    tomek_programista
    Poziom 19  

    Poskładałem to.

    Code:

    [BITS 16]
    [ORG 0000h]

    jmp     START
         
         OEM_ID                db "TRAIN-OS"
         BytesPerSector        dw 0x0200
         SectorsPerCluster     db 0x01
         ReservedSectors       dw 0x0001
         TotalFATs             db 0x02
         MaxRootEntries        dw 0x00E0
         TotalSectorsSmall     dw 0x0B40
         MediaDescriptor       db 0xF0
         SectorsPerFAT         dw 0x0009
         SectorsPerTrack       dw 0x0012
         NumHeads              dw 0x0002
         HiddenSectors         dd 0x00000000
         TotalSectorsLarge     dd 0x00000000
         DriveNumber           db 0x00
         Flags                 db 0x00
         Signature             db 0x29
         VolumeID              dd 0xFFFFFFFF
         VolumeLabel           db "QUASI  BOOT"
         SystemID              db "FAT12   "
         

    START:
         cli
         mov     ax, 0x07C0
         mov     ds, ax
         mov     es, ax
         mov     fs, ax
         mov     gs, ax
         mov     ax, 0x0000
         mov     ss, ax
         mov     sp, 0xFFFF
         sti
         xor     cx, cx
         xor     dx, dx
         mov     ax, 0x0020                     ; 32 bajtowy opis katalogu
         mul     WORD [MaxRootEntries]          ; liczba pozycji w katalogu glownym
         div     WORD [BytesPerSector]          ; bajty na sektor
         xchg    ax, cx




         ; w cx znajduje się teraz wielkość katalogu głownego
         ; oblicza polozenie root directory i zapisuje w 'ax'
              mov     al, BYTE [TotalFATs]           ; liczba tablic FAT
         ; liczba sektorow uzywanych przez tablice FAT
         mul     WORD [SectorsPerFAT]
         add     ax, WORD [ReservedSectors]     ; adjust na bootsektor
         mov     WORD [datasector], ax          ; base of root directory
         add     WORD [datasector], cx
         
         ; odczytaj root directory do pamieci pod adres (7C00:0200)
         ; skopiuj root dir nad kodem bootloadera
         mov     bx, 0x0200                     
         call    ReadSectors
         mov     cx, WORD [MaxRootEntries]      ; maksymalna liczba plikow to 224
                                                     ; i tyle razy może wykonywać się
                                                     ; nasza pętla
              mov     di, 0x0200                     ; pod tym adresem znajduje się
                                                     ; pierwszy wpis w katalogu głównym
         .LOOP:
              push    cx
              mov     cx, 0x000B                     ; nazwa pliku z rozsz. ma Bh znakow
              mov     si, ImageName                  ; nazwa pliku z jadrem
              push    di
              rep     cmpsb                          ; sprawdza czy nazwa naszego pliku
                                                     ; zgadza się z nazwą znajdującą się w
                                                     ; aktualnym wpisie w katalogu głównym
              pop     di
              je      LOAD_FAT                       ; znaleziono plik, wyjdź z pętli
              pop     cx 
              add     di, 0x0020                     ; przestaw na nastepny wpis
                                                     ; (każdy wpis ma 32 bajty (20h))
              loop    .LOOP                          ; w tym obiegu nie znaleziono pliku,
                                                     ; próbujemy szukać dalej
              jmp     FAILURE                        ; jeżeli na dysku nie ma pliku z jądrem
      LOAD_FAT:
         ; zapisz poczatkowy klaster pliku w fat
              mov     dx, WORD [di + 0x001A]         ; na przesunięciu 1Ah we wpisie katalogu
         ; znajduję się adres pierwszego klastra pliku w fat
              mov     WORD [cluster], dx             ; adres ten zapisujemy w zmiennej klaster
         ; obliczamy rozmiar tablicy FAT i zapisujemy go w rejestrze cx
              xor     ax, ax
              mov     al, BYTE [TotalFATs]           ; liczba tablic FAT
              mul     WORD [SectorsPerFAT]           ; liczba sektorow uzywanych przez FAT
              mov     cx, ax
         ; obliczamy lokalizacje fat na dyskietce i zapisujemy ją w ax
              mov     ax, WORD [ReservedSectors]       
         ; read FAT into memory
              mov     bx, 0x0200                         
              call    ReadSectors
    ; plik załadujemy pod adres es:bx (0100:0000)
              mov     ax, 0x0100                       
              mov     es, ax
              mov     bx, 0x0000                     
              push    bx
         
         LOAD_IMAGE:
              mov     ax, WORD [cluster]           ; klaster do odczytu
              pop     bx                           ; adres pod który będziemy zapisywać plik
              call    ClusterLBA                   ; zamień numer klastra na postac LBA
              xor     cx, cx
              mov     cl, BYTE [SectorsPerCluster] ; liczba sektorów do odczytu
              call    ReadSectors
              push    bx
              ;oblicz adres nastepnego klastra
              mov     ax, WORD [cluster]           ; bieżący klaster
              mov     cx, ax                             
              mov     dx, ax                             
              shr     dx, 0x0001                         
              add     cx, dx                       ; wartość 3/2
              mov     bx, 0x0200                   ; miejsce w pamięci z FAT
              add     bx, cx                       ; dodaj do niego obliczony offset
              mov     dx, WORD [bx]                ; odczytaj 2 bajty
              ; potrzebujemy wartości o rozmiarze 3/2 bajta, najpierw sprawdzamy parzystość
              test    ax, 0x0001                         
              jnz     .ODD_CLUSTER
         .EVEN_CLUSTER:
              and     dx, 0000111111111111b        ; pobierz 12 dolnych bitów
             jmp     .DONE
         .ODD_CLUSTER:
              shr     dx, 0x0004                   ; pobierz 12 górnych bitów
         .DONE:
              mov     WORD [cluster], dx           ; zapisz numer nowego klastra
              cmp     dx, 0x0FF0                   ; sprawdz czy to koniec pliku
              jb      LOAD_IMAGE                   ; jezeli nie to skocz do poczatku petli
     DONE:
              push    WORD 0x0100
              push    WORD 0x0000
              retf
     FAILURE:
              mov     ah,00h
              int     16h         ; zaczekaj na wciśnięcie klawisz a                           
              jmp 0FFFFh:0000h
    TIMES 510-($-$$) DB 0
    DW 0xAA55
    ImageName   db "KERNEL  BIN"        ; nazwa pliku z kernelem
         msgWelcome  db 0x0D, 0x0A, "Witaj w bootloaderze.", 0x0D, 0x0A, 0x00     
         msgLoading  db "Trwa ladowanie systemu... ", 0x0D, 0x0A, 0x00
         msgFailure  db "ERROR : Nacisnij cos aby zresetowac...", 0x00
    ClusterLBA:
        sub     ax, 0x0002
        xor     cx, cx
        mov     cl, BYTE [SectorsPerCluster]       
        mul     cx
        add     ax, WORD [datasector]  ; datasector - adres glownego obszaru danych
     ret
    ReadSectors:
         .MAIN
              push    ax
              push    bx
              push    cx
              call    LBACHS
              mov     ah, 02h                             
              mov     al, 01h                           ; czytamy jeden sektor
              mov     ch, BYTE [absoluteTrack]          ; ścieżka
              mov     cl, BYTE [absoluteSector]         ; sektor
              mov     dh, BYTE [absoluteHead]           ; głowica
              mov     dl, BYTE [DriveNumber]            ; dysk
              int     13h                             
              pop     cx
              pop     bx
              pop     ax
              ; przygotuj adres do odczytu następnego sektora
              add     bx, WORD [BytesPerSector]           
              inc     ax                      ; numer kolejnego sektora do odczytu
              loop    .MAIN                             ; odczytaj następny sektor
              ret
    LBACHS:
              xor     dx, dx                            ; prepare dx:ax for operation
              div     WORD [SectorsPerTrack]            ; calculate
              inc     dl                                ; adjust for sector 0
              mov     BYTE [absoluteSector], dl
              xor     dx, dx                            ; prepare dx:ax for operation
              div     WORD [NumHeads]                   ; calculate
              mov     BYTE [absoluteHead], dl
              mov     BYTE [absoluteTrack], al
              ret
    absoluteSector db 0x00
         absoluteHead   db 0x00
         absoluteTrack  db 0x00
    datasector  dw 0x0000
    cluster  dw 0x0000

    Niestety nie działa tak jak powinien.
    A ja nie wiem dla czego.
    Jeśli ktoś ma jakiś pomysł dla dlaczego, to proszę pisać.

    0