Autor Thema: Tastatur Treiber geht als Interrupt nicht  (Gelesen 7113 mal)

Biehler Productions

  • Beiträge: 51
    • Profil anzeigen
    • http://bielos.de.tk
Gespeichert
« am: 10. February 2006, 21:13 »
Hi,
ich baue grad meinen Tastatur Treiber zusammen.
Ich lade meinen Treiber an die Stelle 7c0h:3600h.
Dort wird dann mittels:

Keyboard_driver:
PUSH ES
PUSH AX
PUSH DS
MOV AX,0
MOV ES,AX
CLI
MOV WORD [ES:4*9h],int9h
MOV WORD [ES:4*9h+2],CS
MOV WORD [ES:4*16h],int16h
MOV WORD [ES:4*16h+2],CS
STI
POP DS
POP AX
POP ES
RET

Der Int 9h umgebogen und der int 16h

Im OS will ich dann in einem INT Aufruf ein Zeichen einlesen und ausgeben:


rd_z:
;mov ah,0
;int 16h
CMP BYTE [scan],0h
JE rd_z
MOV AL,[scan]
MOV BYTE [scan],0h
mov ah,0eh
int 10h
POPA
iret


Dieser Int hätte die Nummer 02h.
Rufe ich ihn dann im OS auf:

mov ah,02h
int 21h


Wird nichts ausgegeben.

Schreibe ich aber hingegen folgendes direkt im OS Code (wird also jetzt nicht als INT aufgerufen):

rd_z1:
;mov ah,0
;int 16h
CMP BYTE [scan],0h
JE rd_z1
MOV AL,[scan]
MOV BYTE [scan],0h
mov ah,0eh
int 10h
jmp rd_z1

Geht es.
Ich benutzte BOCHS.
Woran kann das liegen?
Den Treiber schließe ich eigentlich aus, aber der Rest erscheint mir eigentlich ganz logisch und fehlerfrei.
?

Falls jemand den Treiber in Verdacht hat, hier mal der Code:


Keyboard_driver:
PUSH ES
PUSH AX
PUSH DS
MOV AX,0
MOV ES,AX
CLI
MOV WORD [ES:4*9h],int9h
MOV WORD [ES:4*9h+2],CS
MOV WORD [ES:4*16h],int16h
MOV WORD [ES:4*16h+2],CS
STI
POP DS
POP AX
POP ES
RET


int16h:
; hier muss der BIOS INT 16H nacjhgebildet werden
;CMP AH,0h
;JnE int16h_nothing
PUSH ES
PUSH DS
PUSH AX
CHECK_SCAN:
CMP byte [scan],0
JE CHECK_SCAN
MOV AL,[scan]
MOV byte [scan],0

int16h_nothing:
POP AX
POP DS
POP ES
IRET

;hier beginnt der Keyboardtreiber
int9h:

pusha                       ;alle Register retten
in AL,60h                   ;Port 60 lesen
;and AL,AL                   ;AND mit sich selbst - setzt "Sign" Flag, wenn >=128
;js Weiter                  ;Taste losgelassen - also nichts tun
cmp al,129
JAE Weiter
;:::::::::::::
;Hier das tun, was immer man tun will, wenn einer ne Taste drückt.
mov bl,al
lea si,[scancode]
check_scan:
lodsb
cmp bl,al
JE scan_ok
cmp word [si],0AAAAh
JE Weiter
inc si
inc si
inc si
jmp check_scan

scan_ok:
lodsb
mov byte [scan],al
;:::::::::::::
Weiter:                    ;hierhin wird gesprungen, wenn nur losgelassen
mov AL,20h                  ;Code 20h für "reset PIC"
out 20h,AL                  ;in den PIC (Port 20h) schreiben
popa                        ;alle Register wiederholen
iret                        ;und Int beenden

bitmaster

  • Troll
  • Beiträge: 1 138
    • Profil anzeigen
    • OS-64 = 64 Bit Operating System
Gespeichert
« Antwort #1 am: 10. February 2006, 23:51 »
Hi,

also ich weiß jetzt nicht genau wo der Fehler ist. Aber mir ist folgendes aufgefallen in diesem Code:

rd_z:
;mov ah,0
;int 16h
      CMP BYTE [scan],0h
      JE rd_z
      MOV AL,[scan]
      MOV BYTE [scan],0h
      mov ah,0eh
      int 10h
POPA
iret

