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