Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Probleme mit int 9h

18 views
Skip to first unread message

Kai Strnad

unread,
May 7, 2002, 1:06:35 PM5/7/02
to
Hallo, wäre schön wenn mir jemand helfen könnte:

Der Sachverhalt:
ich bin Assembler - Anfänger und beschäftige mich gerade mit dem
Tastatur - Interrupt 9. Ich möchte ihn Umleiten,
die Make und Break Codes abfangen, und diese dann weiterverarbeiten.
Gleichzeitig möchte ich vom Interrupt 9 an den Tastaturpuffer
weitergeleiteten Zeichen auslesen. Dazu habe ich in dem Buch PC Intern 4
von Michael Tischer ein kleines Programm gefunden,welches den
Sachverhalt anschaulich erklärt. Ich habe die interrupt_9 Routine im
Kern übernommen und bei mir eingebaut.
Jetzt ergibt sich folgendes Problem:
Wenn ich nach dem Wiederherstellen der Ursprünglichen ISR (Interrupt
Service Routine) für int 9 eine Zeichenkette auf dem Bildschirm ausgeben
will, erscheint nicht die gewünschte Zeichenkette, sondern viele andere
Zeichen.

Hier also meine Fragen:
1. Warum gibt das Programm nicht die gewünschte, sondern eine andere
Zeichenkette aus ?
2. Wieso ist es notwendig, in der ISR mit assume das Datensegment auf
nothing zu setzen ? (ohne geht es nicht)
3. Muss man das DS wieder auf CS setzen ? Wenn ja, wie macht man das in
einer COM Datei ?


Hier das Programm:
(Betriebssystem: Win2k)
(Assembler:Masm 5.10)


code segment para 'code' ;definition des code-segments
org 100h
assume cs:code, ds:code, es:code, ss:code

start: jmp install_interrupt ;sprung zum eigentlichen prg.-start

int9_ptr equ this dword ;alter interrupt-vektor 9h
int9_ofs dw 0 ;offsetadresse des alten handlers
int9_seg dw 0 ;segmentadresse des alten handlers
tastendruck db 0
message db "hallo welt",13,10,'$'


install_interrupt:
mov ax,3509h ;inhalt des interruptvektors 9h holen
int 21h ;dos-funktion aufrufen
mov int9_seg,es ;segment- und offsetadresse des
mov int9_ofs,bx ;interruptvektors 9h merken
mov dx,offset interrupt_9
mov ax,2509h ;interruptvektor 9h auf
int 21h ;eigene routine verbiegen


keyscan:
main_loop:

mov ah,01h ;feststellen, ob eine taste bereit-
int 16h ;steht
je main_loop ;nein: wiederhole

xor ah,ah ;ja, das zeichen auslesen
int 16h

cmp al,13 ;wenn es return ist, brich ab
je finally

mov ah,02 ;gib das zeichen aus
mov dl,al
int 21h

jmp main_loop

finally:


remove_interrupt:

lds dx,int9_ptr
mov ax,2509h
int 21h

quit:

mov ah,09
lea dx,message
int 21h

mov ax,4c00h ;programm beenden
int 21h

interrupt_9 proc far
;warum diese Anweisung ??
assume cs:code, ds:nothing, es:nothing, ss:nothing

push ax
in al,60h ;scan-code vom tastatur-port holen
cmp al,128 ;wenn < 128 make sonst break

;tu was ....

pop ax ;scancode an alten tastatur-handler
jmp [int9_ptr]

interrupt_9 endp


code ends ;ende des code-segments
end start

Vielen Dank im Vorraus

Kai Strnad

Hubert Seidel

unread,
May 7, 2002, 2:28:45 PM5/7/02
to
Hallo Kai,

"Kai Strnad" <kai.s...@gmx.de> schrieb im Newsbeitrag
news:ab9186$b10$00$1...@news.t-online.com...


> 1. Warum gibt das Programm nicht die gewünschte, sondern eine andere
> Zeichenkette aus ?