Wo ist denn da das pusha? Und bei den Interruptfunktionen würde ich ds und es immer neu setzten, da man ja nie weiß ob sie auch da sind wo sie sein müssen. Ansonsten sind mir keine Fehler aufgefallen.

bitmaster
In the Future everyone will need OS-64!!!

Biehler Productions

  • Beiträge: 51
    • Profil anzeigen
    • http://bielos.de.tk
Gespeichert
« Antwort #2 am: 11. February 2006, 09:18 »
Das PUSHA befindet sich hier:

int21h:
[b]pusha[/b]
cmp ah,0h
JE pr_z
cmp ah,01h
JE pr_str
cmp ah,02h
JE rd_z
cmp ah,03h
JE rd_z_a
cmp ah,04h
JE rd_str
mov al,1  ;Fehlercode
int21h_e:
popa
iret


Werd das heute mal ausprobieren mit DS und ES neu setzen, vielleicht bringts was.

EDIT:
Es wird imer dümmer irgendwie.
Ich habe jetzt mal eine Funktion geschrieben:

;---------------------------------------------------------------------
;-- Frage die Tastatur ab
;------------------------------------------------------------------------
GETC:
CMP BYTE [scan],0
JE GETC
MOV AL,[scan]
MOV BYTE [scan],0
RET

Füge ich den Code wo ein:

call GETC
mov ah,0eh
int 10h

Wird ein Buchstabe ausgegeben.
Packe ich den allergleichen Coe aber in die Int Routine:



;###Int 21h
int21h:
mov al,"w"
mov ah,0eh
int 10h
[b]
call GETC
mov ah,0eh
int 10h
jmp $
[/b]
pusha
cmp ah,0h
JE pr_z
cmp ah,01h
JE pr_str
cmp ah,02h
JE rd_z
cmp ah,03h
JE rd_z_a
cmp ah,04h
JE rd_str
mov al,1  ;Fehlercode
int21h_e:
popa
iret


Geht nichts.
Da kann ich sooft INT 21h aufrufen wie ich will.
Daher dachte ich, vielleicht geht der Interrupt nicht.
Deshalb habe ich folgende Codesequenz oben angefügt:

mov al,"w"
mov ah,0eh
int 10h

Das W wird ausgegeben, der Buchstabe aber nicht.
Ich meine, generell ist es mir wurscht, ob ich die Tastatureingaben per Interrupt oder per Funktion einlese, allerdings ist es per Interrupt einfach komfortabler und außerdem ist es doch ein total unlogischer Fehler.
Kann das an BOCHS liegen?

Biehler Productions

  • Beiträge: 51
    • Profil anzeigen
    • http://bielos.de.tk
Gespeichert
« Antwort #3 am: 13. February 2006, 18:46 »
Also, nachdem ich das Problem mit dem Interrupt nicht lösen konnte, versuche ich es nun komplizierter:
Ich mache, wenn ich ein Zeichen einlesen will, einen FAR CALL auf eine Adresse, die in der VAriable GET_CHAR liegt.
Das entsprechende CS steht in der VAriable GET_CHAR_CS.

Soweit so gut.
Lese ich nun so ein Zeichen ein, funktioniert alles.
Sobald ich allerdings meinen Tastaturtreiber starte, und mit einem FAR CALL anspringe, geht nix mehr.
Der Tastaturtreiber setzt die beiden VAriablen
GET_CHAR
GET_CHAR_CS
neu und füllt sie eben mit den DAten des Treibers.

Zur Veranschaulichung mal der Code:



Keyboard_driver:
PUSHA
PUSH ES
PUSH DS
MOV AX,CS
MOV ES,AX
MOV DS,AX
MOV AX,0
MOV ES,AX
CLI
MOV WORD [ES:4*9h],int9h
MOV WORD [ES:4*9h+2],CS
;MOV WORD [ES:4*16h],int16h
;MOV WORD [ES:4*16h+2],CS
STI
MOV BX,GETC
MOV AX,CS
MOV AX,07c0h
MOV DS,AX
MOV AX,CS
MOV [DS:153h],AX
MOV [DS:151h],BX
POP DS
POP ES
POPA
RETF


GETC:
CMP BYTE [scan],0
JE GETC
MOV AL,[scan]
MOV BYTE [scan],0
RETF


Bei dem obigen Code werden eben die VAriablen neu gesetzt.
Die FUnktion GETC liest eben ein Zeichen ein.
Das funktioniert noch.
JEtzt der Treibercode:


;hier beginnt der Keyboardtreiber
int9h:

