C 64
Tips und Tricks

Directory auf Knopfdruck

Häufig steht man vor dem Problem, Programme direkt, also ohne SYS-Aufrufe, über einen Tastencode zu aktivieren. Wir zeigen Ihnen, wie man ein Directory auf dem Bildschirm ausgibt, ohne ein vorhandenes Basic-Programm zu zerstören.

Das Programm »Directory auf Knopfdruck« (siehe Listing 1) kann, nachdem es mit Hypra-Assassembliert wurde, mit dem Befehl SYS 49152 aktiviert werden.

Den erzeugten Maschinencode zeigt Listing 2, das auch direkt mit dem MSE eingegeben werden kann. Solange kein Reset ausgelöst oder die RUN/STOP-Taste gedrückt wird, erscheint bei der Tastenkombination »CTRL-D« das Directory auf dem Bildschirm, ohne ein eventuell im RAM stehendes Basic-Programm zu zerstören.

Der hier vorgestellte Lösungsweg, ein beliebiges Programm auf Tastendruck aufzurufen, hat den Vorteil, daß er allgemeingültig ist und nicht nur auf die Ausgabe des Directorys beschränkt ist.

Im allgemeinen müßte das Betriebssystem geändert werden, um eine zusätzliche Tastaturabfrage einzubinden. Aber wir haben Glück, denn einige Routinen im Betriebssystem werden über einen sogenannten Sprungvektor aufgerufen. Alle zugänglichen Sprungvektoren, die sich ändern lassen, befinden sich in der dritten Page, also im Bereich von $311 bis $333, jeweils im Low-/High-Byte-Format. Der zum Einbinden einer Tastaturabfrage geeignetste Vektor ist der Interruptvektor, denn diese sogenannte Interrupt-Routine wird 60mal pro Sekunde angesprungen. Ein Sprungvektor, der in diese Routine verzweigt, befindet sich in den Speicherzellen $314/$315. Die Speicherzellen enthalten im Normalzustand den Wert $31/$EA. Das bedeutet, daß immer, wenn ein Interrupt ausgelöst wird, zu einer Routine verzweigt wird, die bei $EA31 liegt. Schreibt man nun in die Speicherzellen $314/ $315 einen anderen Wert, wird bei einem Interrupt nicht mehr zur Adresse $EA31, sondern zu der Adresse verzweigt, die in den Speicherzellen $314/315 steht, wobei die Adresse $314das Low- und die Speicherzelle $315 das High-Byte der anzuspringenden, neuen Interrupt-Routine enthält. Damit sich der Vektor aber verändern läßt, muß zuerst der normale Interrupt gesperrt werden, denn sonst könnte folgendes passieren: Angenommen, es wird ein Interrupt ausgelöst, nachdem erst das Low-Byte in die Adresse $314 geschrieben wurde, dann nimmt der Computer an, daß die neue Interrupt-Routine bei $EAOO plus dem in Adresse $314 stehendem Low-Byte liegt, verzweigt an diese Adresse und stürzt ab.

Mit dem Maschinenbefehl »SEI« für SEt Interruptflag läßt sich nun der prozessorinterne Interrupt ausschalten. Dies wird in der Zeile 230 im Listing 1 realisiert. Die Zeilen 240 bis 270 sorgen dafür, daß die Startadresse der neuen Interrupt-Routine in die entsprechenden Adressen kommt. Eine Bemerkung noch zu den Zeilen 240 und 270. Durch das »kleiner«- beziehungsweise »größer«-Zeichen läßt sich eine 16-Bit-Adresse (in diesem Fall »INTER«) in zwei 8-Bit-Zahlen splitten. Durch das »kleiner«-Zeichen erhält man das Low- und entsprechend für das »größer«-Zeichen das High-Byte.