Weil Du die Nummer der Taste ausgiebst, aber das große A den
ASCII-Wert 65 hat. Ein Tastaturtreiber (sowas in der Art programmierst Du
ja)
muss die entsprechenden Codes in ASCI erst wandeln.

> 2. Wieso ist es notwendig, in der ISR mit assume das Datensegment auf
> nothing zu setzen ? (ohne geht es nicht)

Das DS aus nothing gesetzt wird und funktioniert ist mehr oder weniger
eh unsauber. Setzte DS auf CODE.
Auch wenn es funktioniert, ist es sinnvoller/einleuchtender DS
auf CODE zu haben.

> 3. Muss man das DS wieder auf CS setzen ? Wenn ja, wie macht man das in
> einer COM Datei ?

PUSH CS
POP DS

oder

MOV AX,CS
MOV DS,AX wenn Du AX "frei" haben solltest

> Hier das Programm:
> (Betriebssystem: Win2k)
> (Assembler:Masm 5.10)
>
> code segment para 'code' ;definition des code-segments
> org 100h
> assume cs:code, ds:code, es:code, ss:code

Hier ist ja auch DS auf CODE. Also ok.

> ;warum diese Anweisung ??
> assume cs:code, ds:nothing, es:nothing, ss:nothing

Hier muss ich leider passen. (nothing habe ich nie verwendet :)

Der folgende Befehl bezieht sich auf DS: da kein Segment angegeben ist.
> jmp [int9_ptr]

Ich bevorzuge um sicher zu sein entweder:
jmp [cs:int9_ptr] bzw.
cs: jmp [int9_ptr]

In einer ISR wird ja aus "irgendwo" gesprungen. D.h.
kein Register ist besonders vorinitialisiert, und muss beim
verlassen alle verwendeten Register restaurieren.
Da beim Sprung DS ja wieder restauriert ist _muss_ CS angegeben werden.

mfg. Herby

--
Mailto:Hubert...@T-Online.de
http://meine.seite.bei.t-online.de

Willi Marquart

unread,
May 7, 2002, 5:14:51 PM5/7/02
to
Kai Strnad <kai.s...@gmx.de> wrote:

>1. Warum gibt das Programm nicht die gewünschte, sondern eine andere
>Zeichenkette aus ?

Weil Du mit
lds dx,int9_ptr
dafür gesorgt hast, dass DS nicht mehr auf Dein Code-Segment zeigt.

>2. Wieso ist es notwendig, in der ISR mit assume das Datensegment auf
>nothing zu setzen ? (ohne geht es nicht)

Weil in der Interrupt-Routine DS nicht auf Dein Code-Segment zeigt und
damit
jmp [int9_ptr]
in die Irre geht.

Mit Assume DS:nothing macht der Assembler daraus
jmp cs:[int9_ptr]
und das klappt.

>3. Muss man das DS wieder auf CS setzen ? Wenn ja, wie macht man das in
>einer COM Datei ?

Siehe Huberts Mail, einmal soll er auch Recht haben :-).

Gruss Willi

Kai Strnad

unread,
May 8, 2002, 1:16:34 PM5/8/02
to
Vielen Dank, jetzt geht es!

Kai

Matthias Paul

unread,
May 13, 2002, 8:37:20 PM5/13/02
to
Am 2002-05-07 schrieb Kai Strnad:

> ich bin Assembler - Anfänger und beschäftige mich gerade mit dem
> Tastatur - Interrupt 9.

Da hast Du Dir aber direkt eine der komplizierteren Sachen
ausgesucht... ;-) Auf den ersten Blick sieht das sehr einfach
aus, aber der Teufel steckt ja bekanntlich im Detail...

