Tastaturabfrage

Hier dürfen auch unregistrierte Besucher posten.
Gast

Tastaturabfrage

Beitrag von Gast »

Hallo,
hab da mal ne Frage zu "Debug".

Um ein kleines Programm unter Debug während des Laufs zu stoppen, hatte ich, bild ich mir ein, einen 4 Zeiler wie folgt.

Mov dx,378
mov al,01
out dx,al
mov al,00
out dx,al
in al,60
cmp al,01
jnz (nach mov al,01)
int 21

Funtioniert jedoch nicht, da" in al,60" die ASII Werte in den Akku holt und ich somit keinen Vergleich mit 1 machen kann.
Weiß jemand, wie ich das Tastatur Statusflag abfragen kann?!
MfG

Berndt
Benutzeravatar
Odin
DOS-Guru
Beiträge: 712
Registriert: Fr 3. Feb 2006, 16:52

Beitrag von Odin »

Willst Du wissen, ob eine Taste gedrückt wurde? Wenn ja, dann geht das wie folgt:

Code: Alles auswählen

MOV AH, 01h   // Funktion für Tastaturstatus
INT 16h       // Interrupt 16h aufrufen
JNZ ...       // Wenn Zero-Flag = 0, dann wurde eine Taste gedrückt
Das hat allerdings recht wenig mit DOS zu tun, sondern ist simple Maschinensprache ;-)

Gruss,
Odin
"640k ought to be enough for anybody." - Bill Gates (1981)
"Windows 95 needs at least 8MB RAM." - Bill Gates (1996)
... also braucht niemand Windows 95 !!!
Gast

Beitrag von Gast »

Hallo Odin,

Dank für Deine Antwort !
Das ist natürlich auch eine Möglichkeit. Werd's gleich mal probieren.
Das Problem beim Interrupt ist jedoch, daß dadurch der Prozessablauf gestoppt wird und relativ viel Zeit kostet, wenn ich richtig informiert bin.

Deswegen kam ein schlauer Ingenieur von Siemens, dessen Namen und Adresse ich jedoch nicht mehr weiß, auf die Lösung mit der direkten Einlesung über -- IN AL, 60 (Tastaturport) --
Leider habe ich da aber irgenwo einen Denkfehler gemacht .

Werd aber gleich mal sehen, wieviel Zeit Deine Sequenz braucht. Vielleicht ja sogar weniger.
Also, nochmals vielen Dank und einen schönen Tag

Berndt
bttr

Beitrag von bttr »

Ich glaube, jetzt habe ich endlich verstanden, was du überhaupt meinst. Setze die 1 einfach in Anführungszeichen und schon vergleichst du zwei ASCII-Codes.
Gast

Beitrag von Gast »

High bttr,

die 1 in " 1" setzen geht nicht , da Debug das nicht annimmt.

Angenommen ich hab in Debug ein kleines Assemblerprogramm geschrieben, und möchte, das ich das Programm, wenn ich es gestartet habe, mit einer x-beliebigenTaste anhalten kann.

Dazu sollte der Controller ständig die Tastatur abfragen, ob irgendeine Taste gedrückt ist und den Zustand (0 oder 1) in den Akku einlesen. Nur welches Bit ist das, und wie fragt man das ab.

Der Tastaturport ist "60", also
" IN AL,60 " stimmt schon. Der Wert des Bits (0 oder 1) müßte dann im Low Byte des Akkus stehen, damit er dann vergleichen kann, ob"AL" 00 oder 01 ist.
Ich habe aber immer nur den Hex Code der gedrückten Taste im Akku.

Vielleicht geht diese Art der Tastaturabfrage aber auch nur mit älteren Dos Versionen. DOS 5.0 vielleicht.

Die Lösung von Odin funktioniert für sich allein wunderbar. Nur in Verbindung mit einem Programm hängt sich DOS auf.
Benutzeravatar
Odin
DOS-Guru
Beiträge: 712
Registriert: Fr 3. Feb 2006, 16:52

Beitrag von Odin »

Der Tastaturport 60h gibt auch nur den Scancode der gedrückten Taste aus. Das bedeutet, dass Du bei einem Vergleich mit 01h abfragst, ob die ESC-Taste gedrückt wurde.

Wenn ich mich recht erinnere, dann musst Du den Inhalt mit 00h vergleichen, das beudeutet nämlich, dass kein Scancode vorliegt - also auch keine Taste gedrückt wurde.

