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


Anmelden zum Antworten