> Ich möchte ihn Umleiten, die Make und Break
> Codes abfangen, und diese dann weiterverarbeiten. Gleichzeitig möchte
> ich vom Interrupt 9 an den Tastaturpuffer weitergeleiteten Zeichen
> auslesen. Dazu habe ich in dem Buch PC Intern 4 von Michael Tischer
> ein kleines Programm gefunden, welches den Sachverhalt anschaulich
> erklärt.

Hm, leider habe ich selbst nur PC Intern 2.0 hier, aber auch schon
in dieser Ausgabe war Michael Tischers Buch nicht mehr auf der Höhe
der Zeit was die Programmierung des Tastaturkontrollers seit der
Einführung des ATs angeht - leider hat sich das, bei allem Lob,
das das Buch ansonsten als gut verständliche Einführung verdient,
offenbar selbst in der 4.0er Ausgabe noch nicht geändert...

Es ist ein weitverbreiteter, aber offenbar nicht kaputtzukriegender
Irrglaube, daß man auf ATs die Scancodes von der Tastatur noch
immer in der gleichen Weise lesen kann, wie man das von PCs und
XTs gewohnt war. Ich vermute, daß das daran liegt, daß es eben
"scheinbar" funktioniert - so schreibst Du ja auch am Ende des
Threads, "jetzt geht es". Kai, ich kann Dir versichern, das
sieht nur so aus. ;-)
Leider kann man gerade bei diesem Themenkomplex nicht sagen,
"wenn es bei mir funktioniert, wird das auch in anderen
Konfigurationen der Fall sein". Wenn bei Dir im weiteren
Testverlauf mit dieser XT-Style-INT 09h-Routine seltsame
Effekte auftreten, dann weißt Du, wo Du suchen mußt.
Sollten z.B. plötzlich Tastendrücker scheinbar verschluckt
werden, beim Bewegen in einem Editor plötzlich unvermittelt
Zahlen in den Text eingestreut werden (die Du oft erst viel
später dort findest und Dich dann wundest, wie die dort hin-
gekommen sind), sollte die Tastatur plötzlich "aus dem Nichts
heraus" in einen Shift-Zustand gehen (also z.B. Großbuchstaben
oder Steuerzeichen produzieren, obwohl Du die entsprechende
Modifizierertaste überhaupt nicht gedrückt hast, sollte Deine
Maus plötzlich verrückt spielen oder ruckeln oder sollte die
Kiste gar plötzlich unvermittelt hängen oder booten, dann ist
das eben auf darauf zurückzuführen, daß Du auf einem AT nicht
die AT-Methode verwendest, um auf die Tastatur zuzugreifen.

Grundsätzlich kann es auch passieren, daß Dein INT 09h-Handler
auch auf einem PC/XT versagt, weil Du plötzlich die DIP-Switches
liest und nicht mehr den Tastaturport. Siehe PORTS.LST in RBIL61.

Und bei ATs und PS/2 Rechnern gibt es erstens 'zig verschiedene
Betriebsmodi, in denen die Kombination aus Tastaturcontroller
und Tastatur gerade arbeiten könnte (drei Codesets sowie
Translation/Pass Through Modes), dann wird die PS/2-Maus über
den gleichen Port gelesen, und es gibt sowieso jede Menge
Hardware-Unterschiede, auf die man speziell eingehen müßte.
Und manche ganz neuen Rechner haben gar überhaupt keinen
Port 60h mehr, wo man die Scancodes auslesen könnte...

Leider kann ich in der Kürze der Zeit nicht auf alle diese Dinge
eingehen. Aber zumindest kann ich ein paar kurze Hinweise geben:

