

                         Tips & Tricks
                         


Hier soll mal ein wenig Stimmung aufkommen! Deswegen habe ich 
mir ein paar 'Tricks' einfallen lassen, die im sonstigen 
(Programmierer-) Leben ganz ntzlich sein knnten.

Zum einen: Wie lsche ich den Tastaturpuffer?

Es gibt zwei (einfache) Mglichkeiten:

 a) PROCEDURE DelKeyBuf;
    BEGIN
     WHILE KeyPressed DO IF ReadKey = #0 THEN;
    END;

 So funktioniert's: KeyPressed liefert TRUE zurck, solange noch
 eine Taste im Puffer ist. ReadKey liefert den ASCII-Code zurck.
 Wenn sich keine Taste mehr im Puffer befindet, wartet ReadKey
 solange, bis wieder eine Taste gedrckt wird. Doch soweit soll
 es ja gar nicht kommen. Also: ReadKey nur solange aufrufen, wie
 KeyPressed TRUE zurckliefert. Was wahrscheinlich ein wenig
 komisch wirkt ist die Abfrage 'IF ReadKey = #0 THEN;'. Diese
 Abfrage bewirkt natrlich gar nichts - oder? Doch! Sie lscht
 nmlich einen Wert im Tastaturpuffer. Und wenn das lange ge-
 nug gemacht wird... dann is' er leer.

 b) PROCEDURE DelKeyBuf;
 BEGIN
  ASM CLI END;            {Oder: INLINE($FA);}
  MEM[$0040:$001A] := MEM[$0040:$001C];
  ASM STI END;            {Oder: INLINE($FB);}
 END;

 Diese Variante ist etwas trickreicher. Man kann sie wohl auch
 problemlos in andere Prospen umsetzen. Dafr ein wenig Theorie:
 Der Tastaturpuffer ist als ein sogenannter Ringpuffer konzi-
 piert. Das bedeutet: Es existieren zwei Zeiger, wobei einer der
 beiden Zeiger auf das Element im Puffer zeigt, das als nchstes
 ausgelesen werden soll, und der zweite Zeiger auf eine Speicher-
 stelle zeigt, die ein neues, 'hereinkommendes' Zeichen belegen
 soll. Was dabei eigentlich nur interessiert, ist folgendes:
 Sollten die Zeiger auf die selbe Speicherstelle zeigen, also
 den gleichen Inhalt haben, so zeigt dies an, da der Tastatur-
 puffer leer ist. Dabei ist es egal, ob das nun tatschlich zu-
 trifft, indem man nmlich wirklich alle Zeichen ausgelesen hat
 (siehe a)), oder ob dies durch direkte Manipulierung dieser Zei-
 ger zustande gekommen ist. Das Gute ist nmlich: Man kennt die
 Adresse dieser Zeiger (der 'Anfangszeiger' bei $40:$1A und der
 'Endzeiger' bei $40:$1C).
 Man sollte, wenn man diese Zeiger aktiv manipuliert, allerdings
 darauf achten, da die Interrupts gesperrt sind, da sonst, just
 in dem Moment, wo man die Zeiger auf die gleiche Stelle setzt,
 eine Taste gedrckt werden knnte, die das Ganze dann zunichte
 macht.


2.) Zeitmessung in Pascal

 Es gibt in Pascal keine direkte Methode, zu berprfen, wie
 lange eine Routine oder berhaupt ein Programmabschnitt braucht.
 Zumindest habe ich das frher (als ich noch jung und schn war
 :-), echt vermit. Man kann das zwar auch mittels der Prozedur
 'GetTime' von Pascal machen, doch ist diese ein wenig umstnd-
 lich in der Handhabung (probiert's mal aus, ich spare mir hier
 eine Erklrung). Heute (!) gibt's eine bessere Lsung. Die fol-
 gende Routine liefert zwar nur die Sekunden zurck, und funktio-
 niert auch nicht richtig, wenn man gerade Mitternacht ber-
 brckt, doch war und ist sie genau das Richtige fr mich gewe-
 sen.
 An der Adresse $0000:$046C steht die Anzahl der 'Ticks', die
 seit Mitternacht des laufenden Tages vergangen sind. Diese
 Speicherstelle wird 18.20648193... mal in der Sekunde aufgeru-
 fen. Als ich mal jung war, wute ich auch noch, woher diese Zahl
 kam. Jetzt nicht mehr. Macht nichts. Das Heraufsetzen geschieht
 automatisch, man braucht sich also um nichts zu kmmern. Man
 kann sich dieser Sache aber annehmen, indem man sie zur Zeitmes-
 sung mibraucht. Will man die Zeit messen, die zum Beispiel ver-
 geht, wenn man 10000 Punkte auf den Bildschirm bringt, dann kann
 man diese Speicheradresse vor dem Setzen der Pixel auslesen und
 zwischenspeichern und danach nochmals auslesen. Die Differenz
 der beiden Zahlen sind dann die vergangenen Ticks. Teilt man
 diese dann noch durch 18.2..., erhlt man die Dauer in Se-
 kunden. Die unten stehende Routine (in UNIT-Format: einmal
 compilieren, immer benutzen (RECYCLING!)) ist ganz einfach auf-
 gebaut. In Pascal ist es mglich, eine Variable auf eine be-
 liebige Adresse zu legen. Genau das wird getan: Die Variable
 'Ticks' wird auf die Adresse 0:$046C gepackt und spiegelt so-
 mit die 'Ticks' seit Mitternacht wieder. Die Funktion Timer
 liefert dann die Ticks durch 18.2..., also die Sekunden seit
 Mitternacht zurck.

  UNIT Time;

  INTERFACE

   FUNCTION Timer : REAL;

  IMPLEMENTATION

   VAR Ticks : LONGINT ABSOLUTE $0000:$046C;

   FUNCTION Timer : REAL;
   BEGIN
    Timer := Ticks / 18.20648193;
   END;

  END.

 In Euren eigenen Programmen braucht Ihr jetzt nur noch eine Va-
 riable vom Typ REAL zu deklarieren und vor der zu messenden 
 Stelle 'ZeitVariable := Timer' zu schreiben. Nach der Stelle 
 kommt dann 'ZeitVariable := Timer - ZeitVariable' und Ihr habt 
 dann die vergangene Zeit in Sekunden vorliegen.

Wenn Ihr auch solche unheimlich dollen Routinen habt, dann
schickt sie uns doch und behaltet sie nicht fr Euch alleine!


                                                      Kemil

Hallo Leute!

Hier ein kleiner Tip ohne groe Erklrung! Diese kommt vielleicht
von einem unsere Assembler-Menschen. Unter TP gibt es nmlich ein
Problem, das mich von Anbeginn meiner Programmierzeiten in TP ge-
rgert hat. Man stelle sich folgende Situation vor:

Ich habe einen tolles Bildschirmlayout und warte auf die Tasta-
tureingabe eines Users. Was erscheint? Richtig, ein dumm rum-
blinkender Cursor. Das gesamte Layout ist hin. Die Rettung sind
die folgenden beiden Prozeduren, die man am Besten in Units ein-
bindet, sofern man dieses beherrscht.

  PROCEDURE KiC; assembler;
  asm
    mov ah,$01
    mov cx,$2020
    INT($10);
  END;

  PROCEDURE ReC; assembler;
  asm
    mov ah,$01;
    mov cx,$0607;
    INT($10);
  END;

Im Programm ruft man dann nur noch Kic; auf, um den Cursor
zu lschen. ReC macht das Gegenteil, der Cursor wird wieder
sichtbar.

                                                 Grisu