pusha                       ;alle Register retten
[b]PUSH ES
PUSH DS[/b]
MOV AX,CS
MOV ES,AX
MOV DS,AX
in AL,60h                   ;Port 60 lesen
;and AL,AL                   ;AND mit sich selbst - setzt "Sign" Flag, wenn >=128
;js Weiter                  ;Taste losgelassen - also nichts tun
cmp al,129
JAE Weiter
;:::::::::::::
;Hier das tun, was immer man tun will, wenn einer ne Taste drückt.
mov bl,al
lea si,[scancode]
check_scan:
lodsb
cmp bl,al
JE scan_ok
cmp word [si],0AAAAh
JE Weiter
inc si
inc si
inc si
jmp check_scan

scan_ok:
lodsb
mov byte [scan],al
;:::::::::::::
Weiter:                    ;hierhin wird gesprungen, wenn nur losgelassen
mov AL,20h                  ;Code 20h für "reset PIC"
out 20h,AL                  ;in den PIC (Port 20h) schreiben
[b]POP DS
POP ES[/b]
popa                        ;alle Register wiederholen
iret                        ;und Int beenden


Es kommt hier maßgeblich auf das fett markierte an.
Lasse ich nämlich die POP und PUSH Befehle im Code stehen (muss ich ja), geht nix mehr.
Lasse ich sie weg, kann ich Zeichen einlesen.
Es tritt dann zwar auch unerklärliche fehler auf, aber erstmal muss das gelöst werden.
Ich verstehs überhaupt nicht, wo da ein Fehler sein kann.
Mein Stack liegt bei 9000h:200h. Da ist afaik kein BIOS Kram oder sonstiger reservierter Speicher.

Übrigens:
Sichere ich die beiden Segmentregister mittels:

MOV CX,DS
MOV BX,ES

und schreibe sie dementsprechend zurück, geht es auch nicht.

joachim_neu

  • Beiträge: 1 228
    • Profil anzeigen
    • http://www.joachim-neu.de
Gespeichert
« Antwort #4 am: 13. February 2006, 19:02 »
Ich hab meine lieben Probleme mit dem Setzen der LEDs und allgemein mit dem Senden irgendwelcher Befehle an die Tastatur. Wie habt ihr das regelt? Werden da immer Ints erzeugt, wenn ACKs kommen, etc? Danke!
http://www.joachim-neu.de | http://www.orbitalpirates.de | http://www.middleageworld.de

System: 256 RAM, GeForce 2 MX 400, AMD Athlon XP 1600+, Windows XP, 1x Diskette, 1x DVD-ROM, 1x CD-R(W) Brenner,...

bitmaster

  • Troll
  • Beiträge: 1 138
    • Profil anzeigen
    • OS-64 = 64 Bit Operating System
Gespeichert
« Antwort #5 am: 14. February 2006, 14:32 »
Zitat von: joachim_neu
Ich hab meine lieben Probleme mit dem Setzen der LEDs und allgemein mit dem Senden irgendwelcher Befehle an die Tastatur. Wie habt ihr das regelt? Werden da immer Ints erzeugt, wenn ACKs kommen, etc? Danke!
Also ich habe es so gemacht: Eine Variable von einem Byte erstellen mit den Wert NULL. Dann wenn du eine der Tasten drückst prüfst du ob es sich dabei um NUMLOCK, CAPSLOCK oder SCROLLLOCK handelt. Ist das der Fall, dann soll das jeweilige Bit in der Variable umgedreht werden. Und wenn es NULL ist, die LEDs löschen, ansonsten setzten.

Beispiel:
;Wurde eine LOCK Taste gedrückt
;wenn ja gehe nach LEDS
...
LEDS:
CapsLock gedrückt?
ja -> zuständiges Bit in der LEDVar (Variable) umdrehen und nach SLED
NumLock gedrückt?
ja -> zuständiges Bit in der LEDVar umdrehen und nach SLED
ScrollLock gedrückt?
ja -> zuständiges Bit in der LEDVar umdrehen und nach SLED
SLED:
Welches Bit in LEDVar ist gesetzt?
Dann das entsprechende LED setzten.

;LEDVar könnte so aussehen
76543210

0=CAPS
1=NUM
2=SCROLL
3-7 = nicht besetzt

Wie du die LEDs setzt weißt du aber, oder? Ansonsten frag mich per MSN.

bitmaster
In the Future everyone will need OS-64!!!

 

Einloggen