Der folgende »CLI«-Befehl (CLear Interruptflag) läßt nun den normalen Interrupt wieder zu. Nur wird jetzt, wenn ein Interruptstattfindet, nicht mehr zur Adresse $EA31, sondern zur Routine »INTER« verzweigt. Die Aufgabe des Teilprogramms »INTER« ist es, die »CTRL«- und »D«-Taste abzufragen. Sind beide Tasten gleichzeitig gedrückt, wird nach »DIR« verzweigt, ansonsten in der Zeile 420 zum normalen Interrupt nach $EA31. Die Zeilen 370 und 380 beziehungsweise 400 und 410 sperren auch den Interrupt, aber auf eine etwas andere Art.

Sie werden sich vielleicht fragen, warum der Interrupt überhaupt gesperrt werden muß. Die Antwort auf diese Frage ist leicht zu geben. Die Bearbeitung der Routine »DIR« dauert länger als 1/60 Sekunde. Dadurch würde bereits ein neuer Interrupt ausgelöst, bevorderalteabgearbeitetwäre. Die Art, wie der Interrupt abgeschaltet wird, wurde mit Absicht so gewählt, da einige Routinen im Betriebssystem den Interrupt durch den CLI-Befehl wieder zulassen, so auch die Routine »CHROUT«, die ein Zeichen auf einem Gerät, hier dem Bildschirm, ausgibt. Durch die Befehle »LDA #TIMERAUS« und »STA ICR« wird eigentlich nicht der Interrupt abgeschaltet, sondern der Timer gestoppt, der den Interrupt auslöst. Doch nun zum eigentlichen »DIR«-Programm.

Die Zeilen 450 bis 550 entsprechen dem Basic-Befehl »OPEN 1,8,0,"$"«. Dabei liegt das Augenmerk auf der Sekundäradresse »0« und dem Dollarzeichen. Das Dollarzeichen als Filename bewirkt, daß das Directory eingelesen wird und zwar einschließlich Track 18 Sektor 0. Durch die »0« als Sekundäradresse wird das Directory schon soweit aufbereitet, daß nur noch die Zeichen, die sich nach einem »LOAD"$",8« tatsächlich im RAM befinden, zum Computer gesendet werden, inklusive Filetyp, Steuerzeichen, Leerzeichen und Anzahl der Blöcke pro File. Leider enthält ein vom Floppy-Laufwerk gesendeter Directory-Eintrag auch noch Platzhalter für die Zeilenlinkadressen, die wir natürlich nicht brauchen und folglich ausblenden beziehungsweise überlesen müssen. Eine vom Floppy-Laufwerk gesendete Directory-Zeile hat folgendes Format:

LI LI AB SP "filename SP" SP FT

LI = Linkbyte; AB = Anzahl der Blöcke pro File im Low/ High-Byte-Format; SP = Leerzeichen; FT = Filetyp im Klartext.

Das einzige, was zu tun bleibt, ist die Ausgabe »RETURN« am Ende jeder Directory-Zeile (Zeile 811/812). Außerdem muß die Information, die die Anzahl der Blöcke pro File enthält, in dezimale Schreibweise umgerechnet und auf dem Bildschirm ausgegeben werden. Das ist aber kein Problem, denn das Betriebssystem stellt eine solche Routine »INTOUT=$BDCD« zur Verfügung. Wenn sie aufgerufen wird, muß der Akku das High- und das X-Register das Low-Byte der auszugebenden Zahl enthalten. Das Low-Byte wird in Zeile 590 an das X-Register übergeben. Das High-Byte dagegen wird in Zeile 630 durch das Unterprogramm »CHRIN« eingelesen und steht automatisch im Akku.

Zum Programmablauf

