Lowlevel
Lowlevel => Lowlevel-Coding => Thema gestartet von: Feuermonster am 01. May 2009, 13:15
-
Hallo,
ich habe versucht einen Handler fuer das Keyboard zu setzen, doch leider klappt dies irgendwie nicht. (keyboard_handler wird nie aufgerufen)
Ein weiteres Problem ist, dass nach dem call show_info der Kernel irgendwie haengen bleibt und ich kann mir nichts ausdenken, was dazu fuehren koennte. Eine unmittelbare Ausgabe auf den Bildschirm nach call show_info funktioniert nicht, d.h das jmp _continue nach call show_info wird gar nicht erst aufgerufen.
Code:
mov ax, 0x1000 ;update segment register...
mov ds, ax
mov es, ax
init0:
mov si,s_noos_init0
call noos_putstr
mov bl, 0x05
mov si, s_noos_logo
call noos_printf
mov bl, 0x02
mov si, s_noos_jmp_good
call noos_printf
call noos_inc_line
call noos_reset_line
mov bl, 0x05
mov si, s_noos_logo
call noos_printf
mov bl, 0x02
mov si, s_noos_step1
call noos_printf
call noos_inc_line
call noos_reset_line
push dx
push es
xor ax, ax
mov es, ax
cli
mov word [es:0x21*4], _int0x021
mov [es:0x21*4+2], cs
mov word[ds:(9*4) ], keyboard_handler ;Offset
mov word[ds:(9*4)+2], 0 ;Segment
sti
pop es
pop dx
mov bl, 0x05
mov si, s_noos_logo
mov dl, 0x03
int 0x021
mov bl, 0x02
mov si, s_noos_step2
mov dl, 0x03
int 0x021
mov dl, 0x07
int 0x021
mov dl, 0x08
int 0x021
mov bl, 0x05
mov si, s_noos_logo
mov dl, 0x03
int 0x021
mov bl, 0x02
mov si, s_noos_step3
mov dl, 0x03
int 0x021
mov dl, 0x07
int 0x021
mov dl, 0x08
int 0x021
mov bl, 0x05
mov si, s_noos_logo
mov dl, 0x03
int 0x021
mov bl, 0x02
mov si, s_noos_step4
mov dl, 0x03
int 0x021
mov dl, 0x09
int 0x021
mov bl, 0x06
mov dl, 0x03
int 0x021
mov dl, 0x07
int 0x021
mov dl, 0x08
int 0x021
mov bl, 0x0A
mov si, s_noos_i_info
mov dl, 0x03
int 0x021
mov dl, 0x07
int 0x021
mov dl, 0x08
int 0x021
loopi:
mov ah,00h
int 16h
mov bl,0x08
cmp al,0x31
je do_show_info
cmp al,0x32
je do_calc_test
jmp _continue
do_show_info:
call show_info
jmp _continue
do_calc_test:
call calc_test
jmp _continue
_continue:
call noos_putchar
call noos_inc_row
call noos_inc_line
call noos_reset_line
jmp loopi
;Variablen
;========
s_noos_init0 db "Init 0",13,10,0
s_noos_logo db "[ NoOS ]",0
s_noos_jmp_good db " Jump into kernel successful",0
s_noos_step1 db " Setting up syscalls",0
s_noos_step2 db " Syscalls (INT 0x021) set",0
s_noos_step3 db " Reading from CMOS (Month)",0
s_noos_step4 db " And the month is: ",0
s_noos_keyp db "KEY_PRESSED",0
s_noos_i_info db "Options",13,9,"1.) Show copyright",13,9,"2.) Calc test",0
s_noos_i_autor db "NoOS (c) by Roman Muentener",0
s_noos_i_calc_end db "Calc test done...",0
;Funktionen
;========
calc_test:
mov cx, 0xFFFF
calc_test_loop:
cmp cx,0
je calc_test_end
dec cx
jmp calc_test_loop
calc_test_end:
mov bl,0xA8
mov si,s_noos_i_calc_end
mov dl,0x03
int 0x021
retn
show_info:
mov bl,0x0D
mov si,s_noos_i_autor
mov dl,0x03
int 0x021
retn
keyboard_handler:
mov si,s_noos_keyp
mov bl,0x02
mov dl,0x03
int 0x021
mov al, 0x20
out 0x20, al
iret
noos_reset_line:
call noos_get_cursor_pos
mov dl,0
call noos_set_cursor_pos
retn
;ret: DL = Spalte; ret: DH = Zeile
noos_get_cursor_pos:
mov ah, 0x03
int 0x10
retn
;DL = Spalte; DH = Zeile
noos_set_cursor_pos:
mov ah, 0x02
push bx
xor bh, bh
int 0x10
pop bx
retn
noos_inc_line:
call noos_get_cursor_pos
inc dh
call noos_set_cursor_pos
retn
noos_inc_row:
call noos_get_cursor_pos
inc dl
call noos_set_cursor_pos
retn
;SI = string
noos_printf:
lodsb
or al,al
jz noos_printf_end
call noos_putchar
call noos_inc_row
jmp noos_printf
noos_printf_end:
retn
;AL = char; BL = Farbe
noos_putchar:
push cx
mov cx, 1
mov ah, 0x09
int 0x10
pop cx
retn
;SI = string
noos_putstr:
lodsb
or al, al
jz noos_putstr_end
mov ah, 0x0E
mov bx, 0x07
int 0x10
jmp noos_putstr
noos_putstr_end:
retn
noos_reboot:
jmp 0xffff:0x0000
noos_getkey:
mov ah,00h
int 0x16
retn
;-------
;Syscalls
;-------
_int0x021:
cmp dl, 0x01
je _int0x021_f1
cmp dl, 0x02
je _int0x021_f2
cmp dl, 0x03
je _int0x021_f3
cmp dl, 0x04
je _int0x021_f4
cmp dl, 0x05
je _int0x021_f5
cmp dl, 0x06
je _int0x021_f6
cmp dl, 0x07
je _int0x021_f7
cmp dl, 0x08
je _int0x021_f8
cmp dl, 0x09
je _int0x021_f9
iret
;noos_putstr: SI = string
_int0x021_f1:
push dx
lodsb
or al, al
jmp _int0x021_f1_end
mov ah, 0x0E
mov bx, 0x07
int 0x10
_int0x021_f1_end:
pop dx
retn
;noos_putchar: AL = char, BL = farbe
_int0x021_f2:
push dx
push cx
cmp al, 0xD
je _int0x021_f2_newline
cmp al, 0x09
je _int0x021_f2_tab
mov cx, 1
mov bh, 0x00
mov ah, 0x09
int 0x10
call _int0x021_f4
jmp _int0x021_f2_end
_int0x021_f2_tab:
call _int0x021_f4
call _int0x021_f4
call _int0x021_f4
call _int0x021_f4
jmp _int0x021_f2_end
_int0x021_f2_newline:
call _int0x021_f7
call _int0x021_f8
_int0x021_f2_end:
pop cx
pop dx
retn
;noos_printf: SI = string, BL = farbe
_int0x021_f3:
push dx
lodsb
or al,al
jz _int0x021_f3_end
call _int0x021_f2
pop dx
jmp _int0x021_f3
_int0x021_f3_end:
pop dx
retn
;noos_inc_row
_int0x021_f4:
push dx
call _int0x021_f5
inc al
call _int0x021_f6
pop dx
retn
;noos_get_cursor_pos: ret: AL = Spalte; ret: AH = Zeile
_int0x021_f5:
push dx
mov ah, 0x03
int 0x10
mov al,dl
mov ah,dh
pop dx
retn
;noos_set_cursor_pos: ;AL = Spalte; AH = Zeile
_int0x021_f6:
push dx
mov dl,al
mov dh,ah
mov ah, 0x02
push bx
xor bh, bh
int 0x10
pop bx
pop dx
retn
;noos_inc_line
_int0x021_f7:
push dx
call _int0x021_f5
inc ah
call _int0x021_f6
pop dx
retn
;noos_reset_line
_int0x021_f8:
push dx
call _int0x021_f5
mov al,0
call _int0x021_f6
pop dx
retn
;noos_get_month
_int0x021_f9:
push dx
mov al,0x08
out 0x70,al
in al,0x71
cmp al,0x01
je _int0x021_f9_jan
cmp al,0x02
je _int0x021_f9_feb
cmp al,0x03
je _int0x021_f9_mar
cmp al,0x04
je _int0x021_f9_apr
cmp al,0x05
je _int0x021_f9_may
cmp al,0x06
je _int0x021_f9_jun
cmp al,0x07
je _int0x021_f9_jul
cmp al,0x08
je _int0x021_f9_aug
cmp al,0x09
je _int0x021_f9_sep
cmp al,0x0A
je _int0x021_f9_oct
cmp al,0x0B
je _int0x021_f9_nov
cmp al,0x0C
je _int0x021_f9_dec
je _int0x021_f9_end
_int0x021_f9_jan:
mov si,jan
jmp _int0x021_f9_end
_int0x021_f9_feb:
mov si,feb
jmp _int0x021_f9_end
_int0x021_f9_mar:
mov si,mar
jmp _int0x021_f9_end
_int0x021_f9_apr:
mov si,apr
jmp _int0x021_f9_end
_int0x021_f9_may:
mov si,may
jmp _int0x021_f9_end
_int0x021_f9_jun:
mov si,jun
jmp _int0x021_f9_end
_int0x021_f9_jul:
mov si,jul
jmp _int0x021_f9_end
_int0x021_f9_aug:
mov si,aug
jmp _int0x021_f9_end
_int0x021_f9_sep:
mov si,sep
jmp _int0x021_f9_end
_int0x021_f9_oct:
mov si,oct
jmp _int0x021_f9_end
_int0x021_f9_nov:
mov si,nov
jmp _int0x021_f9_end
_int0x021_f9_dec:
mov si,dec_
jmp _int0x021_f9_end
mov si,unk
_int0x021_f9_end:
pop dx
retn
retn
_int0x021_end:
iret
jan db "January",0
feb db "February",0
mar db "March",0
apr db "April",0
may db "May",0
jun db "June",0
jul db "July",0
aug db "August",0
sep db "September",0
oct db "October",0
nov db "November",0
dec_ db "December",0
unk db "Unknown",0
times 1474048-($-$$) db 0
Etwas viel ich weiss, aber ich hoffe ihr koennt mir weiterhelfen.
-
mov es, ax
cli
mov word [es:0x21*4], _int0x021
mov [es:0x21*4+2], cs
mov word[ds:(9*4) ], keyboard_handler ;Offset
mov word[ds:(9*4)+2], 0 ;Segment
du benutzt für den Keyboard_handler ja auch die falsche Segmentaddresse für die IVT
du woltest wohl es stat ds schreiben ^^
außerdem gehst du für den handler von codsegemnt 0 aus. für den int 21 nimmst du das aktuelle cs, die sollten beide im aktuellen cs liegen, sonst stimmen die offsets nicht.
IIRC geht mov […], cs gar nicht. und muss z.B. lauten
mov ax, cs
mov […], ax
oder halt mit jedem anderen allzweckregister
[edit]
keyboard_handler:
mov si,s_noos_keyp
mov bl,0x02
mov dl,0x03
int 0x021
mov al, 0x20
out 0x20, al
iret
ein interrupthandler sollte keine register verändern?
stell dir vor:
xor al, al
;hier drückt einer eine taste
;dann landet man bestimmt nicht mehr bei _bla
cmp al, 0
je _bla
also alle register die du im interrupt veränderst vor her push'en und am ende wieder vom stack holen.
loopi:
mov ah,00h
int 16h
hier wirst du nicht vorbei kommen, wenn du nicht den int0x16 auch noch selbst machst. Wie soll denn das BIOS mitkriegen das ne taste gedrückt wurde wenn du ihm den IRQ klaust und deine keyboard_handler dran hängst.
-
>hier wirst du nicht vorbei kommen, wenn du nicht den int0x16 auch noch selbst machst. Wie soll denn das BIOS mitkriegen das ne taste gedrückt wurde wenn du ihm den IRQ klaust und deine keyboard_handler dran hängst.
Wenn der keyboard_handler funktioniert, dann ja. Momentan tut er das nicht, der int 16h funktioniert.
Wenn ich die Taste 1.) druecke, wird die Nachricht "[..] (c) Roman [...]" ausgegeben. Danach ist jedoch fertig. Theoretisch sollte ich ja wieder zur Auswahl kommen -> ist jedoch nicht der Fall.
>außerdem gehst du für den handler von codsegemnt 0 aus. für den int 21 nimmst du das aktuelle cs, die sollten beide im aktuellen cs liegen, sonst stimmen die offsets nicht.
CS aendere ich ja noch nicht. Soll ich das auch wie es auf 0 setzen?
Wenn ich
push dx
push es
xor ax, ax
mov es, ax
mov cs, ax
cli
mov word [es:0x21*4], _int0x021
mov [es:0x21*4+2], cs
mov word[es:(9*4) ], keyboard_handler ;Offset
mov word[es:(9*4)+2], cs ;Segment
sti
pop es
pop dx
schreibe, bleibt der Kernel haengen. (Die nachricht Syscalls set kommt dann gar nicht mehr).
-
>hier wirst du nicht vorbei kommen, wenn du nicht den int0x16 auch noch selbst machst. Wie soll denn das BIOS mitkriegen das ne taste gedrückt wurde wenn du ihm den IRQ klaust und deine keyboard_handler dran hängst.
Wenn der keyboard_handler funktioniert, dann ja. Momentan tut er das nicht, der int 16h funktioniert.
:?
Du registrierst einen IRQ1 Handler, richtig? Und du willst den BIOS Interrupts zum Empfangen einer Taste verwenden richtig? Beides zusammen geht nicht, wie MNemo bereits sagte, da damit der BIOS Interrupt funktioniert der IRQ1 Handler nicht verändert werden darf. Das BIOS wartet ja schließlich auf einen IRQ1, um vom Tastendruck was mitzubekommen. Und du klaust dem BIOS durch das Umbiegen der IVT einfach so den IRQ1.
-
CS aendere ich ja noch nicht. Soll ich das auch wie es auf 0 setzen?
Wenn ich
push dx
push es
xor ax, ax
mov es, ax
mov cs, ax
cli
mov word [es:0x21*4], _int0x021
mov [es:0x21*4+2], cs
mov word[es:(9*4) ], keyboard_handler ;Offset
mov word[es:(9*4)+2], cs ;Segment
sti
pop es
pop dx
schreibe, bleibt der Kernel haengen. (Die nachricht Syscalls set kommt dann gar nicht mehr).
nein du sollst nicht cs auf 0 setzen. ich finde es zwar merkwürdig das dein assembler den code oben überhaupt akzeptiert denn ich dachte dass man auf cs nicht direkt zugreifen kann, deshalb hatte ich gemeint du solst mal:
push es
xor ax, ax
mov es, ax
mov ax, cs
cli
mov word [es:0x21*4], _int0x021
mov [es:0x21*4+2], ax
mov word[es:(9*4) ], keyboard_handler ;Offset
mov word[es:(9*4)+2], ax ;Segment
sti
pop es
den sinn deines push/pop dx muss man nicht verstehen oder?
-
Du registrierst einen IRQ1 Handler, richtig? Und du willst den BIOS Interrupts zum Empfangen einer Taste verwenden richtig? Beides zusammen geht nicht, wie MNemo bereits sagte, da damit der BIOS Interrupt funktioniert der IRQ1 Handler nicht verändert werden darf. Das BIOS wartet ja schließlich auf einen IRQ1, um vom Tastendruck was mitzubekommen. Und du klaust dem BIOS durch das Umbiegen der IVT einfach so den IRQ1.
Eben registriere ich ihn nicht. Der keyboard handler funktioniert nicht. Ich will den int 16h gar nicht, der steht einfach so da damit ich wenigstens etwas habe womit ich Eingaben verwerten kann (was irgendwie auch nicht so richtig funktionert, er springt nicht mehr nach loopi zurueck).
Eigentlich will ich nur dass bei jedem Tastendruck mein keyboard_handler aufgerufen wird. Die Funktion zum den Tastendruck nachher auszulesen bau ich dann schon selber, aber dazu muss erst mal der Handler funktionieren.
Edit: Ich hab jetzt mal folgendes getaetigt
push dx
push es
xor ax, ax
mov es, ax
mov bx, cs
cli
mov word [es:0x21*4], _int0x021
mov [es:0x21*4+2], bx
mov word[es:(9*4) ], keyboard_handler ;Offset
mov word[es:(9*4)+2], bx ;Segment
sti
pop es
pop dx
Der Int 16h funktioniert nun nicht mehr, dass ist soweit ja wie es sein sollte.
Doch der keyboard_handler wird nicht aufgerufen. Oder die Nachrichtenausgabe failt, aber wenn ich ein int 0x09 schreibe, wird sie ausgegeben. Also tendiere ich eher dazu, dass die CPU meinen keyboard_handler nicht aufruft.
-
Ich bezweifle das das viel mit deinem problem zu tun hat, aber ich hab da ein paar fehler entdeckt.
du machst folgeneds
int0x21:
cmp dl, 0x3
je func3
…
func3:
…
retn
falls du das versuchst, zu einem jmp kann man mit einem retn nicht zurückkehren, das funktioniert nur nach einem call.
falls das nicht dein ziel ist und du einfach nur aus der ISR zurückkehren wilst must du das mit iret machn.
ret und iret unterscheiden sich dahingehend, dass iret zusätzlich noch die flags vom stack holt(mit ret bleiben die nach einem int einfach da liegen und machen dir den stack kaput.
daraus folgt auch, dass du nicht einfach einmal
jmp func2
und einmal
call func2
machen kannst.(ich geb zu, unter gewissen umständen geht das schon, die sind hier aber nicht gegeben)
-
Ein iret geht nicht, da ich ja zwischen den Interrupts auch calls habe. wenn func4 mittels call func5 aufruft und func5 wuerde mit iret ja sofort den ganzen Interrupt zufrueh beenden.
D.h ich muss das Design der Interrupts wohl umschreiben.
-
wie gesagt du kannst das nicht einfach mischen.
Entweder dein func5 ist eine Procedure, die du mittels call aufrufst und mit ret beendest,(darfst du sie nicht mit jmp/je/.. aufrufen) oder du darfst func5 nicht mit call starten.
-
Eine Funktion kannst du nur entweder als Interrupt oder als normale Funktion aufrufen, wenn du anfängst zu mischen hast du ein Problem.
Das call legt ja letztendlich nur die Rücksprungadresse auf den Stack und springt, und ret holt sie wieder vom Stack und springt zurück. Ein Interrupt speichert etwas mehr auf den Stack und ein iret holt entsprechend auch wieder mehr zurück, um den alten Zustand wiederherzustellen.
Wenn der Aufruf und der Rücksprung nicht zusammenpassen, läßt du entweder überschüssiges Zeug auf dem Stack liegen, was den Aufrufer durcheinanderbringt oder du nimmst zuviel runter, was den Aufrufer ebenfalls durcheinanderbringt und höchstwahrscheinlich einen unsinnigen Zustand "wiederherstellt".
-
Kann ich wenn ich innerhalb des Interrupts 0x21 bin,
einen weiteren Interrupt 0x21 ausloesen?
Genau gesagt, wenn die Funktion 0x3 fuer jedes Byte die Funktion 0x2 aufruft mittels mov dl,0x02 int 0x21, geht das in Ordnung?
Edit: Hat jemand eine Idee wieso der keyboard_handler nicht funktioniert?
-
Jo, natürlich.
-
Ja, grundsätzlich schon. Bringt eben ein bißchen Overhead mit sich. Aber das ist dann halt die berühmte Geschwindigkeit, wenn man Assembler programmiert.
-
Und es wird halt extrem übersichtlich und Probleme lassen sich so extrem einfach debuggen. :roll:
-
Edit: Hat jemand eine Idee wieso der keyboard_handler nicht funktioniert?
wenn du mir deinen bootsector auch noch gibst kann ich mir das mal mit bochs angucken.
-
Vielen Dank fuer die Hilfe. Ich habe den Code jetzt mal aufgeraeumt.
;===========
; Kernel
;===========
; Update segment registers
mov ax, 0x1000
mov ds, ax
mov es, ax
push dx
push es
xor ax, ax
mov es, ax
mov bx, cs
cli
mov word [es:0x21*4], noos_int21h
mov [es:0x21*4+2], bx
mov word[es:(9*4) ], noos_keyboard_handler ;Offset
mov word[es:(9*4)+2], bx ;Segment
sti
pop es
pop dx
mov si, s_noos_logo
xor bh, bh
mov bl, 0x05
mov dl, 0x01
int 0x21
noos_loop:
jmp noos_loop
;=============
; Variables
;=============
s_noos_logo db "[ NoOS ]",0
s_noos_jmp_good db " Jump into kernel successful",0
s_noos_step1 db " Setting up syscalls",0
s_noos_step2 db " Syscalls (INT 0x021) set",0
s_noos_step3 db " Reading from CMOS (Month)",0
s_noos_step4 db " And the month is: ",0
s_noos_keyp db "KEY_PRESSED",0
s_noos_i_info db "Options",13,9,"1.) Show copyright",13,9,"2.) Calc test",0
s_noos_i_autor db "NoOS (c) by Roman Muentener",0
s_noos_i_calc_end db "Calc test done...",0
;==============
; Handlers
;==============
noos_keyboard_handler:
pusha
; Print dummy message
mov bl, 0x06
xor bh, bh
mov dl, 0x01
mov si, s_noos_keyp
int 0x21
; Tell the PIC we handled the interrupt
mov al, 0x20
out 0x20, al
popa
iret
;==============
; Functions
;==============
noos_int21h:
;Jump to the right function
cmp dl, 0x01
je noos_int21h_0x1
cmp dl, 0x02
je noos_int21h_0x2
cmp dl, 0x03
je noos_int21h_0x3
cmp dl, 0x04
je noos_int21h_0x4
cmp dl, 0x05
je noos_int21h_0x5
iret
;=========
;noos_print
; BL = Attribute, SI = String
;=========
noos_int21h_0x1:
lodsb ;Load byte
or al, al ;Zero byte?
jz noos_int21h_0x1_end
; Call noos_putchar
mov dl, 0x02
int 0x21
;Loop
jmp noos_int21h_0x1
noos_int21h_0x1_end:
iret
;============
;noos_putchar
; BL = Attribute, AL = Character, BH = Page
;============
noos_int21h_0x2:
mov cx, 1
mov ah, 0x09
int 0x10
; Call noos_inc_column
mov dl, 0x05
int 0x21
iret
;===================
;noos_get_cursor_pos
; ret: AL = Column, ret: AH = Row
;===================
noos_int21h_0x3:
mov ah, 0x03
int 0x10
mov al, dl
mov ah, dh
iret
;===================
;noos_set_cursor_pos
; AL = Column, AH = Row, BH = Page
;===================
noos_int21h_0x4:
mov dl, al
mov dh, ah
mov ah, 0x02
int 0x10
iret
;============
;noos_inc_column
;============
noos_int21h_0x5:
; Call noos_get_cursor_pos
mov dl, 0x03
int 0x21
; Increment
inc al
; Call noos_set_cursor_pos
mov dl, 0x04
int 0x21
iret
times 1474048-($-$$) db 0
Der Handler wird jetzt aufgerufen, jedoch nur einmal. Was ist noch falsch?
-
Jetzt musst du nur noch die Daten aus dem KBC-Auslesen, sonst nimmt der keine weiteren tasten drücke an, und gibt auch keine mehr weiter.