Tastaturtreiber
-
Ich suche gerade einen Fehler, der beim Ersetzen des Interrupt 0x16 durch folgende Datei entsteht - komischerweise werden beim Ausführen scheinbar danach stehende Variablen überschrieben, und beim Aufrufen der Funktion 'update_key_map' hängt Bochs.
Ist etwas in dieser Datei fehlerhaft? Sonst schreibe ich demnächst den Probekernel neu - will hier niemand mit wirrem Code nerven.^^
; Keyboard Driver ; include 'keyboard.asm' ; es and ds should point to 07C0:0000 ; ax, di and si might be changed ; used labels: key_map, update_key_map, get_key_status ; use al for get_key_status decimal key number: 0 A, 1 S, 2 D, 3 W, 4 1, 5 2, 6 3, 7 4, 8 left, 9 down, 10 right, 11 up ; returns al=0 up, al=1 down update_key_map: cli .test_kbc: in al, 0x64 and al, 1b ; byte available jz .return_update_key_map in al, 0x60 cmp al, 0xE0 ; arrow keys jz .arrow_key test al, 10000000b ; break code jz .make_code cmp al, 0x9E ; break A jz .break_A cmp al, 0x9F ; break S jz .break_S cmp al, 0xA0 ; break D jz .break_D cmp al, 0x91 ; break W jz .break_W cmp al, 0x82 ; break 1 jz .break_1 cmp al, 0x83 ; break 2 jz .break_2 cmp al, 0x84 ; break 3 jz .break_3 cmp al, 0x85 ; break 4 jz .break_4 .make_code: cmp al, 0x1E ; make A jz .make_A cmp al, 0x1F ; make S jz .make_S cmp al, 0x20 ; make D jz .make_D cmp al, 0x11 ; make W jz .make_W cmp al, 0x02 ; make 1 jz .make_1 cmp al, 0x03 ; make 2 jz .make_2 cmp al, 0x04 ; make 3 jz .make_3 cmp al, 0x05 ; make 4 jz .make_4 .arrow_key: in al, 0x60 test al, 10000000b ; break code jz .make_arrow cmp al, 0xCB ; break left jz .break_left cmp al, 0xD0 ; break down jz .break_down cmp al, 0xCD ; break right jz .break_right cmp al, 0xC8 ; break up jz .break_up .make_arrow: cmp al, 0x4B ; make left jz .make_left cmp al, 0x50 ; make down jz .make_down cmp al, 0x4D ; make right jz .make_right cmp al, 0x48 ; make up jz .make_up .make_A: mov di, key_map jmp short .save_make_again .make_S: mov di, key_map+1 jmp short .save_make_again .make_D: mov di, key_map+2 jmp short .save_make_again .make_W: mov di, key_map+3 jmp short .save_make_again .make_1: mov di, key_map+4 jmp short .save_make_again .make_2: mov di, key_map+5 jmp short .save_make_again .make_3: mov di, key_map+6 jmp short .save_make_again .make_4: mov di, key_map+7 jmp short .save_make_again .make_left: mov di, key_map+8 jmp short .save_make_again .make_down: mov di, key_map+9 jmp short .save_make_again .make_right: mov di, key_map+10 jmp short .save_make_again .make_up: mov di, key_map+11 jmp short .save_make_again .save_make_again: mov al, 0x1 stosb jmp word .test_kbc .break_A: mov di, key_map jmp short .save_break_again .break_S: mov di, key_map+1 jmp short .save_break_again .break_D: mov di, key_map+2 jmp short .save_break_again .break_W: mov di, key_map+3 jmp short .save_break_again .break_1: mov di, key_map+4 jmp short .save_break_again .break_2: mov di, key_map+5 jmp short .save_break_again .break_3: mov di, key_map+6 jmp short .save_break_again .break_4: mov di, key_map+7 jmp short .save_break_again .break_left: mov di, key_map+8 jmp short .save_break_again .break_down: mov di, key_map+9 jmp short .save_break_again .break_right: mov di, key_map+10 jmp short .save_break_again .break_up: mov di, key_map+11 jmp short .save_break_again .save_break_again: xor al, al stosb jmp word .test_kbc .return_update_key_map: sti ret key_map times 12 db 0 get_key_status: cli mov si, key_map xor ah, ah add si, ax lodsb sti ret
Edit: Die erste Zeile nach '.arrow_key:' hatte ich vergessen, ist eingefügt - ändert aber nichts am nicht funktionieren, hätte nur einen Fehler bei Pfeiltasten verursacht.
-
Ich würde mal ES:(E)DI prüfen, die sollen ja bestimmt auf key_map zeigen
-
Hallo Thuruk,
schau dir mal den Befehl XLAT genauer an..
Der könnte dir bei deinem Code wertvolle Dienste leisten und den Code
erheblich verkürzen.Gruß, Nicky
-
supernicky schrieb:
Hallo Thuruk,
schau dir mal den Befehl XLAT genauer an..
Der könnte dir bei deinem Code wertvolle Dienste leisten und den Code
erheblich verkürzen.Gruß, Nicky
Guter Hinweis, danke.
Ich kenn ja nur eine Handvoll Befehle.
gargyle schrieb:
Ich würde mal ES:(E)DI prüfen, die sollen ja bestimmt auf key_map zeigen
Der Fehler lag tatsächlich in einer absoluten Adressangabe, die davon ausging, dass ab 7C00:000+2 Sektoren alles frei sei. Mein Code lag aber ein paar Bytes darüber - es wurde ein Objekt mitten hinein gespeichert.
Jetzt funktioniert zwar der Treiber noch nicht wie er sollte, aber zumindest hängt das System nicht und der Rest geht wieder.
Für alle Interessierten kopiere ich mal die anderen Dateien:
; Bootloader ; sets registers, loads sectors ; graphics mode 13h ; cs:ip, es:di, ds:si to boot sector ; ss:sp to pre-vram segment [BITS 16] %define sectors 3 jmp word 0x7C0:setup ; cs:ip to boot sector setup: mov ax, 0x07C0 ; es:di and ds:si to boot sector mov ds, ax mov es, ax mov ax, 0x9000 ; ss:sp to start of pre-vram segment mov ss, ax xor ax, ax ; wraps to top of segment mov sp, ax mov ax, 0x13 ; mode 13h int 0x10 load_sectors: xor ah, ah ; reset drive dl int 0x13 jc load_sectors ; cf set on error mov bx, 0x200 ; es:bx to post boot sector xor dh, dh ; head=0 mov cx, 0x2 ; cylinder:sector=0:2 mov ax, 0x200+sectors int 0x13 jc load_sectors ; cf set on error jmp word second_sector times 510-($-$$) db 0 db 0x55 db 0xAA second_sector: %include "kernel.asm" ; include kernel, drivers and resources %include "keyboard.asm" %include "vga.asm" %include "font.asm" times 0x200*(sectors+1)-($-$$) db 0
; VGA Driver ; include 'vga.asm' ; used labels: 'draw_character', 'draw_brush' ; draws characters using fg/bg colors and brushes using 255 colors ; transparency color=0 %define screen_width 320 %define screen_height 200 draw_character: ; es:di to target, ds:si to source, bx=back:fore color, zero for transparency cli push es mov ax, 0xA000 mov es, ax mov ch, 0x10 ; height .line_start: mov cl, 0x8 ; width mov ah, 10000000b ; start with left bit .loop: mov al, [ds:si] ; get bit from font source test al, ah ; foreground? jz .draw_bg mov al, bl ; fg color to al jmp short .draw_chk .draw_bg: mov al, bh ; bg color to al .draw_chk: or al, al ; transparency? jnz .draw inc di ; next byte in vram jmp short .post_draw .draw: stosb ; draw color and next byte in vram .post_draw: shr ah, 0x1 ; will test next bit in source dec cl ; decrement inline counter jnz .loop inc si ; next byte (=line) in source add di, screen_width-0x8 ; next line in vram dec ch ; decrement line counter jnz .line_start pop es sti ret draw_brush: ; es:di to target, ds:si to source, bx=height, cx=width, writes nonzero source bytes to target cli push es mov ax, 0xA000 mov es, ax mov dx, cx ; dx=width .pre_loop: or cx, dx ; cx=width (restore after each line) .loop: lodsb ; color to al & next byte in source or al, al ; transparency? jnz .draw inc di ; next byte in vram jmp short .post_draw .draw: stosb ; draw color to vram .post_draw: dec cx ; decrement inline counter jnz .loop ; line of source drawn? add di, screen_width sub di, dx dec bx ; decrement line counter jnz .pre_loop ; all lines drawn? pop es sti ret
; Kernel ; include 'kernel.asm' ; using vga.asm, keyboard.asm and font.asm ; TESTKERNEL mov di, 0x200*(sectors+1) ; store brush in ram mov cx, 6042 mov al, 0x4 rep stosb mov si, 0x200*(sectors+1) ; draw brush mov cx, 318 mov bx, 19 mov di, 57601 call word draw_brush main_loop: ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; call word update_key_map xor al, al call word get_key_status or al, al jnz draw_a jmp short main_loop ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; call word get_cursor_position mov bx, 0xF mov si, font_cursor call word draw_character xor ah, ah int 0x16 cmp ax, 0x1E41 jz draw_A cmp ax, 0x1E61 jz draw_a cmp ax, 0x3042 jz draw_B cmp ax, 0x3062 jz draw_b cmp ax, 0x2E43 jz draw_C cmp ax, 0x2E63 jz draw_c cmp ax, 0x0E08 jz backspace cmp ax, 0x5300 jz delete cmp ax, 0x1C0D jz enter_key cmp ax, 0x4B00 jz left_key cmp ax, 0x5000 jz down_key cmp ax, 0x4D00 jz right_key cmp ax, 0x4800 jz up_key cmp ax, 0x343E jz DP_key cmp ax, 0x342E jz PU_key cmp ax, 0x332C jz CO_key cmp ax, 0x567C jz prompt cmp ax, 0x8200 jz backslash cmp ax, 0x3920 jz space jmp word main_loop draw_A: call word get_cursor_position mov bx, 0x100F mov si, font_A call word draw_character call word inc_cx jmp word main_loop draw_a: call word get_cursor_position mov bx, 0x100F mov si, font_a call word draw_character call word inc_cx jmp word main_loop draw_B: call word get_cursor_position mov bx, 0x100F mov si, font_B call word draw_character call word inc_cx jmp word main_loop draw_b: call word get_cursor_position mov bx, 0x100F mov si, font_b call word draw_character call word inc_cx jmp word main_loop draw_C: call word get_cursor_position mov bx, 0x100F mov si, font_C call word draw_character call word inc_cx jmp word main_loop draw_c: call word get_cursor_position mov bx, 0x100F mov si, font_c call word draw_character call word inc_cx jmp word main_loop backspace: call word navigation call word dec_cx call word get_cursor_position mov bl, 0x10 mov si, font_full call word draw_character jmp word main_loop delete: call word navigation call word get_cursor_position mov bl, 0x10 mov si, font_full call word draw_character jmp word main_loop enter_key: call word navigation call word inc_cy xor ax, ax mov [cursor_position_x], ax jmp word main_loop left_key: call word navigation call word dec_cx jmp word main_loop down_key: call word navigation call word inc_cy jmp word main_loop right_key: call word navigation call word inc_cx jmp word main_loop up_key: call word navigation call word dec_cy jmp word main_loop DP_key: call word get_cursor_position mov bx, 0x100F mov si, font_DP call word draw_character call word inc_cx jmp word main_loop CO_key: call word get_cursor_position mov bx, 0x100F mov si, font_CO call word draw_character call word inc_cx jmp word main_loop PU_key: call word get_cursor_position mov bx, 0x100F mov si, font_PU call word draw_character call word inc_cx jmp word main_loop prompt: call word get_cursor_position mov bx, 0x100F mov si, font_prompt call word draw_character call word inc_cx jmp word main_loop backslash: call word get_cursor_position mov bx, 0x100F mov si, font_BS call word draw_character call word inc_cx jmp word main_loop space: call word get_cursor_position mov bl, 0x10 mov si, font_full call word draw_character call word inc_cx jmp word main_loop get_cursor_position: mov ax, [cursor_position_y] mov bx, 5120 mul bx mov di, ax mov ax, [cursor_position_x] mov bx, 8 mul bx add di, ax mov bx, 0x10 ret inc_cx: mov ax, [cursor_position_x] cmp ax, 39 jz .left inc ax .write: mov [cursor_position_x], ax ret .left: call word inc_cy xor ax, ax jmp short .write dec_cx: mov ax, [cursor_position_x] or ax, ax jz .right dec ax .write: mov [cursor_position_x], ax ret .right: call word dec_cy mov ax, 39 jmp short .write inc_cy: mov ax, [cursor_position_y] cmp ax, 10 jz .top inc ax .write: mov [cursor_position_y], ax ret .top: xor ax, ax jmp short .write dec_cy: mov ax, [cursor_position_y] or ax, ax jz .bottom dec ax .write: mov [cursor_position_y], ax ret .bottom: mov ax, 10 jmp short .write navigation: call word get_cursor_position mov bx, 0x10 mov si, font_cursor call word draw_character ret cursor_position_x db 0, 0 cursor_position_y db 0, 0
-
Sry wenn der letzte Beitrag den Firefox ein wenig stresst.
Was haltet ihr von folgendem Konzept:
Tastatureingaben werden je nach Wahl des Programmierers in eine programmeigene Tabelle der Form
Nr. Tastendruck (1 Byte) | Code (1 Byte) 0 | 24 1 | 33
eingelesen, wobei ein weiteres Byte die aktuelle Position angibt - für einen Verlauf bei Textverarbeitung o.ä. und/oder in einer Keymap gespeichert:
Code (1 Byte) | Status (1 Byte) 24 | 0 35 | 1
Die Programme müssen dann die Tastatureingaben verwerten. Müsste also einen Interrupt die Tabelle bearbeiten lassen und das Betriebssystem für jedes Programm den entsprechenden Speicher reservieren.
Wie habt ihr das gelöst? Gute oder schlechte Idee?
-
Habe zwar nicht ganz verstanden, wie das praktisch aussehen soll, klingt aber etwas umstaendlich. Intern in deinem OS kannst du das vielleicht so handhaben, extern fuer die APIs wuerde ich mich da jedoch an die Klassiker FIFO-Queue fuer Tasteneingaben (siehe z.B. BIOS / "readkey"-funktion) und events (Taste xy wurde gedrueckt/losgelassen) und evtl. abgespeckte Bitmaps der Form "Taste gedrueckt? ja/nein" ("keypressed"-funktion) halten.
Kannst auch mal schauen, wie Erhard das in seinem BS geloest hat und die Sache dort evtl. etwas lebhafter diskutieren... Projekt: OS-Development