[asm] OS - co zrobiłem źle

0

Czytając kurs ze strony: http://www.osprogramming.webpark.pl/part2.html
Zrobiłem jak tam pisało i... nie działa :( Co zrobiłem źle?
Kod:
boot.asm

[ORG 0h]
jmp 07C0h:start       
msg  DB 'Witaj w boot sektorze.', 13, 10, 0
start:
mov ax, 07C0h          
cli                      ; przed ustawianiem stosu w celach
                         ; bezpieczeństwa powinno się wyłączyć przerwania
mov ss, ax               ; ustawiamy segment stosu 
mov sp, 03FEh            ; i wskaźnik pokazujący na szczyt stosu
sti                      ; włączamy przerwania
push cs
pop ds                           
pop es         ; odrazu wykorzystamy stos iniciując nasze rejestry segmentowe

;funkcyjka wyswietlajaca napis(w niezbyt dobrym stylu)
mov si, msg
next_char: 
mov al, [si]
cmp al, 0
jz char_end
inc si
mov ah, 0eh
int 10h
jmp next_char
char_end:

mov ah, 02h             ; odczytaj sektor z dyskietki
mov al, 1               ; ile sektorow
mov ch, 0               ; numer sciezki
mov cl, 2               ; numer sektora
mov dh, 0               ; glowica
mov dl, 0               ; numer dysku
mov bx, 0800h  
mov es, bx  
mov bx, 0               ; odczytany sektor zapisujemy pod adresem 0800:0000h
int    13h              ; i z tak przygotowanymi danymi wywolujemy przerwanie
     
jmp     0800h:0000h        ; skok do kernela ktory przed chwila wczytalismy z dyskietki
times 510-($-$$) db 0      ; uzupelnienie pliku tak aby zawieral 510 bajtow
dw 0xAA55                ; sygnaturka (2 bajty), plik ma razem 512 bajtow (200h)

kernel.asm

[org 0x0000]
[bits 16]

[SEGMENT .text]
get_cmd:

mov BYTE [CmdSize],0  ; zerujemy zmienną przechowującą 
                      ; bieżącą liczbę znaków w buforze
mov di, UserCmd       ; wpisujemy do DI offset bufora na komende

get_cmd_start:              

mov ah,10h
int 16h               ; pobieramy znak z klawiatury

cmp al,0              ; al=0 gdy wciśnięty klawisz to klawisz rozszerzony
je get_cmd_start      ; jeżeli tak to wróć do początku,
                      ; jeżeli nie to przejdz dalej

cmp al,08h            ; sprawdź czy wciśnieto spację
je backspace_key      ; jeżeli tak to skocz do podprocedury obsługującej spację

cmp al,0dh            ; sprawdź czy wciśnięty klawisz to enter
                      ; (czyli koniec polecenia)
je enter_key          ; jeżeli tak to skocz do odpowiedniego miejsca

; pobrany znak to zwykły znak ascii

mov bh, [MaxLen]             
mov bl, [CmdSize]
cmp bl, bh            ; sprawdz czy nie osiągnięto max dozwolonej ilości znaków
je get_cmd_start      ; jeżeli tak to wróć do początku

space:
    mov ah, 0Eh    
    mov al, 20h    ; kod ascii spacji
    mov bh, 00h    ; strona graficzna
    mov bl, 07h    ; atrybuty tekstu
    int 10h        ; wywołanie przerwania
ret

next_line:
    mov ah, 0Eh        
    mov al, 0Dh
    mov bh, 00h
    mov bl, 07h
    int 10h
    mov ah, 0Eh
    mov al, 0Ah
    mov bh, 00h
    mov bl, 07h
    int 10h
ret

prompt:
    mov ah, 0Eh        
    mov al, 02h
    mov bh, 00h
    mov bl, 07h
    int 10h
ret

backspace_key:        ; jeżeli wciśnięto backspace...
mov bl,0
mov bh,[CmdSize]
cmp bh,bl             ; jeżeli w buforze nie ma nic, to znaczy,
je get_cmd_start      ; że nia ma czego usuwać, wróć więc do początku

; usuwamy ostatni znak i z bufora i z ekranu

dec BYTE [CmdSize]    ; zmniejsz licznik wpisanych znakow 
dec di                ; zmniejsz bufor

mov ah, 0Eh           ; przesuń kursor w lewo wypisując backspace
int 10h

mov ah, 09h           ; wyczyść znak pod kursorem nie przesuwając go
mov al, ' '
mov bh, 0h
mov bl, 07h
mov cx, 1       
int 10h

jmp get_cmd_start     ; wróć do początku

enter_key:            ; jeżeli wciśnieto enter to dopisz 0 
mov BYTE [di], 0x00   ; na koniec bufora i wyjdź
ret


reboot:
jmp 0FFFFh:0000h
; nie musimy dodawać instrukcji ret gdyż z tej funkcji nie wracamy

clear_screen:
push ax    
push ds      
push bx      
push cx      
push di 

mov     AX, 40h
mov     DS, AX      
mov     AH, 06h     
mov     AL, 0       
mov     BH, 07      
mov     CH, 0      
mov     CL, 0      
mov     DI, 84h     
mov     DH, [DI]   
mov     DI, 4Ah    
mov     DL, [DI]
dec     DL        
int     10h

mov     BH, 0  
mov     DL, 0  
mov     DH, 0  
mov     AH, 02
int     10h

pop di
pop cx
pop bx
pop ds
pop ax        
ret

version:
mov si,OsName       
call disp_str
mov si,MajorVer       
call disp_str
mov si,MinorVer       
call disp_str
ret

help:
mov si,msgHelp      
call disp_str
ret

execute:          
mov si, UserCmd
cmp BYTE [si], 0h
je koniec_execute    ; jeżeli bufor polecenia jest pusty nie wykonujemy żadnej akcji

cmd_ver:             ; sprawdzamy czy pobrane polecenie to nie 'version'
mov si, UserCmd
mov di, cmdVersion
mov cx, 8
repe cmpsb

jne cmd_reset        ; jeżeli nie to sprawdzamy nastepnš mozliwość

call version         ; jeżeli tak to skaczemy do odpowiedniej funkcji
jmp koniec_execute   ; i wracamy do pętli glownej

cmd_reset:
mov si, UserCmd
mov di, cmdReboot
mov cx, 7
repe cmpsb

jne cmd_clrscr
call reboot
   
cmd_clrscr:
mov si, UserCmd
mov di, cmdClrscr
mov cx, 7
repe cmpsb

jne cmd_help
call clear_screen
jmp koniec_execute

cmd_help:       
mov si, UserCmd
mov di, cmdHelp
mov cx, 5
repe cmpsb
jne UnknownCmd       
call help
jmp koniec_execute

UnknownCmd:
mov si,cmdUnknown      
call disp_str

koniec_execute:
ret

 

disp_str:
    lodsb               ; load next character
    cmp al, 0        ; sprawdza czy nie 0
    je  .DONE           ; jeżeli tak to kończy
    mov ah, 0x0E       
    int 10h             
    jmp disp_str
.DONE:
ret

[SEGMENT .data]
MaxLen    db  40h       ; maksymalna długość polecenia - 64 znaki
OsName          db  13,10,"LukOS RMODE",13,10,0    
MajorVer        db  "Wersja 1",0
MinorVer        db  ".02",0
msgHelp         db  13,10,"Dostepne polecenia:",13,10,
                db  "clrscr - czysci ekran",13,10,   
                db  "help - wyswietla liste dostepnych polecen",13,10,
                db  "version - wyswietla nazwe i wersje systemu",13,10,
                db  "reboot - restartuje komputer",0
cmdVersion        db  "version",0    
cmdReboot         db  "reboot",0
cmdClrscr         db  "clrscr",0
cmdHelp           db  "help",0
cmdUnknown        db  13,10,"Nieznane polecenie! Wpisz 'help', aby uzyskac pomoc",0
[SEGMENT .bss]
UserCmd  resb  40h      ; tekst wpisany przez użytkownika
CmdSize  resb    0      ; ilość wpisanych znaków

Potem traktuje to merge Wolverina i wczytuje obraz do VirtualBox i wyświetla się tylko napis Witaj w boot sektorze. Dalej nic :(

0

Na samym początku systemu operacyjnego dodaj

mov ax, 0800h
mov es, ax
mov ds, ax

Ewentualnie zmień [org 0x0000] na [org 0x8000] - gorsze rozwiązanie!

0
ADuch napisał(a)

Na samym początku systemu operacyjnego dodaj

mov ax, 0800h
mov es, ax
mov ds, ax

Nie działa :( po naciśnięciu pokazuje się na ekranie tylko to:
user image

Ewentualnie zmień [org 0x0000] na [org 0x8000] - gorsze rozwiązanie!
To w ogóle nie działa

0

Pytanie: jak kompilujesz plik "kernel.asm" ?
Dokładniej do jakiego formatu wykonywalnego. Występowanie "[SEGMENT .text]" itp. sugeruje, że nie jest to format pliku beznagłówkowego np. com . Więc wydaje mi się, że tutaj tkwi błąd.
Jak nie to. To jest jeszcze pytanie jak tworzysz obraz dysku ew. jak wgrywasz te pliki przekompilowane na dyskietke ?

0

To ja dorzucę kod jeszcze jednego pliku
make.bat:

nasm.exe kernel.asm -o kernel.bin
nasm.exe boot.asm -o boot.bin
merge.exe boot.bin kernel.bin image.img

PS: Wie ktoś skąd wziąć programy Copyboot lub Partcopy?

0

nasm plik.asm -f bin -o wynik.bin

0

To nic nie daje :(

0

Może to być związane z tym iż plik kernel.asm zajmuje po skompilowaniu więcej niż 512 bajtów i Boot Loader musi wczytać dwa kolejne sektory aby załadować go w całości do pamięci. Jest jeszcze taka możliwość, że program jest po prostu źle napisany.

lukasz1235: Daj mi jakiś mail czy inny kontakt do ciebie, albo napisz do mnie. Chciałbym z tobą pogadać.

0
Nevar napisał(a)

Może to być związane z tym iż plik kernel.asm zajmuje po skompilowaniu więcej niż 512 bajtów
Rzeczywiście. Zajmuje więcej. Wiem jak to naprawić, ale nie ma odpowiedniego programu. Ponawiam prośbę: Jeżeli ktoś ma link lub ma na dysku te programy: Copyboot lub Partcopy to proszę o kontakt.

//Skoro nikt nie ma to może jakiś podobny program?

lukasz1235: Daj mi jakiś mail czy inny kontakt do ciebie, albo napisz do mnie. Chciałbym z tobą pogadać.
Najlepiej wyślij wiadomość prywatną.</quote>

0

No niestety muszę przyznać, że po pierwsze źle przekopiowałeś sam kod. Niestety w tym przypadku samo uporządkowanie go nic nie da. Artykuł do którego podałeś link jest tragiczny. Jak widzę w kodzie takie wywołanie:

cmp al,0dh
je enter_key
...
enter_key:
mov BYTE [di], 0x00
ret

To sie zastanawiam czy autor wiedział czy podawany przez niego kod działa, ablo czy miał pojęcie o programowaniu. Przykładów podobnych do podanego wyżej jest kilka w tym programie.

W każdym razie zreanimowałem ten program do jako takiego działania, ale nie gwarantuje jego 100% poprawnego działania.

[org 0x0000]
[bits 16]

[SEGMENT .text]
get_cmd:
mov	ax,	0x800
mov	ds,	ax
mov	es,	ax

mov ax, 0E0Dh
mov bh, 00h
mov bl, 07h
int 10h
mov ax, 0E0Ah
int 10h


mov BYTE [CmdSize],0  ; zerujemy zmienną przechowującą 
                      ; bieżącą liczbę znaków w buforze
mov di, UserCmd       ; wpisujemy do DI offset bufora na komende

get_cmd_start:              

mov ah,10h
int 16h               ; pobieramy znak z klawiatury

cmp al,0              ; al=0 gdy wciśnięty klawisz to klawisz rozszerzony
je get_cmd_start      ; jeżeli tak to wróć do początku,
                      ; jeżeli nie to przejdz dalej

cmp al,08h            ; sprawdź czy wciśnieto spację
je backspace_key      ; jeżeli tak to skocz do podprocedury obsługującej spację

cmp al,0dh            ; sprawdź czy wciśnięty klawisz to enter
                      ; (czyli koniec polecenia)
je enter_key          ; jeżeli tak to skocz do odpowiedniego miejsca

; pobrany znak to zwykły znak ascii

mov bh, [MaxLen]             
mov bl, [CmdSize]
cmp bl, bh            ; sprawdz czy nie osiągnięto max dozwolonej ilości znaków
je get_cmd_start      ; jeżeli tak to wróć do początku

mov [di],al           ; dodaj znak do bufora
inc di                ; zwiększ indeks
inc BYTE [CmdSize]    ; zwiększ rozmiar komendy
mov ah,0eh
int 10h               ; wyświetl wpisany znak
jmp get_cmd_start     ; wróć do początku

space:
    mov ah, 0Eh   
    mov al, 20h    ; kod ascii spacji
    mov bh, 00h    ; strona graficzna
    mov bl, 07h    ; atrybuty tekstu
    int 10h        ; wywołanie przerwania
ret

next_line:
    mov ah, 0Eh       
    mov al, 0Dh
    mov bh, 00h
    mov bl, 07h
    int 10h
    mov ah, 0Eh
    mov al, 0Ah
    mov bh, 00h
    mov bl, 07h
    int 10h
ret

prompt:
    mov ah, 0Eh       
    mov al, 02h
    mov bh, 00h
    mov bl, 07h
    int 10h
ret

backspace_key:        ; jeżeli wciśnięto backspace...
mov bl,0
mov bh,[CmdSize]
cmp bh,bl             ; jeżeli w buforze nie ma nic, to znaczy,
je get_cmd_start      ; że nia ma czego usuwać, wróć więc do początku

; usuwamy ostatni znak i z bufora i z ekranu

dec BYTE [CmdSize]    ; zmniejsz licznik wpisanych znakow
dec di                ; zmniejsz bufor

mov ah, 0Eh           ; przesuń kursor w lewo wypisując backspace
int 10h

mov ah, 09h           ; wyczyść znak pod kursorem nie przesuwając go
mov al, ' '
mov bh, 0h
mov bl, 07h
mov cx, 1       
int 10h

jmp get_cmd_start     ; wróć do początku

enter_key:            ; jeżeli wciśnieto enter to dopisz 0
mov BYTE [di], 0x00   ; na koniec bufora i wyjdź
jmp	execute


reboot:
jmp 0FFFFh:0000h
; nie musimy dodawać instrukcji ret gdyż z tej funkcji nie wracamy

clear_screen:
push ax   
push ds     
push bx     
push cx     
push di

mov     AX, 40h
mov     DS, AX     
mov     AH, 06h     
mov     AL, 0       
mov     BH, 07     
mov     CH, 0     
mov     CL, 0     
mov     DI, 84h     
mov     DH, [DI]   
mov     DI, 4Ah   
mov     DL, [DI]
dec     DL       
int     10h

mov     BH, 0 
mov     DL, 0 
mov     DH, 0 
mov     AH, 02
int     10h

pop di
pop cx
pop bx
pop ds
pop ax       
ret

version:
mov si,OsName       
call disp_str
mov si,MajorVer       
call disp_str
mov si,MinorVer       
call disp_str
ret

help:
mov si,msgHelp     
call disp_str
ret

execute:         
mov si, UserCmd
cmp BYTE [si], 0h
je koniec_execute    ; jeżeli bufor polecenia jest pusty nie wykonujemy żadnej akcji

cmd_ver:             ; sprawdzamy czy pobrane polecenie to nie 'version'
mov si, UserCmd
mov di, cmdVersion
mov cx, 8
repe cmpsb

jne cmd_reset        ; jeżeli nie to sprawdzamy nastepnš mozliwość

call version         ; jeżeli tak to skaczemy do odpowiedniej funkcji
jmp koniec_execute   ; i wracamy do pętli glownej

cmd_reset:
mov si, UserCmd
mov di, cmdReboot
mov cx, 7
repe cmpsb

jne cmd_clrscr
call reboot
   
cmd_clrscr:
mov si, UserCmd
mov di, cmdClrscr
mov cx, 7
repe cmpsb

jne cmd_help
call clear_screen
jmp koniec_execute

cmd_help:       
mov si, UserCmd
mov di, cmdHelp
mov cx, 5
repe cmpsb
jne UnknownCmd       
call help
jmp koniec_execute

UnknownCmd:
mov si,cmdUnknown     
call disp_str

koniec_execute:
jmp	get_cmd

disp_str:
    lodsb               ; load next character
    cmp al, 0        ; sprawdza czy nie 0
    je  .DONE           ; jeżeli tak to kończy
    mov ah, 0x0E       
    int 10h             
    jmp disp_str
.DONE:
ret

[SEGMENT .data]
MaxLen    db  40h       ; maksymalna długość polecenia - 64 znaki
OsName          db  13,10,"LukOS RMODE",13,10,0   
MajorVer        db  "Wersja 1",0
MinorVer        db  ".02",0
msgHelp         db  13,10,"Dostepne polecenia:",13,10,
                db  "clrscr - czysci ekran",13,10,   
                db  "help - wyswietla liste dostepnych polecen",13,10,
                db  "version - wyswietla nazwe i wersje systemu",13,10,
                db  "reboot - restartuje komputer",0
cmdVersion        db  "version",0   
cmdReboot         db  "reboot",0
cmdClrscr         db  "clrscr",0
cmdHelp           db  "help",0
cmdUnknown        db  13,10,"Nieznane polecenie! Wpisz 'help', aby uzyskac pomoc",0
[SEGMENT .bss]
UserCmd  resb  40h      ; tekst wpisany przez użytkownika
CmdSize  resb    0      ; ilość wpisanych znaków
 

No i oczywiście ten program też zajmuje dwa sektory po 0x200 bajtów tak więc podany na poczatku BL też trzeba nieznacznie przerobić.

//Skoro nikt nie ma to może jakiś podobny program?

Ja znam debug.exe ale nie wiem czy chodzi ci o program mogący zapisywać konkretne sektory na dysk czy o jakiś innego typu ?

0

Niestety nie działa :(
Programowi debug.exe (trochę myląca nazwa) jeszcze się przyjrzę.
Czegoś nie kumam. Wpisuję:

debug
-N D:\Documents and Settings\Łukasz\Pulpit\os\LukOS RMODE 2\boot.bin
-W 100 0 0 1

I bios nie wykrywa systemu na dyskietce.

0

Chyba źle jest napisany kernel, bo nagrałem na dyskietkę bootloader, który ma za zadanie otworzyć plik kernel.bin i przekazać mu kontrolę. Po włączeniu pokazuje się tylko czarny ekran :-(
Zna ktoś kurs, który działa.
Jest prosto napisany
Wszystko jest wytłumaczone, itp?

0

Mam taki kurs z tym, że on bazuje na trybie chronionym i jest napisany po angielsku. Co do tego kodu powyżej to mi działa. Na pewno twój błąd tkwi w jakimś szczególe. Chcesz mogę ci pomóc dograć te wszystkie moduły systemu tak żeby zadziałał tylko napisz do mnie jak kiedyś będę dostępny na gg albo irc.

http://my.execpc.com/~geezer/os/pm.zip

0

Kurs po angielsku odpada. Jak po polsku mam problem to co będzie po angielsku...
Na tym kodzie już mi nie zależy, bo jak już na tym etapie są problemy ciekawy jestem co będzie potem.

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