Borland Pascal 7.0 - Frage zu Tastaturpuffer leeren und Polling

  • Mahlzeit :Bier


    da ich jetzt mal endlich Zeit habe wieder was mit Pascal zu programmieren, brauche ich doch noch ein wenig Nachhilfe... :tasskaff

    Es geht um das Auslesen des Tastaturpuffers. Wenn ich eine Taste gedrueckt habe, kann ich ja entweder am Port $60 oder im AX Register den Scancode der Taste auslesen. An den Adressen $0417 und $0418 sehe ich die Statusbits der Strg, Alt usw. Tasten.


    Wie mach ich das aber in (sauberem) Assembler, den Tastaturpuffer nach Auslesen wieder zu leeren? Sonst funktioniert das Polling bei immer nur bis die erste Taste gedrueckt wurde :mist


    Ein kleines Beispiel wuerde mir da auf die Spruenge helfen :wizard


    Den bisherigen Quellcode haenge ich gleich mal an oder versuche ihn hier einzubetten.



    Beispiel 1: damit habe erstmal angefangen, die Funktion der Tastaturabfrage zu verstehen und zu sehen, was an den Adressen 417h und 418h passiert


    Beispiel 2 mit Port $60 und einer EmptyKeyBuffer Funktion. Ich moechte aber diese haesslichen Inline-Anweisungen loswerden. Pascal Programme mit diesem Inline-Code laufen nicht auf Windows NT Systemen. Sauberes Assembler hingegen geht ohne Probleme auch auf NT/2000/XP...


    Die Port $60 Geschichte laeuft ab PC AT und aufwaerts, aber (laut Aussage meines Pascal Kompendiums) nicht mehr auf PC XT. Ich habe zwar "nur" 486er hier stehen, moechte aber die XTs ungern von meinem Programmen ausschliessen.

  • habe das Beispiel mit dem Port $60 mal weiter verfeinert und aufgeraeumt, aber diese Inline-Anweisungen stoeren mich halt noch...



    Die INLINE($FA); und INLINE($FB); Anweisungen sollen den Assembleranweisungen CLI und STI entsprechen, aber ich finde (heutzutage) einfach kein gutes Tutorial oder Forum mehr, was sich mit Pascal, vor allem mit dem ALTEN Pascal, beschaeftigt. Zum Glueck treiben sich hier anscheinend ein paar Leute rum, die noch gerne was mit den alten Programmiersprachen unter DOS coden :Banana

  • Ich bin schon etwas eingerostet was direkte Tastaturprogrammierung angeht. Aber deine KeyportOn und Off Prozeduren verwirren mich. Int 9h ist ja eigentlich der Keyboard Interrupt. Wieso rufst du den auf? Finde da gerade nicht was die Funktion macht.


    Und int 16h Funktion 3, Parameter 0 ist laut helppc die Wiederholrate auf Standard setzen. Scheint mit auch nicht unbedingt notwendig...?


    Die Inline Funktionen scheinen direkt aus dem TP6.0 Handbuch zu stammen. Daher denke ich sind die genehm. Turbo C hat schon Funktionen eingebaut, aber ich glaube Turbo Pascal hat da nichts.


    root42 auf YouTube


    80386@25 MHz, 8 MiB RAM, Tseng ET4000 1 MiB, LABS BlasterBoard & SnarkBarker, PC MIDI Card + SC55 + MT-32, XT CF Lite, OSSC 1.6

    Einmal editiert, zuletzt von root_42 ()

  • Mahlzeit :)


    diese KeyPort ON und OFF Routinen scheinen wirklich unnoetig zu sein. Die habe ich halt aus einem Beispiel entnommen ohne zu wissen, was diese eigentlich tun. Die Scancodes sind so oder so am Port $60 zu sehen.


    Weiterhin habe ich fuer das Leeren des Tastaturpuffers nun eine Routine aus einem andere Beispiel ausprobiert, welche genauso gut funktioniert und OHNE dieses Inline-Zeug auskommt 8)


    Link:

    http://swag.outpostbbs.net/KEYBOARD/0049.PAS.html


    Code
    procedure FlushKbd; Assembler;
    asm
    Mov AX, $0C00;
    Int 21h;
    end;
  • Das Inline-Zeugs kannst du ja umwandeln in reinen ASM-CODE.

    Es gibt Umsetzungen mit Listen wo du den Code rausfiltern kannst.

    Geht zwar langsam , aber es klappt.


    Klarer sieht es noch aus wenn du AH und AL noch rausfilterst.

    Sonnst grübelt man , ob es ein kompletter AX-Befehl ist oder ob er sich aufteilt in AH und AL.

    Das ist wichtig.

  • Das CLI und STI war notwendig um zu verhindern, dass ein Tastaturtreiber die Werte am Keyboardcontroller verwurschtelt wärend du davon liest. Denn der Treiber springt an sobald der Tastaturinterrupt ausgelöst wird. Mit dem Inline Code wird das verhindert.

  • Der Inline-Code verfälscht durch seine Eigenheit zum Tp das wahre Verhalten wie es bei ASM stattfindet.


    Ist auch verständlich , denn es waren die ersten Schritte um Dinge im ASM-Verhalten direkt ohne Obj zu nutzen.

    Die innere Struktur des TP zog dem Inline-Verhalten sozusagen ein Korsett an.

  • die Inline-Anweisungen stoeren mich auch deswegen, weil man anhand der Hexcodes nicht direkt den Befehl erkennen kann. Ich bin zwar mit Assembler noch relativ unbeleckt, aber ein paar Befehle hab ich schonmal angewendet.


    Muss fuer das Auslesen der Codes am Port $60 eigentlich noch etwas aktiviert werden? Bisher scheint es ja immer zu funktionieren, den Port einfach auszulesen. Aber sollte man noch eine Art Initialisierungsroutine entwickeln, bevor man auf den Port $60 zugreift?


    Meine Pascal Fachliteratur geht in diesen Fragen leider nicht soweit ins Detail.


    Ziel soll es sein, eine Keyboard Unit zu entwickeln, die die noetigen Routinen in einfachem und sauberen Assembler zur Verfuegung stellt, sodass nicht nur ich, sondern auch andere sie ohne grosse Einarbeitung nutzen koennen :)

  • Ich empfehle Data Beckers PC Intern wenn du diese Details lernen willst. Du kannst immer auf Port 60h lesen. Aber es kann sein, dass dir der Tastaturtreiber dazwischenfunkt, daher auch der Inline Befehl in deinem Originalprogramm. Viele Spiele installieren ihren eigenen Interrupt Handler und stellen den alten beim Beenden wieder her.


    Statt des inline kannst du auch das hier machen:


    Code
    asm
      cli
      mov ax,$40
      mov ds,ax
      mov bx,$1c
      mov ax,[bx]
      mov bx,$1a
      mov [bx],ax
      sti
    end;

    Ohne Gewähr und ungetestet. Die Idee: Die Inline Kommandos entsprechen CLI und STI (clear/set interrupts). Und der memw Zugriff ist die Reihe von MOV Befehlen. Müsste eigentlich so funktionieren, glaube ich... Ist LANGE her...

  • Bisher scheint dieses Beispiel ja am vielversprechendsten:

    Link:

    http://swag.outpostbbs.net/KEYBOARD/0058.PAS.html


    Aber eine Frage zum Assemblerbefehl OR: Was bringt es, einen Operanden mit sich selbst zu verodern?

    Beispiel: OR AL,AL


    Was in Register AL steht, bleibt doch nach dem ODER-Befehl mit sich selber unveraendert, was soll das dann?? Genauso sehe ich manchmal den XOR Befehl, der einen Operanden mit sich selbst "ver-Exklusiv-Odert". Was bringt das?? ?(


    Ich programmiere schon lange mit Pascal und beruflich programmiere ich (daemliche) Siemens SPSen in FUP, KOP, SCL und AWL. Also ich kenne die logischen Verknuepfungen, nur bei manchem Assemblercode frage ich mich doch, was diese oder jene Zeile bewirken soll :grübel

  • or al,al setzt das Flags Register. Damit kannst du quasi den Wert in AL auf seine Flags inspizieren. Insbesondere Zero Flag und Sign Flag. Damit kannst du dann bedingte Sprünge machen.

  • Mahlzeit :Bier


    ich denke, jetzt hab ich die Funktionalitaet so, wie ich es haben wollte. :)


    Aus dem WebSWAG Archiv hab ich mich bedient und die KEYBX-Unit (0058.PAS) getestet. Darin sind noch viele weitere Funktionen enthalten, die ich noch austesten moechte. Die Funktionen, die noetig sind, waren jedenfalls enthalten.


    Unit KEYBX.PAS - Das "Uses Errors;" musste ich auskommentieren, sonst liess es sich nicht uebersetzen

    http://swag.outpostbbs.net/KEYBOARD/0058.PAS.html

    -> editierte Version siehe Anhang


    und ein kleines Testprogramm fuer die zwei relevanten Routinen



    Was habt ihr noch an Verbesserungsvorschlaegen und Anregungen? :tasskaff


    Auf die alte CRT-Unit moechte ich komplett verzichten, nur fuer dieses Beispiel wollte ich die Textausgabe einfach halten...

  • Was sind das verrückte Zeichen dazwischen , sieht chaotisch aus.

    Kann man für das "ÄÄÄ.." usw nichts Lesbares setzen.


    Diese Fremdwörter bringen nichts : liCount...usw oder dieses : #2


    Das TP ist kein Basic, hier kann es lesbar kurz beschriftet werden.


    Dieses Copy/Paste bringt nichts beim lernen.


    ---------------------------------------

    WRITELN('ÚÄ Register AH ÂÄ Register AL ¿');

    WRITELN('³ ',Byte2Dual(HI(wKeyCode)):12,' ³ ',Byte2Dual(LO(wKeyCode)):12,' ³');

    WRITELN('³ ',Byte2Hex(HI(wKeyCode)):12,' ³ ',Byte2Hex(LO(wKeyCode)):12,' ³ ');

    WRITELN('ÃÄ Byte $40:17 ÅÄ Byte $40:18 ´');

    WRITELN('³ ',Byte2Dual(MEM[$40:$17]):12,' ³ ',Byte2Dual(MEM[$40:$18]):12,' ³');

    WRITELN('ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÁÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ');

    ---------------------------------------

Jetzt mitmachen!

Sie haben noch kein Benutzerkonto auf unserer Seite? Registrieren Sie sich kostenlos und nehmen Sie an unserer Community teil!