Das der Interrupt nicht funktioniert, könnte möglicherweise an DOS liegen, ich weiss es aber nicht, ich hab das noch nie ausprobiert.
"640k ought to be enough for anybody." - Bill Gates (1981)
"Windows 95 needs at least 8MB RAM." - Bill Gates (1996)
... also braucht niemand Windows 95 !!!
bttr

Beitrag von bttr »

@Gast

Es gibt freie Assembler in allen möglichen "Farben". Warum willst du da ausgerechnet mit Debug ein Programm schreiben? siehe z.B. http://www.bttr-software.de/links/#asm

Ansonsten habe ich dich wohl doch falsch verstanden. Wenn du die Frage also gleich gut formuliert hättest, dann wären solche Mißverständnisse gar nicht erst aufgekommen. ;-)

Für NASM würde der Quellcode für ein Programm, das abbricht, sobald eine Taste (auch Shift, Ctrl, Alt) gedrückt wurde, so aussehen:

Code: Alles auswählen

Org 100h

start:
  in al, 64h  ; Status-Register des Tastatur-Controllers lesen
  and al, 1   ; alles außer Bit 0 verwerfen
  or al, al   ; auf 0 prüfen (keine neuen Daten vorhanden)
  jz start    ; wieder von vorn beginnen
  ret
EDIT: Die entsprechenden Infos dazu findest du z.B. in Help-PC oder Ralf Browns Interrupt-Liste (Datei "ports.*") ebenfalls auf meiner Homepage erhältlich.
Benutzeravatar
Dosenware
DOS-Gott
Beiträge: 3745
Registriert: Mi 24. Mai 2006, 20:29

Beitrag von Dosenware »

Kann man den Kram nicht einfach an einen Hardwareinterupt (int 9) haengen?

Spart das staendige abfragen und USB-Tastaturen duerften den Kram emuliert bekommen, was dann also auch kein Problem darstellen sollte...

Edit: na gut, in einer warteschleife macht das natuerlich wenig sinn...
Benutzeravatar
Odin
DOS-Guru
Beiträge: 712
Registriert: Fr 3. Feb 2006, 16:52

Beitrag von Odin »

Er hat ja geschrieben, dass er keinen Interrupt will...
"640k ought to be enough for anybody." - Bill Gates (1981)
"Windows 95 needs at least 8MB RAM." - Bill Gates (1996)
... also braucht niemand Windows 95 !!!
Benutzeravatar
Dosenware
DOS-Gott
Beiträge: 3745
Registriert: Mi 24. Mai 2006, 20:29

Beitrag von Dosenware »

Bei ihm gehts um einen Softwareinterrupt...bei mir um einen Hardwareinterrupt (sprich: ich will nicht die Tastatur abfragen, die soll schon selbst sagen wenn was ist...)

diese realisierung hat den Vorteil, das das Programm irgendwas anderes machen kann, bei Tastendruck gehts dann automatisch an der richtigen stelle weiter (sonst braucht man eine Abfrageschleife - was durchaus eine verzoegerte Reaktion bedeuten kann), hat aber den Nachteil das dies fuer harte Echtzeitbedingungen ungeeignet ist (durch den Interrupt treten unvorhersehbare verzoegerungen im Programmablauf auf) und ist fuer reine Warteschleifen ziemlich sinnlos...

Edit: oder mal schnell in Pascal ausgedrueckt:

Code: Alles auswählen

uses dos;
var count:longint;
var OldInterrupt: procedure;
procedure NewInterrupt; interrupt;
 begin
  inc(count);
  OldInterrupt;
  writeln(count);
 end;
{int09=Tasta}
 begin
  count:=0;
  GetIntVec ($09, @OldInterrupt);{ Uebergebe den Interruptvector $09 an OldInterrupt}
  SetIntVec ($09, @NewInterrupt);{ Setze den Interruptvector $09 auf NewInterrupt}
  repeat;
  {Hier ist wirklich nix}
  until count>9;
  SetIntVec ($09, @OldInterrupt);
end.
elianda
DOS-Übermensch
Beiträge: 1150
Registriert: Mi 31. Jan 2007, 19:04
Wohnort: Halle
Kontaktdaten:

Beitrag von elianda »

Harte Echtzeitbedingungen? :P