Ab dem AT ist es eigentlich nicht erlaubt, daß irgendein Programm -
außer dem Tastaturtreiber selbst - den INT 09h übernimmt und per
direktem Portzugriff auf Port 60h etc. die Tastatur liest; der
Tastaturtreiber im BIOS kennt natürlich seine spezielle Hardware
und weiß, wie er damit umgehen muß, und auch gängige Tastaturtreiber
(von diesen Minimal-Treibern mit ein paar Hundert Bytes mal
abgesehen) berücksichtigen etliche Sonderfälle, sonst muß eben
der Hardware-Hersteller seinen eigenen Tastaturtreiber zur
Verfügung stellen. Und dann gibt es natürlich auch noch diverse
Tastaturgenerationen (ich meine jetzt nicht so Kleinkram wie
"Windows"- oder "Internet"-Tasten (das sind nur erweiterte MF2-
Tastaturen), sondern PC-, AT-, MF1-, MF2-, Host Connected 122-
Tasten-Keyboards, sowie etliche Fernost-Tastaturen).
Grundsätzlich ist aber zu sagen, daß Du der Tastatur vor dem
Auslesen des Port 60h das Kommando "Disable" schicken mußt,
dann den Port auslesen (wie vom PC/XT her bekannt) und danach
mußt Du wieder ein "Enable" an die Tastatur schicken. Wenn das
nicht geschieht, können Zeichen verloren gehen oder eben viele
der oben angesprochenen Dinge passieren.
Leider ist das konkrete Prozedere ziemlich timing-abhängig,
insofern mußt Du die dafür notwendige Warteschleife an die
Rechnergeschwindigkeit anpassen - das ist also alles etwas
frickelig. Und: Auf einem PC/XT darfst Du das auf keinen Fall
so machen, dann hängt sich so eine Maschine normalerweise auf.
Insofern mußt Du also wenigstens zwischen diesen beiden Rechner-
generationen unterscheiden, besser ist es jedoch auch PS/2-
Rechner gesondert zu behandeln.

Also, Finger weg vom INT 09h, es sei denn, Du willst wirklich
einen Tastaturtreiber schreiben oder Du arbeitest auf einem
XT. Glücklicherweise gibt es für die anderen Fälle ab dem AT
den INT 15h/AH=4Fh. Das ist ein Broadcast, der aus dem INT 09h
heraus aufgerufen wird *nachdem* der Scancode bereits gelesen
wurde. Alle interessierten Treiber können sich nun in die
INT 15h/AH=4Fh-Kette hängen und unter Beachtung einiger
etwas umständlicher Konventionen mit dem Scancode, der in
AL steht, mehr oder weniger machen, was sie wollen, z.B.
den Code auf einen anderen Scancode ummappen, ihn einfach
ignorieren, ihn verwerfen usw. Je nachdem, was dabei
herauskommt, verwirft der INT 09h-Handler den Code, wenn
er wieder die Kontrolle zurückbekommt oder er arbeitet mit
dem alten oder dem ggfs. neuen Scancode weiter.

Der Vorteil der INT 15h/AH=4Fh Methode liegt klar auf der Hand:
Die Treiber kommen sich nicht mehr beim konkurrierenden
Hardware-Zugriff im INT 09h ins Gehege, und keiner außer
dem wirklichen Tastaturtreiber muß sich um die ganzen
Hardware-Details kümmern. INT 15h/AH=4Fh wird aller
Wahrscheinlichkeit nach auch noch mit USB-Tastaturen
funktionieren, PORT 60h aber nicht, es sei denn, der
Rechner bietet dafür noch eine Legacy-Emulation an.

Viele Details dazu findest Du unter INT 09h, INT 15h/AH=4Fh
und PORT 60h in Ralf Brown's Interrupt Liste 61 in den Dateien
INTERRUP.LST und PORTS.LST. Und in der in Kürze zu erwartenden
RBIL62-Ausgabe sollten da gut 300 Kb Detailbeschreibungen zur
Tastatur-Hardware und zum softwareseitigen Tastaturhandling
hinzukommen, wenn Ralf genug Zeit dafür findet, meine ganzen
Ergänzungen einzuarbeiten.

Viele Grüße,

Matthias

--
<mailto:Matthi...@post.rwth-aachen.de>; <mailto:mp...@drdos.org>
http://www.uni-bonn.de/~uzs180/mpdokeng.html; http://mpaul.drdos.org


0 new messages