Die Zeilen 570 bis 620 überlesen 4 Byte beim ersten Durchlauf. Bei allen weiteren Durchläufen werden immer nur die ersten 2 Byte überlesen, die die Zeilenlinkadresse enthalten. Beim ersten Durchlauf wird neben der Zeilenlinkadresse auch die Startadresse ($0801) gesendet, die ebenfalls ausgeblendet werden muß, darum 4 Byte. Bei einem Sprung auf das Label »ROWOUT« enthält das Y-Register die Anzahl der Byte, die überlesen werden sollen plus 1. Wird die Schleife in Zeile 620 verlassen, enthält das X-Register das Low-Byte der Zahl, die die Anzahl der Blöcke pro File kennzeichnet. Das High-Byte wird in Zeile 630 eingelesen und an den Akku übergeben. Die nächste Schleife, die bei dem Label »NEXTCHR« beginnt, gibt den Rest eines Directory-Eintrags auf dem Bildschirm aus. Der »CMP«-Befehl in Zeile 730 überprüft, ob eine »0«, die das Ende des Eintrags kennzeichnet, gesendet wurde oder nicht. Bei einer »0« wird nach »LASTCHR« verzweigt, ein »RETURN« ausgegeben und zum Label »ROWOUT« gesprungen.

(ah)
10  -.EQ IRQVEKLO = $314
20  -.EQ IRQVEKHI = $315
30  -.EQ SHIFTFLAG = $28D
40  -.EQ TIMERAUS = $80
50  -.EQ TIMEREIN = 129
60  -.EQ ICR = $DC0E
70  -.EQ INTERRUPTALT = $EA31
80  -.EQ SETNAM = $FFBD
90  -.EQ SETLFS = $FFBA
100  -.EQ OPEN = $FFC0
110  -.EQ CHKIN = $FFC6
120  -.EQ CHRIN = $FFCF
130  -.EQ INTOUT = $BDCD
140  -.EQ CHROUT = $FFD2
150  -.EQ CLOSE = $FFC3
151  -.EQ CLRCHN = $FFCC
160  -.EQ STATUS = $90
170  -.EQ RETTEN = $FB
180  -.EQ TASTENCODE = $C5
190  -;
200  -;
210  -.BA $C000
220  -;
221  -;********************************
222  -;* INTERRUPTVEKTOR NEU SETZEN   *
223  -;********************************
224  -;
230  -          SEI
240  -          LDA #<(INTER)
250  -          STA IRQVEKLO
260  -          LDA #>(INTER)
270  -          STA IRQVEKHI
280  -          CLI
290  -          RTS
300  -;
301  -;********************************
302  -;*    NEUE INTERRUPTROUTINE     *
303  -;********************************
304  -;
310  -INTER     LDA TASTENCODE
320  -          CMP #18        ;IST DIE TASTE >>D<< GEDRUECKT?
330  -          BNE INTERE     ;WENN NEIN DANN ZUM NORMALEN INTERRUPT
340  -          LDA SHIFTFLAG
350  -          CMP #4         ;IST >>CTRL<< GEDRUECKT?
360  -          BNE INTERE     ;WENN NEIN DANN ZUM NORMALEN INTERRUPT
370  -          LDA #TIMERAUS  ;TIMER AUSSCHALTEN/INTERRUPT SPERREN
380  -          STA ICR
390  -          JSR DIR        ;UND ZUM UNTERPROGRAMM DIR
400  -          LDA #TIMEREIN  ;TIMER EINSCHALTEN/INTERRUPT ZULASSEN
410  -          STA ICR
420  -INTERE    JMP INTERRUPTALT
430  -;
440  -;
441  -;********************************
442  -;*         DIRECTORY            *
443  -;*          AUSGEBEN            *
444  -;********************************
445  -;
450  -DIR       LDA #1         ;LAENGE DES FILENAMENS
460  -          LDY #>(NAME)
470  -          LDX #<(NAME)
480  -          JSR SETNAM     ;FILENAMENPARAMETERSETZEN
490  -          LDA #1         ;LOGISCHE FILENUMMER = 1
500  -          LDX #8         ;GERAETEADRESSE = 8
510  -          LDY #0         ;SEKUNDAERADRESSE = 0
520  -          JSR SETLFS     ;LOGISCHE FILENUMMER UND SEKUNDAERADR. SETZEN
530  -          JSR OPEN
540  -          LDX #1         ;LOGISCHE FILENUMMER
550  -          JSR CHKIN      ;EINGABEGERAET SETZEN
560  -          LDY #5         ;DIE ERSTEN 5 ZEICHEN UEBERLESEN
570  -ROWOUT    STY RETTEN
580  -          JSR CHRIN      ;EINGABE EINES ZEICHENS
590  -          TAX            ;LO-BYTE BLOCKANZAHL INS X-REGISTER
600  -          LDY RETTEN
610  -          DEY
620  -          BNE ROWOUT
630  -          JSR CHRIN      ;HI-BYTE BLOCKANZAHL IN DEN AKKU
640  -          LDY STATUS     ;IST FILEENDE SCHON ERREICHT?
650  -          BNE ENDE       ;WENN JA DANN FERTIG
670  -          JSR INTOUT     ;ANZAHL DER BLOECKE AUSGEBEN (X/AKKU)
690  -          LDA #" "       ;BLANK AUSGEBEN
700  -          JSR CHROUT
710  -NEXTCHR   JSR CHRIN      ;NAECHSTES ZEICHEN HOLEN
720  -          STA RETTEN     ;UND RETTEN
730  -          CMP #0         ;IST FILEEINTRAG AUSGEGEBEN?
740  -          BEQ LASTCHR    ;WENN JA DANN RETURN AUSGEBEN
790  -          LDA RETTEN     ;ANSONSTEN MUSS NOCH DAS LETZTE ZEICHEN
800  -          JSR CHROUT     ;AUSGEGEBEN WERDEN
810  -          JMP NEXTCHR
811  -LASTCHR   LDA #13        ;>>RETURN<< AUSGEBEN
812  -          JSR CHROUT
813  -          LDY #$3        ;3 ZEICHEN UEBERLESEN
814  -          JMP ROWOUT
820  -ENDE      JSR CLRCHN     ;EIN- UND AUSGABEKANAELE
830  -          LDA #1         ;UND LOGISCHES FILE SCHLIESSEN
840  -          JSR CLOSE
850  -          RTS
860  -;
870  -NAME      .TX "$"
Listing 1. »Directory auf Knopfdruck«. Der Quelltext wurde mit Hypra-Ass erstellt.
PROGRAMM : DIREKTORY.OBJ  C000 C087
-----------------------------------
C000 : 78 A9 0D 8D 14 03 A9 C0   C3
C008 : 8D 15 03 58 60 A5 C5 C9   CA
C010 : 12 D0 14 AD 8D 02 C9 04   5D
C018 : D0 0D A9 80 8D 0E DC 20   E6
C020 : 2A C0 A9 81 8D 0E DC 4C   9A
C028 : 31 EA A9 01 A0 C0 A2 84   FC
C030 : 20 BD FF A9 01 A2 08 A0   EA
C038 : 00 20 BA FF 20 C0 FF A2   44
C040 : 01 20 C6 FF A0 05 84 FB   3F
C048 : 20 CF FF AA A4 FB 88 D0   93
C050 : F5 20 CF FF A4 90 D0 23   A1
C058 : 20 CD BD A9 20 20 D2 FF   52
C060 : 20 CF FF 85 FB C9 00 F0   08
C068 : 08 A5 FB 20 D2 FF 4C 60   65
C070 : C0 A9 0D 20 D2 FF A0 03   02
C078 : 4C 46 C0 20 CC FF A9 01   91
C080 : 20 C3 FF 60 24 D8 1F      0A
Listing 2. »Directory auf Knopfdruck« muß mit dem MSE eingegeben werden
PDF Diesen Artikel als PDF herunterladen
Mastodon Diesen Artikel auf Mastodon teilen
← Vorheriger ArtikelNächster Artikel →