Bei einem PC ist das doch absolute Augenwischerei. Wenn du hier etwas halbwegs Echtzeit machen willst, musst du das durch extra Hardware erledigen. Ansonsten musst du durch nicht ganz triviale Routinen die Zyklen vorher ausmessen, beim Pentium durch den integrieten MSR Counterm beim 486er wirds noch viel schwerer.
Aber das geht auch nicht immer.

Selbst Latenzen wie beim C64 fuer Interrupts (6 us) gehoeren beim PC in den Bereich der Maerchen und MYthen.
[/quote]
Benutzeravatar
Odin
DOS-Guru
Beiträge: 712
Registriert: Fr 3. Feb 2006, 16:52

Beitrag von Odin »

Ob nun Hardware- oder Softwareinterrupt, das macht letztenendes ja kaum einen Unterschied... der Softwareinterrupt ist zwar langsamer, aber bremsen können beide...

Ich glaube, es wäre sinnvoll wenn sich der Autor dieses Threads zu dem Ziel dieser Sache äußern würde - dann könnte man vielleicht eher eine passende Lösung finden...
"640k ought to be enough for anybody." - Bill Gates (1981)
"Windows 95 needs at least 8MB RAM." - Bill Gates (1996)
... also braucht niemand Windows 95 !!!
elianda
DOS-Übermensch
Beiträge: 1150
Registriert: Mi 31. Jan 2007, 19:04
Wohnort: Halle
Kontaktdaten:

Beitrag von elianda »

Der Befehl in al, 64h dauert vermutlich wesentlich laenger als der Rest des Codes. So dass eine direkte Abfrage oder eine Abfrage ueber Soft Int nahezu dieselbe Zeit dauern duerfte. (Unter der Annahme, dass der Soft Int auch nur einmal in al,64h ausfuehrt)

Um das herauszufinden, kann man mit Debug auch mal schnell in den Bios Code schauen oder zB in den Source von 'keypressed' unter TP.
Benutzeravatar
Dosenware
DOS-Gott
Beiträge: 3745
Registriert: Mi 24. Mai 2006, 20:29

Beitrag von Dosenware »

@Odin

ich sags mal so: wenn es nur darum geht einen Tastendruck mitzukriegen, reicht es im Interrupt einen wert im Speicher zu setzen.
(mov x,y - mehr muss da nicht gemacht werden)

diesen Wert im Speicher zu ueberpruefen geht dann verdammt schnell - zumal dieser dann sehr wahrscheinlich sowieso im Cache ist...

und bremsen wird er wahrscheinlich nicht, denn solange du nicht im Interruptregister die Interrupts sperrst, werden sie sowieso ausgefuehrt...(es sei denn der IRQ wird erst per SetIntVec freigeschalten; mit IRQs habe ich mich bisher noch nicht auf Assemblerebene herumgeschlagen - zumindest nicht auf PCs)
Gast

Beitrag von Gast »

Hallo liebe Leute,
da hab ich ja eine ganze Lawine losgetreten. Schön, das es so viele Menschen gibt, die sich noch Gedanken machen !
Danke für Eure Antworten.

Es ist einfach so, daß ich für Demonstrationszwecke (privat) eine kleine Routine bräuchte, mit der ich auf x-beliebigen Tastendruck oder auch eine bestimmte Taste hin eine laufende Schleife (z. B. Rechteckgenerator, Ausgabe an Bit 1) unterbrechen kann. Die Abfrage ist ein Bestandteil der Schleife.
z.B. diese Schleife

MOV DX,378 (Parallelschnittstelle initialisieren)
MMOV,AL,01 (Bit 1=1)
OUT DX,AL (Ausgabe an Parallelschnittstelle = 1)
MOV,AL,00 (Bit 1=0)
OUT DX,AL (Ausgabe an Parallelschnittstelle = 0)

Hier sollte jetzt die Tastaturabfrage geschehen, und die Schleife sollte zu
MOV AL,01
zurückspringen, oder das Programm bei Tastendruck abbrechen(z.B. INT 21)
Ich hatte früher mit dem verflixten "IN AL, 60"
und einem Vergleich das ganze schon am Laufen, habe jedoch die Unterlagen nicht mehr.
Was mich interessieren würde, was genau kommt rein beim IN-Befehl
und steht dann in AL oder auch AX ?!
Was, und wie kann ich dann vergleichen ?!

Nochmals vielen Dank für Eure Bemühungen und einen wunderschönen Tag


Berndt







I
Antworten