********* Welcome to International Project 64! The goal of International Project 64 is to preserve non-English Commodore 64 related documents in electronic text format that might otherwise cease to exist with the rapid advancement of computer technology and declining interest in 8-bit computers on the part of the general population. If you would like to help by converting C64 related hardcopy documents to electronic texts please contact the manager of International Project 64, Peter Karlsson, at pk@abc.se. Extensive efforts were made to preserve the contents of the original document. However, certain portions, such as diagrams, program listings, and indexes may have been either altered or sacrificed due to the limitations of plain vanilla text. Diagrams may have been eliminated where ASCII-art was not feasible. Program listings may be missing display codes where substitutions were not possible. Tables of contents and indexes may have been changed from page number references to section number references. Please accept our apologies for these limitations, alterations, and possible omissions. Document names are limited to the 8.3 file convention of DOS. The first characters of the file name are an abbreviation of the original document name and the language of the etext. The version number of the etext follows next. After that a letter may appear to indicate the particular source of the document. Finally, the document is given a .TXT extension. The author(s) of the original document and members of International Project 64 make no representations about the accuracy or suitability of this material for any purpose. This etext is provided "as-is". Please refer to the warantee of the original document, if any, that may included in this etext. No other warantees, express or implied, are made to you as to the etext or any medium it may be on. Neither the author(s) nor the members of International Project 64 will assume liability for damages either from the direct or indirect use of this etext or from the distribution of or modification to this etext. Therefore if you read this document or use the information herein you do so at your own risk. ********* The International Project 64 etext of the book "222 Tips, Tricks und Tools für den C 64", written and donated for IP64 distribution by Nikolaus Heusler . 222_DE1.TXT, June 1997, etext #8. Note from the etexter: This is german text. This document is the text of a book written by Nikolaus M. Heusler. The book was published in 1992 and contains information about the C 64. No part of this text may be copied, stored or published in any way without prior written permission by the author. It is not allowed to store copies of this text or of parts of it on computer-discettes or on computers which can be accessed in the public, for example on the internet. Das Werk einschliesslich aller seiner Teile ist urheberrechtlich geschuetzt. Jede Verwertung ausserhalb der engen Grenzen des Urheberrechtsgesetzes ist ohne vorherige schriftliche Zustimmung des Verfassers unzulaessig und strafbar. Dies gilt insbesondere fuer Vervielfaeltigungen, Uebersetzungen und die Verarbeitung in elektronischen Systemen. Einwilligungen zur Weiterverarbeitung wird der Verfasser im Einzelfall auf schriftliche Anfrage gern geben, falls keine kommerziellen Interessen mit der Verarbeitung verfolgt werden. Produkt- und Herstellerangaben in dem Buch werden ohne Ruecksicht auf eventuellen Patentschutz veroeffentlicht. Warennamen werden ohne Gewaehr- leistung der freien Verwendbarkeit benutzt. Die Texte wurden mit groesster Sorgfalt zusammengestellt. Trotzdem sind Fehler nicht vollstaendig auszuschliessen. Fuer fehlerhafte Angaben und deren Folgen kann der Autor weder juristische Verantwortung noch irgendeine Haftung uebernehmen. Zu dem Buch gehoeren zwei Disketten im 1541-Format mit den Listings aus dem Buch. Das Buch selbst ist leider nicht mehr lieferbar. Verfasser / Author: Nikolaus Heusler Zwengauerweg 18 D-81479 Muenchen Germany Bei schriftlichen Anfragen bitte Rueckporto beilegen, ich antworte gern. This version was published in the internet on the project "IP 64" in June 1997. ********* 222 Tips, Tricks und Tools fuer den C 64 INHALTSVERZEICHNIS Vorwort 1. Alles für den Basic-Alltag Detektiv für Basicprogramme: Das BKS Help! Fehlermeldungen erklärt Data Aid - Hilfe, die DATAs kommen TI$ - die Softwareuhr wird genauer Der intelligente REM-Killer Befehle auf Tastendruck - 64 Keys Array of byte komfortable INPUT-Routine eine geniale Suchroutine 2. Mehr Spaß mit Maschinensprache kompletter Assembler-Dateikurs Multitasking auf dem C 64 das NSS-Kernal Eisberg - da friert der C 64 Nie wieder Abstürze mit Uncrash Der Quickie-Generator neues DOS für die Floppy die große Maschinensprache-Bibliothek 3. Grafik - das Auge ißt mit Spritelist findet alle Sprites der Chartransposer Softscroll Double Print sagt's deutlich Letter - große Anfangsbuchstaben eine starke Using-Routine 4. die Floppy im Griff Kurs für relative Dateien ARC schlägt zu Rattern ade - der Bumpmaster Don't replace TSS - der Zwillingsfinder Verify 2 files Löschen rückgängig machen mit Unscratch Top Secret - Dateien verschlüsseln besser als der BND Der Diskettenspion Diskettenspeichermonitor DMS getestet auf Herz und Nieren - Tester 1541 5. Sonstiges DOC 64 - der Computerarzt Kalender im Griff Großputz - die Tastatur reinigen der Hyper-Reset Schmalschrift auf MPS-Druckern - Condensed Diskettenbriefe - der Message-Maker Die große Trickkiste - auch für Sie ist etwas dabei! 6. Das große Computerlexikon Vorwort Daran gibt es keinen Zweifel: Der C 64 ist Weltrekordhalter beim Verkauf von Homecomputern. Mit ziemlicher Sicherheit wird es auch in der näheren Zukunft keinen Rechner geben, der von der Verbreitung her an die über zehn Millionen C 64 herankommt. Ein wichtiger Grund dafür ist sicherlich die für seinen Preis ungewöhnlich gute technische Ausstattung, was Speicher, Grafikfähigkeit und die Soundmöglichkeiten anbelangt. Ein großes Manko war jedoch schon immer das Handbuch zum C 64. Der frischgebackene Besitzer wird nur sehr grob in die wichtigsten Grundzüge des eingebauten Basic-Dialekts eingeführt. Die Bedienungsanleitung geht weder auf die Programmierung in Maschinensprache, die viele Anwendungen erst ermöglicht, ein, noch steht etwas über die Programmierung der hochauflösenden Grafik drin. Und das sparsame Basic V2 unterstützt die enorme Leistungsfähigkeit kaum. Will man ernsthaft mit dem neuen Gerät arbeiten und programmieren, ist man auf zusätzliche Literatur angewiesen. Fachzeitschriften wie das 64'er-Magazin bieten regelmäßig interessante Tips und Tricks, mit denen schnell die ersten Erfolgserlebnisse kommen. Dieses Buch ist eine weitere wichtige und sehr ergiebige Informationsquelle für Anwender, vor allem aber Programmierer. Enthalten sind unzählige kleine, größere und umfangreiche Programme, die Ihren Programmieralltag erheblich erleichtern werden. Nicht nur der Einsteiger findet hier die Anregungen und Tips, die das Handbuch ausläßt. Was halten Sie von einem Tool, das alle Basic-Fehlermeldungen in deutsch näher erläutert? Tastatur-Utilities erlauben die Belegung der Funktionstasten oder das Abrufen von Basicbefehlen auf Tastendruck. Auch für den Fortgeschrittenen ist viel dabei. Obwohl praktische Hilfen für die Basicprogrammierung den Schwerpunkt darstellen, ist auch einiges aus dem Bereich der Maschinensprache geboten, etwa ein kompletter Kurs über die Dateiprogrammierung in Assembler. Natürlich soll auch der Profi nicht zu kurz kommen, als Beispiele seien hier nur »DOC 64« und der »Tester 1541« genannt, zwei Programme, die den C 64 und das Laufwerk auf Herz und Nieren überprüfen, oder ein interessantes Multitask-Hilfsprogramm, mit dessen Hilfe mehrere Projekte gleichzeitig ablaufen. Zum Thema Floppyprogrammierung gibt es allerlei Datei-Analyseprogramme, zwei Diskmonitoren, die die geheimnisvollen schwarzen Scheiben entzaubern, oder ein Hilfsprogramm zum Retten gelöschter Files. Das alles geht ohne stundenlanges Abtippen: Auf den beiliegenden Disketten finden Sie alle Programme fertig zum Ausprobieren. Obwohl viele Utilities weitgehend selbsterklärend sind, lassen sich jedoch mit Hilfe der ausführlichen Anleitungen ärgerliche Bedienungsfehler vermeiden. Mein besonderer Dank gilt den vielen Lesern meiner Beiträge im 64'er-Magazin, die mit konstruktiver Kritik, Verbesserungsvorschlägen und wichtigen Anregungen in Form von Leserbriefen entscheidend dazu beigetragen haben, dieses Buch auf einen sehr breiten Leserkreis auszurichten. Dank gebührt außerdem den Mitarbeitern des IPV-Verlags, vor allem den Herren Felix Röscheisen und Axel Pretzsch, die mit viel Liebe und Sorgfalt die Texte zusammengestellt und das Buch produziert haben. Seitens des Markt & Technik Verlags bedanke ich mich vor allem bei der Redaktion des 64'er-Magazins für die sehr gute und freundschaftliche Zusammenarbeit. Ich hoffe, daß dieses Buch dem Einsteiger eine gute Hilfe beim Erarbeiten und zum Verständnis der C 64-Materie und dem Fortgeschrittenen ein brauchbares Nachschlagewerk ist. Gerne nehme ich Kritik und Verbesserungsvorschläge entgegen. München-Solln, im August 1992 Nikolaus M. Heusler KAPITEL 1: BASIC-PROGRAMMIERHILFEN Der Detektiv für Basicprogramme: Anleitung zum Basic-Kontroll System (BKS), Version 5.0 Gleich der erste Beitrag im Buch ist ein Highlight: Ein hervorragendes Hilfsprogramm prüft Ihre Programme. Fehlerhafte Zeilen werden angezeigt und auf Wunsch ausgedruckt. Die zweitraubende und schweißtreibende Fehlersuche in einem Programm wird damit kinderleicht. Das kurze Maschinenprogramm geht ein im Speicher stehendes Basicprogramm Zeile für Zeile durch und testet dabei, ob typische Fehler enthalten sind, die von vielen Leuten gemacht werden, beispielsweise: Klammer zu viel oder wenig, Syntaxfehler, Formatfehler im Programmtext. Ganz besonders hat es die Testroutine auf Sprungbefehle abgesehen. Hier werden eigentlich alle möglichen Fehler gefunden. Dieses Programm wurde von mir als redaktionellem Mitarbeiter eigentlich entwickelt, um Basic-Leserlistings für das 64'er-Magazin auf ihre Lauffähigkeit zu testen. Doch das BKS (Basic Kontroll System) ist sicherlich nicht nur für professionelle Programmtester interessant. Auch der »Privatmensch« kann durchaus etwas damit anfangen. Beispielsweise ein Einsteiger, der gerne überprüfen möchte, ob das Basicprogramm, das er gerade geschrieben hat, auch sicher läuft. Auch der Fortgeschrittene hat etwas davon. Nehmen wir einmal an, Sie haben ein längeres (vielleicht sogar fremdes) Basicprogramm vorliegen, das Sie überarbeiten möchten. Sie nehmen hie und da eine Zeile heraus, fügen dort eine neue ein, und vertauschen einige Programmteile. Doch was ist, wenn Sie dabei irgendwo einen GOTO-Befehl übersehen haben, der jetzt auf eine nicht mehr existierende Zeile weist? Das Programm wird plötzlich aussteigen, wie üblich dann, wenn man es am wenigsten braucht. Wenn Sie bereits Profi sind, kennen Sie sicher folgende Situation: Sie haben ein langes und komplexes Basicprogramm geschrieben, das von Maschinenprogrammen unterstützt wird. Da wird dann eifrig im Speicher herumgepoket, der Programmierer wirft mit SYS-Befehlen um sich, ein Finger hat seinen Stammplatz am RESET-Taster. Es ist bereits 2 Uhr nachts. Hopps ! Da haben Sie in der Eile einen falschen POKE-Befehl eingegeben, der das Basicprogramm angegriffen hat. Oder durch eine ungeschickte Manipulation wurde der Basic-Endezeiger 45/46 so verändert, daß ein Start des Programmes den totalen Absturz zur Folge hat. In solch einem Fall lädt man einen Monitor und versucht, zu retten, was noch zu retten ist. Doch stimmen alle Zeiger, alle Zeilennummern, alle Sprünge jetzt noch? In allen diesen Fällen können Sie sich mit dem BKS behelfen. Obwohl das BKS aus Gründen der Geschwindigkeit und des Komforts vollständig in stark optimierter Maschinensprache verfaßt wurde, brauchen Sie zur Anwendung keinerlei Assemblerkenntnisse. Laden Sie die Testroutine mit LOAD "BKS 5.0 (49152)",8,1 Danach geben Sie bitte NEW ein, um alle Pointer richtigzustellen. Keine Angst, das Maschinenprogramm wird dabei nicht gelöscht. Es kann jederzeit mit SYS 49152 gestartet werden, allerdings nur, wenn sich ein Basicprogramm im Speicher befindet. Sonst wird eine entsprechende Meldung ausgegeben. Laden Sie nun also das zu testende Basicprogramm. Der Stand des Basic-Anfangszeigers (43/44) spielt keine Rolle. Starten Sie nun das BKS mit SYS 49152. Es erscheinen nun einige Fragen, die Sie durch Druck auf die Taste für Ja oder für Nein beantworten. Zunächst werden Sie gefragt, ob Spaces bemängelt werden sollen. Manche Programmierer setzen in Basicprogramme viele Leerzeichen, um sie übersichtlicher zu machen, andere verschmähen dies. Sollten Sie zu letzteren gehören, können Sie die Frage mit beantworten, dann wird auch getestet, ob außerhalb von Anführungszeichen und DATAs überflüssige Spaces auftreten. Wenn in einem Programm allerdings zu viele Leerzeichen sind, besteht die Liste, die das BKS erzeugt, praktisch nur noch aus diesem Fehler, und wird unübersichtlich. Schalten Sie den Fehler dann also besser aus. Die nächste Frage hat eine ähnliche Funktion. Das BKS kann auf Wunsch auch Sprünge (RUN, GOTO, GOSUB, THEN) finden, die auf eine REM-Zeile oder eine Trennzeile, das ist eine Zeile dieser Art: 10 : weisen. Das kann problematisch werden, wenn das Programm mit einem »unintelligenten« REM-Killer bearbeitet wird. Auch Listings in einer Zeitschrift sollten solche Sprünge nicht enthalten, da der eine oder andere Leser die REM-Zeilen wegläßt und nicht alle Sprünge findet, die er zu korrigieren hat. Auch diese Fehlermeldung kann man »ausblenden«, wenn der Fehler allzu oft auftritt. Drücken Sie dazu die N-Taste. Die folgende Frage ist wieder so etwas ähnliches. Man kann damit gleich zwei Fehler auf einmal ausblenden: Den Fehler Nr. 7, der angezeigt wird, wenn ein Sprungbefehl auf einen Strukturierbefehl zeigt, den man auch anstelle des Sprungbefehles hätte setzen können. Beispiel: 10 A = 4 : GOTO 20 20 RETURN kann man auch einfacher so schreiben: 10 A = 4 : RETURN Der zweite Fehler, der von diesem »Schalter« betroffen ist, ist der Fehler Nr. 17. Er wird gemeldet, wenn der Programmierer direkt hinter das Befehlswort THEN einen GOTO Befehl gesetzt hat (anstelle THEN GOTO 12 schreibt man kürzer THEN 12). Da beides aber Schönheitsfehler sind, kann man sie, wenn sie zu häufig auftreten, beide zusammen ausblenden, indem die Frage mit beantwortet wird. Die letzte der vier »Ausblendfragen« betrifft gleich drei Fehler: Wie Sie aus der Liste ersehen können, betreffen diese Fehler 12, 13 und 14 Befehlswörter, die ein geübter Programmierer nicht verwendet: LET, NEW und STOP. LET kann man sich sowieso sparen, und NEW und STOP gehören nicht in ein gutes Basicprogramm. Falls der Bediener des BKS anderer Meinung ist, kann er die Ausgabe der drei Fehler unterdrücken, indem er die Frage mit beantwortet. Als nächstes werden Sie gefragt, ob die fehlerhaften Zeilen auch gelistet werden sollen, oder ob die Ausgabe der Zeilennummer genügt. Beantworten Sie auch diese Frage wieder mit oder . Die letzte Frage dient dazu, festzulegen, auf welches Gerät die Fehlerliste ausgegeben werden soll. Drücken Sie eine der Tasten , oder : S: Die Fehlerliste wird auf dem Bildschirm ausgegeben. Dieser Modus ist vor allem bei sehr kurzen Programmen angebracht, und zum Test, ob die ausblendbaren Fehler (siehe oben) zu oft vorkommen. D: Die Liste wird auf dem Drucker ausgegeben. Die Geräteadresse ist 4, die Sekundäradresse 0. Die Routine wurde für Commodore-kompatible Drucker geschrieben, müßte jedoch auch mit anderen Printern zusammenarbeiten. Diesen Ausgabemodus braucht man, wenn die Fehlerliste schriftlich vorliegen soll, beispielsweise beim Test von Leserlistings. Da die selbe Routine wie zur Bildschirmausgabe verwendet wird, ist die Ausgabe nicht breiter als 40 Zeichen. Sollten die eckigen Klammern, in denen der Härtecode erscheint (siehe unten), auf Ihrem Drucker nicht oder fehlerhaft (z.B. als deutsche Umlaute) wiedergegeben werden, beachten Sie bitte die untenstehenden Hinweise. F: Listet die Aufstellung auf Diskette. Dabei wird auf der (eingelegten) Floppy ein Basicprogramm mit dem Namen erzeugt, den Sie nun eingeben. Er beginnt gewöhnlich mit der Kennung »DOC.« für DOCument, diese kann durch Eingabe von jedoch überschrieben werden (Vorsicht! Den Cursor nicht weiter links als auf das »D« bewegen!). Dieses File kann dann wie ein normales Basicprogramm geladen werden, ansehen können Sie sich die Auswertung durch Eingabe von LIST oder RUN (frei nach Wahl). Nach der Eingabe dieser Parameter geht das BKS das Basicprogramm nun Zeile für Zeile durch und überprüft, ob es Fehler enthält. Bei jeder neuen Zeile wechselt der Bildschirmrahmen seine Farbe, so erkennen Sie, wenn es länger dauert, daß die Routine nicht abgestürzt ist (das BKS ist so programmiert, daß es nicht abstürzen KANN). Am Ende des Tests werden alle Dateien geschlossen und das BKS beendet. Jedesmal, wenn ein Fehler auftritt, wird eine Zeile mit folgendem Format ausgegeben (auf Schirm, Drucker oder Diskette): AAAAA: BB[C] blablablabla AAAAA ist die Basic-Zeilennummer, in der der Fehler auftritt. Sie wird rechtsbündig ausgegeben. BB ist die laufende Nummer des Fehlers, siehe dazu die untenstehende Tabelle. Es gibt zwei verschiedene Fehlergrade, die C angibt: leichte Fehler, die eigentlich nur Schönheitsfehler sind und keine Fehlfunktion des Programmes bewirken. C ist bei diesen Fehlern 1. Beispiele: überflüssige Spaces, Listschutz, LET-Befehl. Anders ist es bei den schweren Fehlern (C=2): Hier wird sich das Programm mit einer Basic-Fehlermeldung verabschieden, beispielsweise, wenn Sprungbefehle auftreten, die auf nicht vorhandene Zeilen zeigen, wenn das Programm formal zerstört ist (POKEs) oder bei Syntaxfehlern. Der hier mit »blablablabla« bezeichnete Teil stellt einen Pauschaltext dar, der ungefähr die Art des Fehlers angibt. Die möglichen Texte sind: »FORMATFEHLER«, »SPRUNGFEHLER«, »ÜBERFLÜSSIGER BEFEHL« und »UNERLAUBTER BEFEHL«. Da dieser Pauschaltext nicht genau die Art des Fehlers angibt, ist der Parameter BB besonders wichtig: Er kann 28 verschiedene Werte annehmen: (in Klammern der Härtecode, Parameter C) 1 {1} Direkt nach der Zeilennummer folgt ein Nullbyte (dies wird zu Listschutzzwecken verwendet). 2 {1} Im Programmtext kommt ein überflüssiges Leerzeichen vor. Nach DATA, in Anführungszeichen oder wenn diese Funktion abgeschaltet ist, werden die Spaces nicht bemängelt. 3 {2} Ein THEN, GOTO, LIST, RUN oder GOSUB Befehl zeigt auf eine nicht existierende Zeile (UNDEF'D STATEMENT) 4 {2} Die hinter einem dieser Befehle stehende Zeilennummer ist größer als 63999. 5 {2} Die hinter einem dieser Befehle stehende Zeilennummer enthält verbotene Zeichen (etwa GOTO 4+6 oder GOTO LABEL). PASCAL gewohnte Programmierer werden diese Funktion des BKS zu schätzen wissen. 6 {2} Eine Basic-Zeile ist länger als 255 Zeichen (Fehler von der Suchroutine). 7 {1} Ein GOTO oder THEN Befehl zeigt auf einen RETURN, GOTO, RUN usw. Befehl (Strukturierbefehl), den man auch einfach anstelle des Sprungbefehles hätte setzen können. 8 {1} Ein Sprungbefehl zeigt auf eine REM- oder Trennzeile (das ist eine Zeile, die nur einen Doppelpunkt enthält). Das kann zu Problemen beim Abtippen führen, wenn die REM Zeile weggelassen wird. Falls in einem Listing dieser Fehler zu oft vorkommt, kann auch die Ausgabe dieses Fehlers abgeschaltet werden. 9 {2} Eine Basic-Zeile ist länger als 255 Zeichen (Fehler von der Hauptroutine). Wenn dieser Fehler auftritt, dürfen eventuelle sonstige Fehler nicht mehr unbedingt ernstgenommen werden, da dann das System vollkommen durcheinandergerät. 10 {2} Ein GOTO oder RUN-Befehl zeigt auf sich selbst (nicht hinter THEN; Beispiel: 10 GOTO 10) 11 {2} Der Befehl CONT darf nicht im Programmtext vorkommen. 12 {1} Der Befehl STOP sollte nicht im Programmtext vorkommen. 13 {1} Der Befehl NEW sollte nicht im Programmtext vorkommen. 14 {1} Der Befehl LET sollte nicht im Programmtext vorkommen. 15 {1} Hinter einem REM Befehl steht ein geshiftetes L (Listschutz). 16 {2} Ein illegales Token (Zeichen, Byte) kommt im Programmtext vor. 17 {1} Der Befehl GOTO sollte nicht direkt hinter THEN stehen, einer von beiden genügt. 18 {2} Hinter einem Befehl fehlt der Parameter (z.B. OPEN). 19 {2} Hinter GO fehlt TO. 20 {1} Hinter GOTO, RUN etc folgen weitere Befehle, die niemals ausgeführt werden (z.B. GOTO 20:PRINT "GEISTERBAHN") 21 {2} Klammer(n) zu viel bzw. wenig. 22 {1} Das Zeichen »^« (Pfeil nach oben) zur Potenzierung sollte vermieden werden (große Rechenungenauigkeit). 23 {2} Der Befehl PRINT# wurde mit ?# abgekürzt. (SYNTAX ERROR) 24 {2} Falsche Reihenfolge der Basiczeilen. Das kann zu Problemen bei Sprungbefehlen führen. 25 {2} Ein falscher Linkpointer kommt im Programmtext vor. (Vor jeder Basic-Zeile steht im Speicher ein Zeiger, der angibt, wo im Speicher die nächste Zeile beginnt. Anhand dieser Zeiger »hangeln« sich u.a. die Sprungbefehle zur gesuchten Zeile.) 26 {2} ON ohne legalen Sprungbefehl. 27 {2} THEN ohne IF. 28 {1} Der Pointer 45/46 zeigt nicht genau auf das Byte hinter dem Basic Programm. Wahrscheinlich ist noch ein Maschinenprogramm angehängt, oder es wurde ein fehlerhafter RENEW-Befehl verwendet. Die Fehler 6 und 9 unterscheiden sich in ihrer Bedeutung nicht und werden ggf. immer paarweise erscheinen. Diese Meldungen werden innerhalb des BKS an zwei verschiedenen Stellen erzeugt: Nummer 6 in dem Unterprogramm, welches bei Sprungbefehlen die Existenz der angesprochenen Zeile überprüft, und Nummer 9 in der Hauptroutine, die das Basicprogramm Befehl für Befehl durchgeht und nach Fehlern sucht. Die »Fehler«-Meldungen Nr. 11 (CONT) und Nr. 5 (GOTO 4+6) wurden ebenso wie zum Beispiel Nr. 22 oder Nr. 12 nur der Vollständigkeit halber in das BKS aufgenommen. Sie bezeichnen keine schweren Fehler, insofern ist der Härtecode 2 hier prinzipiell übertrieben. Die eckigen Klammern, in denen der Härtecode erscheint, können auf dem Drucker nur dann richtig wiedergegeben werden, wenn Sie ihn vom deutschen in den amerikanischen Zeichensatz schalten (bei MPS-Druckern nicht nötig). Sollten hier falschen Zeichen ausgegeben werden, und gelingt Ihnen die Anpassung nicht, können Sie den Code auch direkt im Programm ändern, beispielsweise in runde Klammern. Die entsprechenden Speicherzellen sind $ca4e und $ca5f. Wie funktioniert das BKS intern? Für eine genaue Funktionsbeschreibung reicht hier leider der Platz nicht aus. Der interessierte Leser erhält jedoch vom Autor gegen Einsendung einer Diskette und einer Gebühr von DM 10,- gern den kompletten Quelltext (gilt für alle Programme!). Die Adresse finden Sie in dem im folgenden beschriebenen Programm »BKS.WHAT«. Dabei handelt es sich um ein wichtiges Zusatzprogramm zum BKS, mit dem die ausgegebenen Listen genau kommentiert werden. Die Anwendung ist einfach: Laden Sie wie oben beschrieben das BKS, dann das zu testende Programm. Führen Sie den Test durch, und lassen Sie sich die Referenz auf den Drucker ausgeben. Danach laden Sie, ohne vorher den Computer auszuschalten, das Programm "BKS.WHAT 5.0" und starten es mit RUN. Sofern vorher eine Auswertung mit dem BKS durchgeführt wurde, erscheint jetzt die Frage nach dem Datum und dem Namen des getesteten Basicprogrammes. Alle anderen Angaben hat das BKS dem Kommentierprogramm bereits übergeben (im »Common-Bereich«, siehe Speicherbelegung). Nach kurzer Zeit wird jetzt ein ausführlicher Kommentar auf den Drucker ausgegeben, und zwar diesmal über die Sekundäradresse 7 (Groß-/Kleinschriftmodus). Darin enthalten ist eine kommentierte Liste ähnlich der oben abgedruckten, die Auskunft über die genaue Bedeutung der aufgetretenen Fehler gibt (siehe Beispielausdruck). Das Druckprogramm wurde für MPS-Drucker geschrieben, und enthält einige Steuercodes dieser Drucker. Ich wünsche Ihnen nun noch viel Erfolg mit dem BKS! ANHANG: Speicherbelegung des BKS (Version 5.0, hexadezimal): 0002-0003 temporär (u.a. Zeiger auf Programm) 0334-0344 Filename C000-CCDD Programm »BKS« C000-C002 Sprung nach $C687 (Anfang) C003-C239 verschiedene Texte (gepackt) C23A-C23B Nummer der gesuchten Basic Zeile für $C37C C23C Flag C23D Flag: Anführungszeichenmodus C23E Flag: REM C23F-C240 Nummer der aktuellen Zeile C241 Position in dieser Zeile C242 Nummer des Fehlers C243-C246 Integerzahlen für Multiplikation mit 10 C247 aktuelles Token C248 aktuelle Zeigerposition C249 Anzahl der Klammerebenen C24A Anzahl der Ziffern hinter Sprungbefehl C24B Flag: THEN C24C Flag: ON C24D Geräteadresse für Ausgabe (3, 4, 8) C24E Low-Byte der Anzahl der leichten Fehler C24F Low-Byte der Anzahl der schweren Fehler C250 High-Byte der Anzahl der leichten Fehler C251 High-Byte der Anzahl der schweren Fehler C252 Flag: DATA C253 letzter Zustand von $C252 C254 Sekundäradresse für Ausgabe C255 Hochkommaflag für Listroutine C256 Flag: Basic Zeilen listen C257 Pointer für Listroutine C258 »First«-zeiger C259-C25A letzte Fehlerzeilennummer C25B temporär C25C wie $C248 C25D Flag: ON/Hochkomma C25E wie $C248 C25F letztes Zeichen C260-C27D Tokentabellen C27E-C2C1 Texte der Fehler C2C2-C2F9 Zeiger auf diese Texte C2FA-C315 Härtecodes der Fehler (AscII) C316-C37B Vorspann für erzeugtes Basicprogramm C37C-CCDD 100% Maschinenprogramm. Interessante Routinen: C37C Sucht die Zeile (X/Y) C4DE Entschlüsselt Text ab (A/Y) und gibt ihn aus C562 Holt nächstes Zeichen aus Basic Text C56F Holt Parameter C584 Holt Tasten J/N C687 Anfang des Hauptprogrammes C6D9 Schleife: Neue Basic Zeile C710 Hauptschleife: Nächstes Zeichen C77A Nächstes Zeichen CA0D REM-Routine CA19 Unterroutinen zu $CACE CACE Gibt Fehlermeldung Nr. X aus CBE0 fertig CC5D Holt Zahl hinter Sprungebefehl CE00-CEFF Puffer für Listroutine CF00-CFFF "Common-Bereich" (hier werden die Ergebnisse des BKS an BKS.WHAT übergeben) CF00-CF04 Erkennungstext »NSS88« CF05 Versionsnummer primär (=5) CF06 Versionsnummer sekundär (=0) CF07 Flag: Fehler Nr. 2 ausgekoppelt (0 = ja) CF08 Flag: Fehler Nr. 8 ausgekoppelt (0 = ja) CF09 Identifikationsbyte (123 = BKS läuft, 222 = BKS fertig) CF0A Flag: Fehler Nr. 7/17 ausgekoppelt (0 = ja) CF0B Flag: Fehler Nr. 12-14 ausgekoppelt (0 = ja) CF0C-CF27 Tabelle aller 28 Fehler (1 = tritt auf) Anleitung zum Programm »HELP«: Dieses Programm ist vor allem für Basic-Einsteiger gedacht, die oft vor dem Bildschirm sitzen und sich wundern, was der Commodore 64 doch alles für Fehlermeldungen erzeugen kann, die er selbst nicht einmal aus dem Handbuch kennt. Wie schön wäre es doch, wenn der Computer auf Anforderung die soeben gezeigte Meldung kurz mal erklären könnte. Genau dies ist mit dem Programm »HELP« in Zukunft problemlos möglich. Laden Sie das Programm mit dem Befehl LOAD "HELP !!",8 und starten durch Eingabe von RUN. Es wird nun noch ein Maschinenprogramm nachgeladen und gestartet. Ab jetzt haben Sie die Möglichkeit, nach jeder Fehlermeldung, die der Computer ausgibt (vom einfachen SYNTAX ERROR über den TYPE MISMATCH ERROR oder ILLEGAL DIRECT ERROR bis hin zum unverständlichen FORMULA TOO COMPLEX ERROR) einfach den neuen Befehl HELP einzugeben (und ), und schon erklärt der Computer in ein paar Zeilen auf Deutsch, was der Grund für diese Fehlermeldung sein könnte. Der HELP-Befehl soll nur im Direktmodus und direkt nach der Ausgabe der Meldung, nicht erst nach dem nächsten (möglicherweise ja wieder korrekten) Befehl verwendet werden. Nach einem oder versehentlichen Abschalten der Erweiterung durch ein anderes Programm kann HELP, so es sich noch im Speicher befindet, mit SYS 29952 wieder gestartet werden. Dieses kleine Hilfsprogramm (der Hauptteil des Nachladeprogrammes wird von den erklärenden Texten belegt) ist sicher eine nützliche Hilfe beim Programmieren, die vor allem Einsteiger sehr bald schätzen werden. HIlfe - die Datas kommen! Dieses »clevere« Utility ist vor allem dann praktisch, wenn Sie mit DATAs arbeiten. Es baut einige neue Befehle in den C 64 ein, die beim Programmieren oder Eintippen von DATAs nützlich sind. Obwohl es vollkommen in Maschinensprache geschrieben ist, müssen Sie nicht in Maschinensprache programmieren können, um es anzuwenden. Zahlen in einer FOR..NEXT-Schleife mit READ aus DATA-Zeilen zu lesen und diese dann in den Speicher zu POKEn ist die am häufigsten angewandte Methode, zum Beispiel ein Assemblerprogramm oder Sprite-Daten in den Speicher zu laden. »DATA-Aid« kann Ihnen in vielfältiger Hinsicht helfen, wenn Sie es mit DATA-Daten zu tun haben. Sie laden dieses in Maschinensprache verfaßte Utility wie ein Basicprogramm mit LOAD "DATA AID",8 und starten mit RUN Jetzt wird automatisch eine Routine in einen vor Basic geschützten Bereich kopiert und die Erweiterung installiert. Der Bildschirm färbt sich grün und eine Meldung erscheint. Jetzt wurden fünf neue Befehle ins Basic eingebaut. Diese können wie normale Basicbefehle verwendet werden, im Programm- oder Direktmodus. Das Ausrufezeichen dient als Kennzeichen dafür, daß ein neuer Befehl folgt. Wenn Sie jetzt gleich mit DATA-AID arbeiten möchten, sollten Sie zunächst mit NEW den Basicspeicher löschen, da hier ja noch die SYS-Zeile zum Start von DATA-AID steht. Und das sind die neuen Kommandos: !R - Restore. Dieser Befehl setzt den DATA-Zeiger auf eine bestimmte Programmzeile. !R wirkt also wie RESTORE, nur daß nicht auf den Anfang des Programmes gesetzt wird, sondern bei !R 100 zum Beispiel auf die DATA-Zeile 100 (falls es diese gibt, sonst auf die nächste DATA-Zeile). Sie können, ähnlich wie beim RENUMBER n Befehl des C 128, nicht nur Zahlen, sondern beliebige numerische Ausdrücke hinter !R verwenden, also zum Beispiel auch !R 9*X+40-PEEK(3) Der nächste Befehl heißt !S - Speed Poke. Dieser Befehl tranportiert sehr schnell Zahlen aus DATA-Zeilen in den Speicher. Der Befehl lautet genau: !S Zeilennummer, Speicherstelle Also schafft zum Beispiel !S 100,8192 alle Zahlen, die in den DATA-Zeilen 100ff abgelegt sind, ab 8192 in den Speicher. Der Vorgang endet, wenn eine negative Zahl gelesen wird. Beispiel: Dieses Programm schreibt DATA-AID rechts oben auf den Bildschirm: 10 !S20,1024 20 DATA68,65,84,65,45,65,73,68,-1 30 !S40,55296 40 DATA1,1,1,1,1,1,1,1,-1 50 END Diese Methode arbeitet über viermal so schnell wie die bekannte Befehlsfolge 10 READA:IFA<0THENRETURN 20 POKEM,A:M=M+1:GOTO10 !S kann in Programmen oder im Direktmodus verwendet werden. Verwenden Sie diesen Befehl nur, wenn die gelesenen DATA-Zeilen nur Werte von 0 bis 255 enthalten, andernfalls erhalten Sie eine Fehlermeldung. Haben Sie die negative Zahl am Ende vergessen, erscheint der normale ?OUT OF DATA ERROR. Dieser negative Wert wird natürlich nicht in den Speicher geschrieben, er markiert nur das Ende der Liste. Übrigens brauchen Sie gar keine echte negative Zahl zu setzen, es reicht im Prinzip das Minuszeichen. !C - Check. Dieser Befehl arbeitet grundsätzlich wie !S, allerdings werden die Werte nicht in den Speicher geschrieben, sondern einfach addiert. Die »Prüfsumme« wird ausgegeben. So können Sie testen, ob die Werte in Ordnung sind. Daher entfällt hier auch die Angabe der Speicherzelle, der Befehl lautet also zum Beispiel !C 100, wenn die DATA-Zeilen ab 100 summiert werden sollen. Hier können auch positive Zahlen über 255 verwendet werden. Der Computer gibt die Summe in Form einer Meldung DIE PRUEFSUMME IST XXXXX aus. !D - DATA-Zeilen erzeugen. Benutzen Sie diesen Befehl, wenn schon Daten im Speicher stehen, und Sie diese in DATA-Zeilen verwandeln wollen. Dieser Befehl hat folgende Syntax: !D ADR1,ADR2+1,ZEIL,ANZ,STEP Dabei gibt ADR1 und ADR2 den Speicherbereich an (bitte denken Sie daran: Die Endadresse ADR2 muß um eins erhöht angegeben werden), ZEIL ist die erste Zeilennummer, die dann im Schritt STEP erhöht wird (z.B. 10). Dabei werden ANZ DATAs pro Zeile untergebracht. ANZ ist aus dem Bereich von 1 bis 19. So wandelt zum Beispiel der Befehl !D 52525,53248,2000,19,1 das Programm DATA-Aid (52525 bis 53247) in DATA-Zeilen ab 2000 in der Schrittweite 1, es werden 19 DATAs pro Zeile ausgegeben. Die mit diesem Kommando erzeugten Zeilen könnten dann zum Beispiel mit einem Speed-Poke (!S) wieder eingelesen werden. Bedenken Sie aber bei Verwendung von !D, daß die DATA-Zeilen etwa viermal so viel Speicherplatz belegen wie der ursprüngliche Speicherbereich. Wenn ein ?OUT OF MEMORY ERROR zu sehen ist, müssen Sie den Rechner aus- und wieder einschalten, damit Sie weiterarbeiten können. Auch wenn der Befehl !D besonders bei größeren Speicherbereichen einige Zeit in Anspruch nimmt, während der sich der Computer nicht zurückmeldet (am Ende erscheint dann READY.), dürfen Sie den Vorgang auf keinen Fall mit abbrechen. Die neuen DATA-Zeilen werden übrigens einfach an der korrekten Stelle in ein ggf. schon bestehendes Basicprogramm eingefügt, also als ob Sie sie neu über Tastatur eingegeben hätten. Bereits bestehende Basiczeilen mit gleichen Nummern wie die neuen DATA-Zeilen werden überschrieben. !D ist in erster Linie für die Verwendung im Direktmodus geschaffen, kann aber auch vom Programm aus verwendet werden. Nach der Ausführung befinden Sie sich allerdings auf alle Fälle im Direktmodus. !Z - Exit. Dieser Befehl schaltet die Erweiterung ab. Dies sollten Sie tun, wenn Sie andere Erweiterungen verwenden wollen, die den selben Speicherbereich belegen oder ebenfalls neue Befehle definieren. Sofern sich DATA-Aid noch im Speicher befinden, kann es mit SYS 52525 (leicht zu merken) jederzeit wieder aktiviert werden. Eine Bemerkung noch zu den neuen Befehlen: Werden sie direkt hinter THEN verwendet, müssen Sie sie mit einem Doppelpunkt abtrennen, also zum Beispiel so: IF A > 40 THEN : !R A*10 Wenn Sie DATA-AID testen wollen, schreiben Sie einfach große Teile des Bildschirms mit beliebigem Text voll. Diesen Screen wollen wir in DATAs im Programm festhalten. Dazu geben Sie jetzt die Befehle NEW !D 1024,2024,2000,19,2 ein und gedulden sich einige Sekunden. Nach Erscheinen der READY.-Meldung geben Sie LIST ein, um das Ergebnis zu begutachten: Scheinbar endlose Kolonnen von DATA-Zeilen, beginnend bei Zeile 1000. Fügen Sie selbst noch die Zeile hinzu: 9999 DATA-1 Jetzt löschen Sie den Bildschirm und holen den Inhalt wieder zurück, natürlich mit Speed-Poke: !S 2000,1024 erledigt das für uns. Anmerkung: Auf älteren Modellen des C 64 ist der Bildschirminhalt noch nicht sichtbar, da die Textzeichen die Farbe des Hintergrundes haben. Um sie sichtbar zu machen, verändern Sie einfach nachträglich die Farbe des Hintergrundes. Ist der Bildschirm momentan zum Beispiel nicht weiß, machen Sie ihn mit POKE 53281,1 weiß. Nun für den interessierten Leser noch eine kurze Beschreibung der programminternen Funktionsweise: DATA-Aid liegt im Speicherbereich 52525 bis 53247 ($CD2D-$CFFF). In der Zeropage werden die sonst unbenutzten Zellen 2 bis 5, 166/7, 181/2, 251-3 und 704-8 verwendet. Die neuen Befehle werden definiert, indem der IGONE-Vektor (776/7) auf eine neue Routine verbogen wird, die das Ausrufezeichen sucht. Der !R Befehl berechnet die Adresse der angegebenen Zeilennummer (Routine ab $A613) und verbiegt den DATA-Vektor (65/66) auf die Adresse. Die Befehle !S und !C rufen vor ihrer eigentlichen Arbeit !R auf, um die richtige DATA-Zeile »anzufahren«. Der Basic-Pointer 122/3 wird auf den Stack gerettet und auf die Adresse der ersten DATA-Zeile verbogen. Der C 64 sucht das Befehlstoken 131 (DATA) und setzt den Zeiger dahinter, auf den ersten DATA-Wert. Nun können mit den normalen FRMNUM-Routinen ($AD8A, $B79E) die Werte gelesen und in den Speicher geschrieben bzw. addiert werden. Die Addition bei !C geschieht mit Hilfe der Floatingpoint-Arithmetik, dabei wird der FAC immer wieder bei 704-708 zwischengespeichert. Der Befehl !D verbiegt den Vektor zur Eingabe einer Basiczeile (770/1) auf eine eigene Routine. Ab $A480 springt der Computer über diesen Vektor. Er arbeitet nun nicht die Routine ab $A560 ab, die von Tastatur eine Zeile in den Basic-Eingabepuffer ab 512 holt, sondern eine DATA-AID-Routine, die auch im Basic-Eingabepuffer eine Zeile der Form Zeilennummer, DATA, Werte durch Kommata getrennt aufbaut. Diese Zeile wird dann der normalen Routine ab $A486 übergeben, diese wertet die Zeile aus und baut sie in das Basicprogramm ein. Wir wünschen Ihnen viel Spaß und Erfolg mit DATA-AID. Genießen Sie die Vorzüge und den Komfort, den Ihnen dieses kurze und neuartige durchdachte Tool bietet! TI und TI$ greifen auf die CIA-Uhr zu Sinn und Zweck der Routine »TI$« ist, die Arbeitsweise der reservierten Basic-Variablen TI und TI$ zu ändern. Bisher wird der System-Interrupt-Zähler abgefragt bzw. gesetzt, wenn man mit TI oder TI$ arbeitet. Da dieser sehr ungenau ist (Abweichungen bis zu einer halben Stunde per Tag sind keine Seltenheit) und bei Ein/Ausgabe sogar angehalten wird, bietet es sich an, stattdessen die Echtzeituhr einer CIA zu verwenden. Genau das erfolgt mit der nur wenige Bytes kurzen Routine TI$. Wurde sie erst einmal mit LOAD "TI$",8 RUN aktiviert, baut das Programm intern die TI$ und TI um. Die Funktionen sind voll kompatibel zur Originalversion (eine Ausnahme gibt's, siehe unten). Bevor Sie TI$ oder TI abfragen können, muß allerdings erst eine Uhrzeit gesetzt werden, da die Uhr sonst noch steht. Dazu verwenden Sie den normalen Befehl TI$ = "HHMMSS" Drei Zugriffsarten sind erlaubt. TI$ kann sowohl gelesen wie auch geschrieben werden, und TI kann nur gelesen werden. Dies entspricht dem Original-System. Eine Zuweisung wie TI = 12345 führt zur Fehlermeldung ?CAN'T DEFINE ERROR die neu eingeführt wurde. Wichtiger Hinweis: Soll eine Zuweisung der Form TI$=... direkt nach THEN erfolgen, muß nach THEN ein Doppelpunkt stehen. Also nicht IF A = 10 THEN TI$ = "230000" sondern IF A = 10 THEN : TI$ = "230000" Dies ist die einzige Änderung zum Originalsystem. Vergessen Sie den Doppelpunkt, wandert die Neueinstellung ins Nirwana (sog. »Ablage P«). Ansonsten können Sie mit TI$ und TI operieren, wie Sie es gewohnt sind. Im Direkt- oder Programm-Modus. Also auch als Bestandteile eines Terms (MID$(TI$,3,2) ermittelt die Minuten). Nur daß eben nicht die Systemuhr, sondern die Uhr der CIA 1 ($DC00) Verwendung findet. Obwohl die Uhr der CIA eine Genauigkeit von einer Zehntelsekunde hat, erscheint bei TI$ nach wie vor nur ein String mit sechs Zeichen, um die Kompatibilität zu wahren. Die 1/10 Sekunden kann der interessierte Anwender über TI ermitteln. TI hat jetzt natürlich nur noch eine Auflösung von 1/10 Sekunde, gibt aber - Kompatibilität - dennoch nach wie vorher die Zeit in 1/60 Sekunden an (der Wert von TI ist demnach immer ein Vielfaches von 6). Änderungen an TI$ bewirken automatisch Änderungen an TI. Die Zuweisung TI$ = ... kann auch nach LET stehen. Die Variable TI% kann weiterhin als »stinknormale« Integer-Basicvariable Verwendung finden, die nichts mit der Uhrzeit zu tun hat. Nach TI können aber auch beliebig weitere Buchstaben oder Ziffern folgen, wie es sich für einen Variablennamen gehört (also TIME$="123456" oder PRINT TIIII/60 "SEKUNDEN"). Außerdem arbeitet natürlich auch unsere neue TI$-Version mit einer 24-Stunden Uhr, obwohl die CIA-Uhr eigentlich nur 12 Stunden (AM/PM-Flag) läuft. Umrechnungsroutinen sind enthalten. Wie Sie sehen, steckt viel Liebe im Detail dieser Erweiterung. Das alles, um die Routine voll kompatibel zu machen. Selbstverständlich wird die CIA-Uhr vor dem Betrieb auf 50 Hertz geschaltet, sonst würde unsere Uhr, die ihren Takt aus der Netzfrequenz bezieht, grob falsch gehen. Eine zweite neue Fehlermeldung gibt es noch: ?TIME FORMAT ERROR erscheint immer dann, wenn der String, der an TI$ übergeben wird, keine vernünftige Uhrzeit enthält. Mögliche U(h)rsachen: Länge ungleich 6 Bytes, enthält nicht nur Ziffern, Minuten oder Sekunden größer 59, Stunden größer 23. Die Routine kann auch wieder abgeschaltet werden, dazu geben Sie einfach SYS 58451 ein. Wiedereinschalten ist, ggf. auch nach einem Reset, mit SYS 49152 wieder möglich. Die Funktionsweise ist einfach zu verstehen. Für diejenigen, die das interessiert, wurde das Assemblerlisting (Profi-Ass Format) sehr gut kommentiert. Daher sollen hier nur allgemeine Hinweise stehen. Der Computer verbiegt die Vektoren zur Ausführung eines Basic-Befehles und zur Auswertung eines Basic-Arguments auf neue Routinen. Die neue Befehlsroutine (Label NEUBEF) prüft, ob eine Zuweisung an die Variable TI$ erfolgt (bei TI=... wird die Fehlermeldung ausgegeben). Wenn ja, wertet der C 64 den String aus, berechnet die Uhrzeit und schreibt sie in die Register der CIA. Die Zehntelsekunden werden auf Null gesetzt. Als »Bonbon« erkennt die Routine auch eine Zuweisung der Form LET TI$ = "123456" und bearbeitet sie korrekt. Andere Variablen als TI und TI$ werden normal in der alten Routine bearbeitet. Die neue Routine zur Auswertung eines Terms prüft auf Vorliegen von TI oder TI$. TI% wird von der alten Routine bearbeitet. In beiden Fällen wird jetzt erst einmal die Uhr der CIA 1 ausgelesen und in einen sechs Bytes langen String HHMMSS ab Adresse 255 codiert. Die Zehntelsekunden werden für TI separat erfaßt. Bei TI$ ist die Arbeit schon getan, der String wird zurückgegeben. Dazu dient eine Unterroutine von STR$. Bei TI wird's jetzt sehr kompliziert. Die einzelnen Stellen von TI$ werden von links kaskadisch mit Vielfachen von 60 multipliziert und addiert. Dadurch kommt die Uhrzeit in Sekunden zustande, allerdings ohne Zehntelsekunden. Das Ergebnis multiplizieren wir noch einmal mit 60 und addieren die Zehntelsekunden mal 6 dazu. Das Ergebnis ist TI, die Zeit in 1/60 Sekunden mit einer Genauigkeit von 1/10 Sekunde. Die neue Routine benutzt fünf normalerweise unbenutzte Speicherzellen zur Datenspeicherung: 155 und 247 bis 250. Das Programm liegt im Bereich von 49152 bis 49799 jeweils einschließlich. Weiterer Speicher wird nicht belegt. Im Maschinenprogramm muß an zwei Stellen im Dezimalmodus gerechnet werden (SED). Davor wird jeweils der Interrupt ausgeblendet, damit der Rechner nicht abstürzt, wenn der Controller bei gesetztem D-Flag den IRQ auslöst (wird von vielen Programmierern, auch denen des 1541-Systems, falsch gemacht). Sollte es die spezielle Anwendung erfordern, kann das Programm leicht auf die Uhr der CIA 2 umgestellt werden. Dazu ändern Sie im Quelltext in Zeile 130 das Label CIA von $DC00 in $DD00. Nun bleibt noch eine Frage. Sie haben ja gar keinen Beweis, daß der Computer mit der neuen Routine tatsächlich nicht mehr auf die Systemzeit zugreift, sondern auf die Uhr der CIA. Die Wirkung ist ja haargenau die selbe. Dazu können Sie mit einem Programm, das die CIA-Zeit am Bildschirm einblendet, Kontrollen vornehmen (Beispiel: »Superinfoirq«). Anleitung zum »REM-KILLER ++« Dieser besondere REM-Killer unterscheidet sich wesentlich von herkömmlichen Programmen dieser Art. Während solche Tools (z.B. Trick des Monats in 64'er 01/90) gewöhnlich nur die REM-Zeilen aus einem Basicprogramm entfernen, denkt dieses Tool mit und verändert auch zum Beispiel die GOTO-Befehle im übrigen Programm so, daß es hinterher immer noch läuft. Obwohl dieses Hilfsprogramm aus Geschwindigkeits- und Komfortgründen vollkommen in Maschinensprache geschrieben ist, kann es wie ein Basicprogramm geladen und gestartet werden. Es installiert sich dann im Speicher und wartet darauf, mit einer besonderen Tastenkombination aktiviert zu werden. Zum Beispiel vorher: 10 PROGRAMMTEIL 1 20 IF A = 5 GOTO 40 30 END 40 REM ALTERNATIVE 50 PRINT "..." 60 STOP:REM DAS ENDE Nach der Behandlung mit dem neuartigen REM-Killer sind nicht nur die REM-Zeile 40, die ja nur unnötig Speicherplatz kostet, und der REM-Befehl in Zeile 60 verschwunden, sondern es wurde auch gleich der »verkappte« GOTO-Befehl in Zeile 20 so verändert, daß die Wirkung nachher die gleiche ist: 10 PROGRAMMTEIL 1 20 IF A = 5 GOTO 50 30 END 50 PRINT "..." 60 STOP Ohne die Änderung der Zeile 20 hätte sonst ein ?UNDEF'D STATEMENT ERROR IN 20 auftreten können, da der GOTO-Befehl auf eine nicht mehr existierende Zeile gewiesen hätte. Die Anwendung ist ganz einfach: Laden Sie zunächst das Tool mit dem Befehl LOAD "REM-KILLER++",8 RUN Es erscheint eine Einschaltmeldung. Dann laden Sie das Basicprogramm ganz normal, das gekürzt werden soll. Der Basicspeicher sollte - wie üblich - bei $801 liegen. Dies ist im normalen Betrieb des C 64 der Fall. Zum Kürzen starten Sie nun den Rem-Killer, indem Sie die beiden SHIFT-Tasten gleichzeitig drücken. Wieder erscheint eine Bestätigung. Es wird nun die Programmlänge in Byte ausgegeben, die Kürzung erfolgt, die Befehle GOTO, GOSUB, THEN sowie ON werden automatisch angepaßt, und das Tool gibt die neue Länge aus. Das gekürzte Programm kann jetzt ganz normal weiterbearbeitet oder gespeichert werden. Das Tool erkennt automatisch, wenn sich kein Programm im Speicher befindet, oder das im Speicher befindliche Programm nur aus REM-Zeilen besteht. Kurz zur Funktionsweise: Dieses Tool geht das Basicprogramm in drei »Passes« durch. Im ersten Durchgang (Pass 1) werden alle REM-Befehle erkannt und in Pass 2 aus dem Programm entfernt. Dabei legt das Utility eine Tabelle mit allen im Programm vorkommenden Basic-Zeilennummern an. Hier wird jeder Zeilennummer des Ursprungsprogrammes eine Nummer im neuen Programm zugewiesen, im obigen Beispiel etwa: 10 -> 10 20 -> 20 30 -> 30 40 -> 50 (da Zeile 40 nicht mehr existiert) 50 -> 50 60 -> 60 Im dritten Durchgang sucht der REM-Killer im Programm nach den Befehlen GOTO, GOSUB und THEN mit einer oder mehreren durch Komma getrennten Zeilennummern (für den ON-Befehl) und korrigiert die Nummern nach der Tabelle. Sollte beispielsweise aus einem GOTO 90 ein GOTO 100 werden, da Zeile 90 eine REM-Zeile war, wird das Basicprogramm automatisch an dieser Stelle um ein Byte verlängert, damit die Zahl 100 hinter den GOTO-Befehl paßt. Bei Laden und Starten des Utilities mit RUN wird der IRQ-Vektor auf eine neue Routine verbogen, die die beiden SHIFT-Tasten prüft. Dazu wird 60 mal in der Sekunde direkt mit Hilfe der CIA-Register $DC00 und $DC01 die Tastatur-Matrix abgefragt. Wurde gedrückt (wahlweise auch die SHIFT-LOCK Taste zusammen mit der rechten SHIFT-Taste), schreibt das Programm einen Befehl in den Tastaturpuffer: SYS 49155 Mit diesem Befehl wird der eigentliche REM-Killer gestartet. Sie können diesen Befehl natürlich auch ganz normal im Direktmodus eingeben, wenn Ihnen das komfortabler erscheint. Nach einem Ausstieg mit Reset kann des Tool, sofern es sich noch im Speicher befindet, mit SYS 49152 wieder gestartet werden. Dann ist wieder die Tastenkombination aktiv. 64 Keys: Befehle auf Tastendruck Wer sagt denn, daß man jedesmal bei der Basicprogrammierung mühsam die Schlüsselwörter von Hand eingeben muß? Sie brauchen nur die CTRL-Taste mit einer anderen Taste zu drücken, und schon erscheint ein vollständiger Basicbefehl am Bildschirm. Geben Sie öfters Listings aus Zeitschriften ein? Dann haben Sie auf 64 Keys gewartet! Laden Sie das Programm mit LOAD "64 KEYS (LADER)",8 und starten es mit RUN. Obwohl die Erweiterung in reiner Maschinensprache programmiert wurde, kann das Programmfile wie ein Basicprogramm geladen, gestartet, gespeichert und kopiert werden. Die Routine wird nun in einen Speicherbereich ab 49152 verschoben und dort gestartet. Ein Titelbild erscheint. Der Rechner arbeitet scheinbar ganz normal weiter. Drücken Sie jetzt aber einmal und gleichzeitig eine Buchstabentaste: Voila - ein Befehl erscheint, als ob Sie ihn ganz normal über Tastatur eingegeben hätten. Sie können die Schlüsselwörter nach wie vor voll ausschreiben, müssen das aber nicht unbedingt. Es ist nur dann notwendig, wenn der gewünschte Befehl nicht in der untenstehenden Tabelle vorkommt. Innerhalb des Quote- oder Insert-Modus (erster wird eingeschaltet, wenn Sie ein Anführungszeichen eingeben, letzter, wenn Sie drücken) reagiert die Erweiterung nicht. Nach Reset oder schalten Sie 64 Keys, so es sich noch im Speicher befindet, mit SYS 49152 wieder ein. Im einzelnen werden folgende Schlüsselwörter wiedergegeben, wenn Sie die angegebene Taste mit drücken: A ASC | B STEP | C CHR$ D DIM | E END | F FOR G GET | H STOP | I INPUT J GOTO | K GOSUB | L LEFT$ M MID$ | N NEXT | O OPEN P POKE | Q PEEK | R RIGHT$ S STR$ | T TAB( | U USR V VAL | X READ | W WAIT Y RESTORE | Z SYS | = LIST . STEP | , THEN | ? PRINT <- DATA | * REM | - NEW + RUN | ^ CONT | £ VERIFY : RND | ; FRE | f1 INT f3 ABS | f5 SGN | f7 LEN RETURN RETURN | CLR CLR | CRSR left SAVE CRSR down LOAD | INST IF | Klammeraffe CLOSE Es sind also alle Tasten des C 64 belegt, natürlich mit Ausnahme der RESTORE-Taste, der Steuertasten , und und der Zifferntasten, da diese mit die Farbumschaltung erledigen. Kurz noch zur Funktionsweise: Da 64 Keys nicht den IRQ-Vektor verbiegt, ist die Erweiterung sehr kompatibel zu sonstigen Zusatzprogrammen, die nicht den Bereich von 49152 bis 49448 belegen. Hier wird vielmehr der Key-Vektor (655/656) auf eine eigene Routine verbogen. Viel Spaß mit 64 Keys. Genießen Sie den Komfort, den dieses sehr kurze Utility Ihnen bietet! Anleitung zu »Array of Byte« Vor allem Pascal-gewohnte Programmierer kennen die Array-of-Byte-Funktion, mit der sich der gesamte Speicher des Computers wie eine indizierte Variable ansprechen läßt. Unsere kleine Erweiterung bringt auch dem C 64 diese nützlichen Befehle bei. Endlich wird PEEK und POKE überflüssig! Die Erweiterung »Array of Byte« ist vor allem für Programmierer nützlich, die ihre Programme übersichtlicher und leichter verständlich schreiben möchten. Fand sich bisher in fast jedem längeren Basicprogramm ein Wust aus PEEK- und POKE-Befehlen, um bestimmte Spezialeffekte durch direkte Speichermanipulation zu erreichen, kann man mit der hier vorgestellten Erweiterung alle 65536 Speicherzellen, die der 64'er bietet, wie eine riesige indizierte Variable ansprechen (indizierte Variablen sind Variablen mit einem Parameter in Klammern hinter dem Variablennamen). Dieser Vorzug war bisher verschiedenen Pascal-Systemen vorbehalten. Obwohl die Erweiterung aus Komfort- und Geschwindigkeitsgründen vollständig in Maschinensprache geschrieben werden, kann sie dank des Ladeprogramms wie ganz normales Basic geladen und gestartet werden: LOAD "ARRAY OF BYTE",8 RUN Nach kurzer Zeit erscheint eine knappe Anleitung auf dem Bildschirm. Jetzt stehen ein neues Schlüsselwort zur Verfügung: MEM (xxx). Dabei gibt xxx (ganzzahlig mit 0 <= xxx < 65536) die Nummer der anzusprechenden Speicherzelle an. Dieser Ausdruck kann wie normale Arrays in Befehlen verwendet werden und als Parameter in Termen stehen, beispielsweise so: MEM (53280) = 0 wirkt wie POKE 53280,0 PRINT MEM (144) wirkt wie PRINT PEEK (144) MEM (53269) = MEM (53269) OR 16 (schaltet Sprite 4 an) IF MEM (808) <> 237 THEN GOTO 900 und so weiter. Es gibt nur zwei Einschränkungen. Hinter LET darf MEM nicht für die Zuweisung verwendet werden. LET MEM (53280) = 1 ist verboten, LET A = MEM (700) ist jedoch erlaubt. Außerdem sollte nach THEN ein Doppelpunkt folgen, falls der neue MEM-Befehl zuweisend direkt dahinter steht. Also nicht IF A = 400 THEN MEM (400) = 60 sondern IF A = 400 THEN : MEM (400) = 60 Diese beiden Einschränkungen haben programmtechnische Gründe und wiegen in der Praxis nicht schwer. Außerdem darf einer Speicherzelle MEM natürlich nur ein ganzzahliger Wert von 0 bis 255 zugewiesen werden. Die Verwendung der Variablen MEM oder ME (...) in Basicprogramme als normales Array ist verständlicherweise bei aktiviertem Array of Byte nicht möglich. Es sollte noch angemerkt werden, daß Sie vor dem Start eines (fertigen) Basicprogramms mit den neuen Befehlen erst die Erweiterung »Array of Byte« wie beschrieben laden und starten müssen. Anleitung zur INFORM-Routine: Komfortable Eingabe Der INPUT-Befehl des C 64 hat einige entscheidende Nachteile: Mit den Cursortasten etwa kann ohne weiteres die Bildschirmmaske zerstört werden. Leider ist es auch nicht möglich, eine maximale Eingabelänge vorzugeben oder Sonderzeichen wie Kommas, Doppelpunkte oder dergleichen mehr einzugeben. Manchmal benötigt man INPUT im Direktmodus, aber es geht nicht! INFORM ist eine 143 Bytes kurze Ersatzroutine, die alle Nachteile beseitigt. Im Gegensatz zu anderen einschlägigen Lösungen dieser Art wird die Eingabe nicht einfach im Speicher abgelegt, sondern wie bei INPUT einer Basic-Variablen zugewiesen. Das Programm wird mit LOAD "INFORM 49152",8,8 geladen. Danach soll NEW eingegeben werden (entfällt, falls INFORM in einem eigenen Programm nachgeladen wird). Jetzt können Sie, sogar im Direktmodus, die Routine mit SYS 49152, LEN, VAR$ aufrufen. LEN gibt an, wie viele Zeichen die Eingabe maximal umfassen darf. Setzen Sie LEN auf Null, können nur Leerstrings eingegeben werden. LEN muß kleiner als 256 (ein Byte) sein. Für LEN können Sie Ziffern einsetzen, aber auch numerische Terme aus Variablen und Rechenzeichen. VAR$ ist die Stringvariable, der die Eingabe zugeteilt werden soll. Einige Beispiele für erlaubte Befehle: SYS 49152, 2, A$ SYS 49152, 56-15, TZ$ SYS 49152, LEN(A$), A$ SYS 49152, PEEK(90)-DD/2, DM$ und so weiter. Bei INFORM können Korrekturen am eingegebenen Text nur mit der DEL-Taste vorgenommen werden, die das zuletzt eingegebene Zeichen löscht. Alle Cursortasten sind gesperrt. Mit schließen Sie die Eingabe ab. Eine kleine Schwäche: Mit INFORM kann pro Wurf immer nur eine Variable definiert werden (die übrigens, wie sich das für eine ordentliche INPUT-Alternative gehört, angelegt wird, falls sie vorher noch nicht definiert war). Mehrfacheingaben wie bei INPUT "NAME, ALTER"; NA$,AL sind nicht möglich. Dieser Nachteil ist die »Schattenseite« des Vorteils, daß jetzt auch Doppelpunkte, Kommas und Anführungszeichen in der Eingabe enthalten sein dürfen. Interessant an dieser Routine ist vor allem der Teil ab $c02d, der die Eingabe aus dem Kassettenpuffer liest und in der Stringvariable speichert. Es handelt sich um eine kürzere, einfachere und sicherere Alternative zu der von der 64'er Redaktion in 64'er 9/90 Seite 56 im Leserforum vorgestellten Möglichkeit. Falls Sie das Programm verändern oder in eigene Projekte einbauen wollen, müssen Sie nur beachten, daß die Adresse, an der der JSR SUCHVAR-Befehl (momentan an $c008) beginnt, nicht das Lowbyte $28 (dez. 40) hat (siehe C 64-Betriebssystem ab $b11d und $af28). Dieses Problem tritt in der Praxis jedoch kaum auf und hat keine Bedeutung für reine Anwender von INFORM, es soll hier nur der Vollständigkeit halber erwähnt werden. Dem fortgeschrittenen Leser wird es sicher nicht schwerfallen, INFORM in eigene Programme oder Erweiterungen einzubinden. Eine Hilfe mag der ausführlich kommentierte Quelltext sein. Die Telefonbuchsuche: »GENIE-SUCH« Eine spezielle Maschinensprache-Routine, die in einem String-Array blitzschnell beliebige Texte findet. Das Besondere: Es erfolgt kein einfacher 1:1 Vergleich, sondern die Routine drückt auf Wunsch ein »Auge zu«, wenn der Suchstring nur fast, nicht aber exakt gefunden wird. Nebenbei erhalten Sie auch eine blitzschnelle Suchroutine, die stundenlange Basic-Schleifen endgültig überflüssig macht. Nehmen wir einmal an, Sie wollen ein Telefonbuch-Programm schreiben. Dazu würden Sie in je einem Variablen-Array (indizierte Variable) die Namen der Personen und die Telefonnummern speichern. Jetzt wird der Name vom Anwender eingegeben, und eine Suchroutine tritt in Aktion, die jedes Element des Namensfeldes mit der Eingabe vergleicht. Bei Übereinstimmung wird die entsprechende Telefonnummer ausgegeben, sonst eine Fehlermeldung. Wenn Sie jedoch zum Beispiel statt des gespeicherten »MEIER« auf der Tastatur »MAIER« eingeben, muß das Programm passen. Um es etwas bedienerfreundlicher zu gestalten, wäre eine Suchroutine praktisch, die kleine Tippfehler oder Ungenauigkeiten im Suchstring automatisch korrigiert. Eine solche Routine ist die hier vorgestellte Routine »GENIE-SUCH«. Sie heißt so, weil sie bei der Suche nach einem genialen System vorgeht, um auch Tippfehler wie »Dreher« (»HBUER« statt »HUBER«), falsche Buchstaben (»HUPER« statt »HUBER«), Vertauschungen in der Groß/Kleinschrift oder zu lange und zu kurze Suchbegriffe (etwa »HUBR« oder »HUBAER« statt »HUBER«) erkennt. Da sie vollkommen in Maschinensprache geschrieben wurde, arbeitet sie recht schnell. Zudem ist sie nur wenige Bytes (drei Blocks) lang. Laden Sie die Routine mit dem Befehl LOAD "GENIE-SUCH",8,8 von Diskette in den Speicher. Geschieht dies im Direktmodus, sollte danach NEW eingegeben werden, um alle Zeiger wieder richtigzustellen. Die Routine kann und soll aber auch von Basicprogrammen aus nachgeladen werden, etwa so: 1 IFA=0THENA=1:LOAD"GENIE-SUCH",8,8 Jetzt kann das Utility mit dem Befehl SYS 49152,SU$,MODE,FE$(ANF),FE$(END),FI% gestartet werden. Dabei haben die Parameter folgende Bedeutung: SU$ ist der nicht leere String, der den Suchtext enthält. Es kann sich um eine Variable, einen Text in Anführungszeichen oder einen Stringausdruck handeln. MODE gibt die Betriebsart an, eine Zahl oder Variable oder ein Term mit einem Wert zwischen 0 und 255 nach untenstehender Tabelle. FE$(...) ist die Arrayvariable, in der gesucht werden soll. Es soll sich um ein eindimensionales Stringfeld handeln. ANF ist die erste Indexnummer, END die letzte Indexnummer. Diese beiden Parameter können auch größer als 255 sein, sie geben den Bereich im Array an, der durchsucht werden soll. ANF sollte nicht Null sein, da die Routine die Nummer des Feldes zurückmeldet, in der der Begriff gefunden wurde. Wird eine Null zurückgegeben, bedeutet dies, daß nichts gefunden wurde. Das Unterprogramm gibt aber auch dann eine Null zurück, wenn der Begriff im Feld Nummer Null gefunden wurde. Da in diesem Fall das steuernde Basicprogramm beide Fälle nicht unterscheiden kann, sollte die Null als Parameter hier vermieden werden. END darf nicht kleiner als ANF und nicht größer als die Anzahl der Elemente in FE$(...) sein. FI% schließlich muß eine Integer-Variable sein, in der die Nummer des Feldes zurückgemeldet wird, in dem der Suchbegriff gefunden wurde. Wird FI% Null, wurde nichts gefunden. Für MODE gibt es 256 Möglichkeiten, die durch Addition der folgenden Optionen entstehen: 1 = Suche falsche Zeichen (»HABER« statt »HUBER«) 2 = Keine Berücksichtigung Groß/Kleinbuchstaben 4 = »Dreher« finden (»HUBRE« statt »HUBER«) 8 = Das Fragezeichen ist als Joker zugelassen 16 = Das erste Zeichen MUSS übereinstimmen 32 = Leerzeichen ignorieren 64 = überflüssige Zeichen ignorieren (»HUBBER« statt »HUBER«) 128 = fehlende Zeichen ignorieren (»HUER« statt »HUBER«) Diese Werte können direkt für MODE eingesetzt werden. Ist MODE=0, wird nur dann ein Fund gemeldet, wenn der Suchbegriff wirklich 1:1 mit dem Feld übereinstimmt (alle Optionen abgeschaltet). Soll zum Beispiel die Suche nach falschen Zeichen (Option 1) und die Suche nach Drehern (Option 4) erlaubt sein, so addieren Sie 1 und 4 und setzen somit die 5 als MODE ein. Sind alle Optionen eingeschaltet, wird MODE=255. Beachten Sie jedoch, daß die Routine intern immer nur maximal eine Option pro Feld zuläßt. Ist der Suchbegriff etwa »PEULAENR«, und enthält ein Feld den Inhalt »PAULANER« (Fehler: ein falsches Zeichen und ein Dreher), so wird dieses Feld nicht gefunden, auch wenn Sie die beiden Optionen gleichzeitig erlaubt haben. Diese Einschränkung ist programmbedingt und mußte getroffen werden, um die Routine nicht unnötig komplex, umständlich und damit langsam werden zu lassen. Ausnahme: Die Optionen Leerzeichen ignorieren, Groß/Kleinschrift ignorieren, Fragezeichen als Joker können zusammen mit anderen Optionen verwendet werden. Erklärung der Option 8: Das Fragezeichen kann als »Joker« verwendet werden, wenn Sie einzelne Zeichen des Suchbegriffes nicht wissen. Die Anwendung entspricht der des Fragezeichens beim Befehlskanal der Floppy: Geben Sie als Suchbegriff »PE?ER« vor, findet der Computer ein Feld mit dem Inhalt »PETER«, allerdings nur, wenn Sie die Option 8 zulassen. Ein Anwendungsbeispiel: Das Feld A$(1) bis A$(15) enthält einige Vornamen. Sie wollen prüfen, in welchem Feld der »PETER« enthalten ist. Als Optionen lassen Sie zu: falsche Zeichen, Dreher, Vertauschung Groß/Kleinschrift, Leerzeichen ignorieren, Fragezeichen als Joker. Die Addition der Optionen ergibt MODE=47. Das Ergebnis soll in F% vermerkt werden. Der Befehl lautet: SYS 49152,"PETER",47,A$(1),A$(15),F% Wird nach diesem Befehl F%=5, so ist »PETER« in A$(5) enthalten. Ist F%=0, so ist »PETER« in A$(1) bis A$(15) nicht enthalten (aber vielleicht zum Beispiel in A$(16)). Zur praktischen Anwendung: Eine sinnvolle Vorgehensweise wird sein, die Suchroutine erst einmal ohne alle Optionen durchlaufen zu lassen, um bei korrekter Eingabe auch wirklich nur das gewünschte Element zu finden. Blieb die Suche erfolglos, können Sie nun nacheinander einige SYS 49152-Aufrufe verwenden und dabei nacheinander die zur Verfügung stehenden Optionen einschalten. Wir wünschen Ihnen viel Spaß mit dieser Routine, die Ihnen sicher helfen wird, Ihre Datenverwaltungsprogramme und andere Projekte komfortabler zu gestalten. Das Demoprogramm gibt noch ein weiteres Anwendungsbeispiel. KAPITEL 2: ASSEMBLERPROGRAMMIERUNG Dateibearbeitung in Maschinensprache Man braucht keinen Generalschlüssel, um in Assembler Files zu öffnen, zu schließen, zu lesen und zu beschreiben. Es sind nur ein paar kleine Programmiertricks, die im Prinzip ganz ähnlich wie in Basic funktionieren. Unser kleiner Kurs für fortgeschrittene Assemblerprogrammierer führt Sie in die Dateibearbeitung direkt vom Prozessor aus. Sie haben gerade Ihre ersten Schritte in der Welt der Maschinensprache hinter sich, wissen, wie man in Assembler Programme eingibt und startet, und sind nun daran interessiert, in größeren Programmen auch Arbeiten wie das Laden und Speichern von Dateien, Anzeigen des Directories, Fehlerkanal auslesen und so weiter direkt in Assembler zu programmieren. Dann sind Sie hier genau richtig. Ausgehend davon, wie man solche Dinge in Basic programmiert, werden wir uns mit Hilfe der Betriebssystem-Routinen langsam an Files in Maschinensprache herantasten. In bewährter Manier stellen wir dabei erst die Programmlistings vor, und kommentieren sie dann ausführlich. Den Abschluß bietet ein Programm, das den Inhalt einer beliebigen Datei auf dem Drucker wiedergibt. Übrigens funktionieren die hier vorgestellten Verfahren keineswegs nur auf dem C 64. Sie sind, soweit nur Kernal-Routinen mit der Startadresse $FFxx verwendet werden, ohne Änderung auf allen Commodore-Homecomputern lauffähig, insbesondere C 128, VC 20, C 16 und möglicherweise sogar auf dem Amiga. Allerdings kann es notwendig sein, die Startadresse der Beispielprogramm anzupassen. In diesem Artikel wurde einheitlich 49152 gewählt, da sich dieser Speicherbereich beim C 64 anbietet. Ohne Änderungen sind alle hier vorgestellten Programmlösungen auf dem C 64 lauffähig. Öffnen und Schließen von Files Wie Sie das von Basic gewohnt sind, müssen wir auch in Maschinensprache dem Computer genau mitteilen, auf welche Datei zugegriffen werden soll. Als Beispiel wählen wir eine auf Diskette gespeicherte sequentielle Datei mit dem Namen »TEST«. In Basic können wir so ein File ganz einfach zum Lesen öffnen: OPEN 1,8,2,"TEST,S,R" Die erste Zahl, 1, gibt die logische Filenummer an. Wir brauchen sie, damit wir uns später auf diesen OPEN-Befehl beziehen können. Die 8 gibt die Gerätenummer an, sie steht für das Diskettenlaufwerk. 2 ist eine Sekundäradresse, die der Floppy die Betriebsdaten mitteilt. Dahinter steht in Stringform erst der Dateiname, dann durch Kommas getrennt ein S für SEQ-Datei und ein R für READ (Lesen aus dem File). Ganz so einfach geht's in Maschinensprache nicht. Den OPEN-Befehl müssen wir in drei Prozeduren zerlegen. Dabei begegnen uns allerdings exakt die selben Angaben wie bei Basic. Zunächst brauchen wir drei wichtige Betriebssystem-Routinen: SETPAR $FFBA SETNAM $FFBD OPEN $FFC0 Die SETPAR-Routine, die im System bereits fest ab Adresse $FFBA gespeichert ist, definiert die File- und die Gerätenummer sowie die Sekundäradresse. Diese Angaben sind im Akku, X- und Y-Register zu übergeben. Der Filename muß im Ascii-Code irgendwo im Speicher abgelegt werden. Dazu übergeben wir der SETNAM-Routine im Akku die Länge des Namens und in den Registern X und Y einen Zeiger (Low/Highbyte) auf die Adresse. Soll kein Dateiname gesetzt werden (ist ja auch in Basic bei OPEN nicht notwendig), übergeben wir als »Länge« im Akku die Null. Erst nach diesen Vorbereitungen darf die OPEN-Routine aufgerufen werden, die das File tatsächlich öffnet. Formulieren wir einmal den obigen OPEN-Befehl in Assembler. Die Funktionsweise der kurzen Routine ist dabei eher unwichtig, begreifen Sie den Ausschnitt einfach als »Kochrezept«: * = 49152 ; Startadresse LDA #1 ; Filenummer LDX #8 ; Gerätenummer LDY #2 ; Sekundäradresse JSR $FFBA ; SETPAR LDA #8 ; Länge des Filenamens LDX #NAME; des Filenamens JSR $FFBD ; SETNAM JSR $FFC0 ; OPEN Datei öffnen Es ist also ganz einfach. Diese wenigen Zeilen haben exakt die gleiche Wirkung wie der oben vorgestellte OPEN-Befehl. Nur eines fehlt noch: Der Dateiname, den wir an einer freien Stelle im Speicher im Ascii-Code ablegen müssen: NAME .ASC "TEST,S,R" Das zweite, was jeder Basicprogrammierer im Zusammenhang mit Files lernt, ist, daß man jede geöffnete Datei wieder schließen muß, wenn man sie nicht mehr braucht. Das ist so, als ob Sie Ihren Computer einschalten (OPEN), dann damit arbeiten und ihn nach Beendigung der Session wieder abschalten (CLOSE). Nur, daß Sie mit mehreren Computern gleichzeitig arbeiten können: Es können viele Dateien gleichzeitig geöffnet sein. Auf welche Sie sich momentan beziehen, wird durch die Filenummer (in unserem Beispiel 1) eindeutig bestimmt. In Basic schließen wir die oben geöffnete Datei einfach mit CLOSE 1 Das geht in Maschinensprache fast genauso einfach: Die entsprechende CLOSE-Routine erwartet im Akku die Filenummer und hat die Adresse $FFC3. Unser CLOSE 1 sieht also in Assembler so aus: LDA #1 ; Dateinummer JSR $FFC3 ; CLOSE Datei schließen Das ist wirklich alles! Bemerkenswert ist, daß wir hier ebenso wie in Basic keine weiteren Angaben brauchen - die hat ja bereits alle der OPEN-Befehl bekommen. Lesen aus der Datei Nachdem wir das File geöffnet haben, wollen wir nun daraus lesen. In Assembler muß dazu zunächst ein Eingabekanal geöffnet werden, das heißt, wir müssen dem Computer sagen, daß wir die Datei, die vorher geöffnet wurde, nun lesen wollen. Dazu gibt es die CHKIN-Routine mit der Adresse $FFC6. Diesem Unterprogramm wird im X-Register (!) die Filenummer der vorher geöffneten Datei übergeben, aus der gelesen werden soll. In unserem Beispiel sieht das so aus: LDX #1 ; Dateinummer 1 JSR $FFC6 ; CHKIN Eingabekanal öffnen Ab jetzt kann man aus dieser Datei lesen. Dazu stehen im Prinzip vor allem zwei Routinen zur Verfügung: GETIN $FFE4 CHRIN $FFCF Die CHRIN-Routine entspricht in etwa dem INPUT# in Basic. Sie merken schon: In Basic muß hinter INPUT# noch die Filenummer angegeben werden. Das kann hier entfallen, da wir ja schon mit CHKIN festgelegt haben, auf welches File Bezug genommen wird. Die GETIN-Routine entspricht dem GET#-Befehl von Basic und ist CHRIN grundsätzlich vorzuziehen. Bitte begnügen Sie sich mit der Ausrede, GET in Basic ist ja auch sicherer als INPUT. Eine etwas detailliertere Erklärung folgt am Ende des Artikels. Die Anwendung von GETIN ist denkbar einfach: Einfach mit JSR $FFE4 aufrufen. Im Akku wird dann der Ascii-Code des gelesenen Zeichens übergeben. Auf ein Beispiel verzichten wir, da in Kürze das erste »richtige« Programm folgt. Ebenso wie geöffnete Dateien wieder geschlossen werden, müssen auch die Eingabekanäle (später werden wir noch Ausgabekanäle kennenlernen) geschlossen werden, da sonst beispielsweise keine Eingabe von Tastatur mehr möglich ist. Unser C 64 kennt dazu die Routine CLRCHN mit der Adresse $FFCC. Rufen Sie diese Adresse auf, wird die Eingabe wieder auf die Tastatur und (falls verändert) die Ausgabe wieder auf den Bildschirm »umgelenkt« (man sollte besser sagen: »zurückgelenkt«). Zur Sicherheit sollte man außerdem zu Beginn jedes Maschinenprogramms den CLALL-Befehl (Adresse $FFE7) anwenden. Er bewirkt, daß alle offnene Dateien und Kanäle geschlossen werden. CLALL beinhaltet also CLRCHN. Der Vollständigkeit halber sei noch die wohl wichtigste Betriebssystem-Routine erwähnt, die es gibt: CHROUT (oft auch PRINT oder BSOUT genannt) mit der Adresse $FFD2. Diese gibt einfach das Zeichen, dessen Codenummer im Akku steht, auf dem Bildschirm oder dem Gerät aus, das momentan Ausgabegerät ist. Wie man ein anderes Ausgabegerät als den Schirm definiert (funktioniert ähnlich wie oben bei CHKIN gesehen), lernen Sie später. Fehlerkanal auslesen Mit dem bisher errungenen Wissen können wir schon unser erstes Programm schreiben. Es soll den Fehlerkanal der Diskettenstation auslesen und am Bildschirm anzeigen. Dazu erst das entsprechende Analogon in Basic: 10 OPEN 15,8,15:REM KEIN DATEINAME 20 GET# 15,A$ 30 PRINT A$; 40 IF A$ <> CHR$(13) THEN 20 50 CLOSE 15 60 END In Zeile 40 erfolgt eine Prüfung, ob das gelesene Zeichen ein CR (Code 13) war. In diesem Fall ist die Statusmeldung vollständig gelesen. Dieses Programm setzen wir 1:1 in Maschinensprache um. ; Beispiel 1: Fehlerkanal 49152 JSR $FFE7; CLALL zur Sicherheit 49155 LDA #15 ; Filenummer 49157 LDX #8 ; Floppy 49159 TAY ; Sekundäradresse 49160 JSR $FFBA; SETPAR 49163 LDA #0 ; kein Dateiname 49165 JSR $FFBD; SETNAM 49168 JSR $FFC0; OPEN 15,8,15,"" 49171 LDX #15 ; File 15 49173 JSR $FFC6; CHKIN zur Eingabe öffnen 49176 JSR $FFE4; GETIN ein Zeichen lesen 49179 JSR $FFD2; auf Bildschirm ausgeben 49182 CMP #13 ; Code 13? 49184 BNE 49176; nein, dann weiter 49186 JSR $FFCC; sonst Kanal schließen 49189 LDA #15 ; Dateinummer 49191 JMP $FFC3; CLOSE 15 Das war auch schon alles. Wenn Sie dieses Programm mit dem Monitor oder Assembler eingegeben und ggf. assembliert haben, starten Sie es mit SYS 49152 Sofort erscheint der Fehlerkanal, im Normalfall 00,OK,00,00. Senden Sie einfach einmal einen fehlerhaften Befehl, etwa OPEN 1,8,15,"X":CLOSE 1 Nach SYS 49152 beschwert sich das Laufwerk mit einem 31,SYNTAX ERROR,00,00. Was bleibt ihm auch anderes übrig: Den X-Befehl gibt es nicht. Übrigens sollten Sie zur Probe im Maschinenprogramm einmal an Adresse 49189 ein RTS einbauen (POKE 49189,96) und damit den CLOSE-Befehl unwirksam machen. Der Aufruf mit SYS 49152 klappt einwandfrei, allerdings ist die Datei 15 noch offen. Das können Sie leicht nachprüfen, indem Sie jetzt von Basic aus eingeben OPEN 15,8,15 Der Computer reagiert artig mit seinem ?FILE OPEN ERROR. In Maschinensprache haben wir es also offenbar mit exakt den gleichen Files zu tun wie in Basic. Das erleichtert die Sache erheblich. Directory ohne Datenverlust Kaum ein größeres Programm kommt ohne eine Routine aus, die das Inhaltsverzeichnis der Diskette lädt und listet. In Basic bietet sich dazu folgende Befehlsfolge an: LOAD "$",8 LIST die jedoch einen fatalen Nebeneffekt hat: Da das Directory wie ein Basicprogramm geladen wird, geht das momentan im Speicher stehende Programm rettungslos verloren. Versuchen wir daher, eine kurze Maschinenroutine zu programmierern, die das gleiche ohne Datenverlust erledigt. Wir lesen Zeichen für Zeichen der Directory und zeigen alles gleich an. Die hier vorgestellte Routine ist nicht optimiert in Bezug auf Kürze und Geschwindigkeit, aber es wird Ihnen mit etwas Einfühlungsvermögen leichtfallen, die Funktionsweise zu verstehen und das Programm vielleicht noch zu erweitern oder zu kürzen. Zunächst öffnen wir in gewohnter Manier das »File«, in dem sich die Directory verbirgt. Aus technischen Gründen braucht man dazu die Sekundäradresse 0. ; Beispiel 2: Directory 49152 JSR $FFE7; CLALL zur Sicherheit 49155 LDA #1 ; Filenummer 49157 LDX #8 ; Geräteadresse 49159 LDY #0 ; Sekundäradresse 49161 JSR $FFBA; SETPAR 49164 LDX #$24 ; Code für Dollarzeichen 49166 STX 2 ; in freier Speicherzelle speichern 49168 LDX #2 ; Adresse low 49170 LDY #0 ; und high 49172 JSR $FFBD; SETNAM 49175 JSR $FFC0; OPEN 1,8,0,"$" 49178 LDX #1 ; Filenummer 49180 JSR $FFC6; CHKIN Eingabekanal öffnen Da ja der Filename irgendwo im Speicher abgelegt werden muß, entscheiden wir uns für die sonst unbenutzte Speicherzelle 2. Ab 49168 richten wir den Zeiger X/Y auf diese Adresse. Sie wundern sich vielleicht, warum wir vor SETPAR nicht die Länge des Namens (1) im Akku gespeichert haben. Das ist hier nicht mehr nötig, da die 1 im Akkumulator von 49155 noch enthalten ist. Ein kleiner Trick also, den sich der Autor einfach nicht verkneifen konnte. Jetzt können wir mit GETIN Zeichen für Zeichen lesen und ausgeben. Beim Directory gibt es allerdings einige Besonderheiten zu beachten. Die ersten beiden Bytes einer jeden Zeile können ignoriert werden, die nächsten beiden Bytes geben im Format Low/Highbyte die Größe in Blocks an. Danach folgt bis zum Nullbyte die Zeileninformation. Außerdem muß getestet werden, ob das Dateiende erreicht wurde. Wie in Basic lesen wir dazu den Wert der Variablen ST aus, auf den der Maschinenprogrammierer durch Auslesen der Speicherzelle 144 (C 64, C 128 und andere) Zugriff hat. Hat diese Speicherzelle einen Inhalt ungleich Null, so ist ein Fehler aufgetreten oder das File ist beendet. Zuletzt brauchen wir eine Routine, die eine 16-Bit Integerzahl (Low/Highbyte) numerisch auf dem Bildschirm ausgibt. So etwas enthält der C 64 an Adresse $BDCD, diese Routine AXOUT wird sonst vom System zur Ausgabe von Basic-Programmzeilennummern verwendet. Sie gibt eine Zahl aus, die sich nach der Formel WERT = X + A * 256 errechnet. High- und Lowbyte wird also im Akku und im X-Register übergeben. 49183 LDY #3 ; drei Bytes überlesen 49185 STY 3 ; als Zähler merken 49187 JSR $FFE4; GETIN Zeichen lesen 49190 STA 4 ; und merken 49192 LDY 144 ; ST Status lesen 49194 BNE 49239; ungleich Null, fertig 49196 JSR $FFE4; GETIN 49199 LDY 144 ; ST lesen 49201 BNE 49239; bei Dateiende 49203 LDY 3 ; Zähler zurückholen 49205 DEY ; und erniedrigen 49206 BNE 49185; nicht null, weitermachen 49208 LDX 4 ; Zeichen restaurieren 49210 JSR $BDCD; AXOUT Zahl ausgeben 49213 JSR $AB3F; SPACE Leerzeichen ausgeben 49216 JSR $FFE4; GETIN 49219 LDX 144 ; Status testen 49221 BNE 49239; bei ungleich Null beenden 49223 TAX ; Zeichencode 49224 BEQ 49232; bei Zeilenende 49226 JSR $FFD2; BSOUT Zeichen ausgeben 49229 JMP 49216; und weiter listen 49232 JSR $AAD7; CRLF Zeilenende ausgeben 49235 LDY #2 ; zwei Bytes für Linkpointer 49237 BNE 49185; und nächste Zeile 49239 JSR $FFCC; CLRCHN Kanal schließen 49242 LDA #1 ; Datei 1 49244 JMP $FFC3; schließen, fertig Besitzer anderer Computer als der C 64 müssen die Befehle JSR $AAD7 (beginnt neue Zeile) und JSR $AB3F (gibt ein Leerzeichen aus) evtl. durch Ersatzkonstruktionen ersetzen. JSR $AB3F hat die gleiche Wirkung wie LDA #32 und JSR $FFD2. Außerdem müssen Sie mit Hilfe eines ROM-Listings die AXOUT-Routine, die beim C 64 an $BDCD beginnt suchen, oder auf die Ausgabe der Blocklänge verzichten. Probieren Sie dieses Programm gleich einmal aus! Wenn alles geklappt hat, sollten Sie zur Übung einmal versuchen, beispielsweise eine Funktion einzubauen, die das Directory auf Tastendruck anhält und/oder abbricht. Druckerausgabe Nachdem wir gelernt haben, wie man in Maschinensprache Eingaben von Files vornimmt, beschäftigen wir uns jetzt mit der Ausgabe in eine Datei. Als erstes Beispiel mag eine Druckerausgabe dienen. Wenn Sie das bisher beschriebene verstanden haben, wird es Ihnen nicht schwerfallen, auch mit dem folgenden zurechtzukommen. Im Prinzip geht es wieder wie gehabt, nur daß wir diesmal nach dem Öffnen des eigentlichen Files keinen Eingabekanal, sondern einen Ausgabekanal öffnen werden. Dazu dient die Routine CHKOUT (Adresse $FFC9), die analog zu CHKIN funktioniert. Auch hier muß im X-Register die Filenummer übergeben werden. CHKOUT leitet dann bis zum abschließenden CLRCHN alle Ausgaben auf das betreffende Gerät um. Das funktioniert genauso wie der CMD-Befehl, den Sie vielleicht vom Basic her kennen. Und in der Tat ruft auch Basics CMD intern einfach nur die CHKOUT-Routine auf! Es soll der Text »ICH GRUESSE DIE WELT!« auf dem Drucker ausgegeben werden. Sehen wir uns wieder zunächst die Basic-Lösung an: 10 OPEN 4,4 30 PRINT#4,"ICH GRUESSE DIE WELT!" 50 CLOSE 4 Die Zeilen 20 und 40 wurden bewußt weggelassen. Damit die Umsetzung in Assembler leichter zu verstehen ist, bauen wir das Basicprogramm etwas um und verwenden den CMD-Befehl. Dieser ergibt die noch fehlende Zeile 20. Bekanntlich muß ein CMD-Befehl mit einem PRINT#-Befehl aufgehoben werden, den wir in Zeile 40 unterbringen. 10 OPEN 4,4 20 CMD 4 30 PRINT"ICH GRUESSE DIE WELT!" 40 PRINT#4 50 CLOSE 4 Das Bemerkenswerte dabei ist, daß wir zur Druckerausgabe den normalen PRINT-Befehl (ohne Doppelkreuz) verwenden dürfen, da ja zuvor mit CMD schon der entsprechende Kanal freigegeben wurde. In Maschinensprache können wir uns die Zeile 40 sparen, wir haben zum Schließen des Kanals ja die CLRCHN-Routine zur Verfügung, die übrigens auch dem Basic-Programmierer mit SYS 65484 (hier etwa in Zeile 40) zur Verfügung steht. Jetzt stellt die Umsetzung kein Problem mehr dar. Merken Sie sich bitte, daß beim Öffnen eines Druckerfiles grundsätzlich kein Filename angegeben wird. Eventuell kann es notwendig sein, eine andere Sekundäradresse als die Null anzugeben, das hängt von Ihrem Interface ab. Ändern Sie bei Bedarf einfach den Befehl ab Adresse 49158. ; Beispiel 3: Druckerausgabe 49152 JSR $FFE7; CLALL zur Sicherheit 49155 LDA #4 ; Filenummer 49157 TAX ; istgleich Gerätenummer 49158 LDY #0 ; Sekundäradresse 49160 JSR $FFBA; SETPAR 49163 LDA #0 ; Länge des Filenamens = 0 49165 JSR $FFBD; SETNAM 49168 JSR $FFC0; OPEN 4,4,0,"" 49171 LDX #4 ; Filenummer 49173 JSR $FFC9; CHKOUT Drucker als Ausgabegerät Jetzt ist die eigentliche Ausgabe des Textes dran. Wir verwenden dazu, damit es leichter verständlich wird, eine Schleife, in der wir Zeichen für Zeichen des im Ascii-Code abgelegten Textes über CHROUT ($FFD2) ausgeben. Im Gegensatz zu Basic wird hier bei der Ausgabe nicht automatisch das Zeilenendezeichen CR (CHR$(13)) angefügt, das müssen wir von Hand erledigen. Wird das vergessen, druckt das Gerät nichts. Der Text hat insgesamt also 22 Zeichen. 49176 LDX #0 ; Zähler initialisieren 49178 LDA 49197,X ; Text lesen 49181 JSR $FFD2 ; und Zeichen ausgeben 49184 INX ; nächstes Zeichen 49185 CPX #22 ; schon 22 Zeichen? 49187 BNE 49178 ; nein, weiter lesen 49189 JSR $FFCC ; CLRCHN Ausgabe beenden 49192 LDA #4 ; File 4 49194 JMP $FFC3 ; CLOSE 4 49197 .ASC "ICH GRUESSE DIE WELT!" 49218 .BYT 13 ; CR Je nachdem, welchen Assembler oder Monitor Sie verwenden, kann es notwendig sein, die Pseudo-Befehle in 49197 und 49218 zu ändern. Es soll einfach der Text ab 49197 im Ascii-Code abgelegt und eine 13 in Speicherzelle 49218 gelegt werden: POKE 49218,13. Jetzt sollten Sie den Drucker einschalten und bereitmachen. Mit SYS 49152 kann dann der Ausdruck gestartet werden. Wenn alles richtig gelaufen ist, wird das Gerät schön brav den Text zu Papier bringen. Beschreiben eines Disketten-Files Jetzt wollen wir aber auch versuchen, in ein File zu schreiben. Dazu werden wir eine neue Routine des C 64 kennenlernen, die uns die Arbeit des Aufrufs von SETPAR und SETNAM abnimmt. Man kann vielmehr direkt hinter dem SYS-Befehl Filenamen und Gerätenummer angeben. Diese Routine GETPAR (Adresse beim C 64: $E1D4) wird normalerweise von den LOAD- und SAVE-Befehlen verwendet, um die Parameter zu ermitteln. Wir wollen ein kurzes Programm schreiben, mit dem eine sequentielle Datei angelegt werden kann. Kurz zu den »Spielregeln«: Das Programm wird mit SYS 49152,"DATEINAME,S,W",8 gestartet. Daraufhin erscheint ein Cursor, und die einzelnen Datensätze werden durch Komma getrennt eingegeben. Das Ende markiert ein Stern, der sonst nicht eingegeben werden darf - der Einfachheit halber. Doch wie programmiert man so etwas? Zunächst holen wir das Komma hinter SYS 49152 und die Parameter. Dabei müssen die Sekundäradresse und die Filenummer immer auf 2 gesetzt werden, auch wenn der Anwender nichts oder etwas anderes vorgibt. ; Beispiel 4: File-Editor 49152 JSR $AEFD; CHKKOM Komma holen 49155 JSR $E1D4; GETPAR Parameter holen 49158 LDX $BA ; Gerätenummer G aus Vorgabe 49160 LDA #2 ; Filenummer 49162 TAY ; istgleich Sekundäradresse 49163 JSR $FFBA; SETPAR 49166 JSR $FFC0; OPEN 2,G,2,"NAME" Zur Eingabe von Tastatur verwenden wir diesmal die oben geschmähte CHRIN-Routine. Wendet man diese auf die Tastatur an, wird beim ersten Aufruf ein Cursor ausgegeben, und der Anwender kann etwas eingeben und mit bestätigen. Im Akku steht dann das erste Textzeichen. Bei weiteren Aufrufen werden dann nacheinander die einzelnen Zeichen gelesen. Das Ganze ist von der Wirkung her mit dem INPUT-Befehl vergleichbar. 49169 LDX #2 ; Filenummer 49171 JSR $FFC9; CHKOUT Ausgabekanal in File 2 öffnen 49174 JSR $FFCF; CHRIN Eingabe holen 49177 CMP #42 ; Stern? 49179 BEQ 49187; ja, dann fertig 49181 JSR $FFD2; sonst in File ausgeben 49184 JMP 49174; und weitermachen 49187 JSR $FFCC; CLRCHN Kanal schließen 49190 LDA #2 ; Filenummer 49192 JMP $FFC3; CLOSE 2 Beim Schreiben in eine Datei auf Diskette ist es ganz wichtig, daß nach dem Beschreiben ordentlich der Kanal mit CLRCHN und das File mit CLOSE geschlossen werden, da sonst die Datei nicht ordnungsgemäß angelegt wird. Wenden wir das Programm einmal an. Legen Sie eine nicht schreibgeschützte Diskette ein, auf der sich noch Platz befindet, und starten das Programm mit SYS 49152,"TEST,S,W",8 Wählen Sie einen Namen, den es noch nicht auf dieser Diskette gibt! Das Laufwerk beginnt kurz zu arbeiten, und ein Cursor erscheint. Geben Sie nun einige Zeilen Text ein, bestätigen Sie wie in Basic jede Zeile mit . Wenn Sie genug haben, geben Sie nur einen Stern gefolgt von ein. Die Datei wird nun geschlossen, der Computer kehrt ins Basic zurück. Wenn Sie nun das Directory einsehen, stellen Sie fest, daß eine sequentielle Datei »TEST« erzeugt wurde. Wir haben also einen richtigen kleinen Editor für sequentielle Files geschrieben! Versuchen Sie doch einmal, das Programm so auszubauen, daß auch Änderungen an bereits bestehenden Files vorgenommen werden können. Auch erkennt unsere Routine keine Diskettenfehler, man müßte dazu noch den Fehlerkanal auslesen, beispielsweise nach dem Schließen der Datei, und prüfen, ob eine andere Angabe als 00,OK,00,00 ausgegeben wurde. Es reicht in diesem Fall, nur das erste Zeichen des Fehlerkanals zu lesen und mit der Null zu vergleichen. File-Lister Den krönenden Abschluß stellt ein kleines Hilfsprogramm dar, mit dessen Hilfe eine Datei von Diskette gelesen werden und direkt auf den Drucker ausgegeben werden kann. Die Bedienung soll dabei wieder über Angaben nach dem SYS-Befehl erfolgen, also listet beispielsweise SYS 49152,"TEST,S,R" die eben erzeugte sequentielle Datei auf dem Drucker. Im Prinzip ist das gar nicht schwer. Wir beginnen damit, ein Diskettefile zu öffnen und dann einen Ausgabekanal zum Drucker anzulegen. ; Beispiel 5: File-Lister 49152 JSR $AEFD; CHKKOM Komma holen 49155 JSR $E1D4; GETPAR Parameter holen 49158 LDX $BA ; Gerätenummer G aus Vorgabe 49160 LDA #2 ; Filenummer 49162 TAY ; istgleich Sekundäradresse 49163 JSR $FFBA; SETPAR 49166 JSR $FFC0; OPEN 2,G,2,"NAME" 49169 LDA #0 ; kein Filename 49171 JSR $FFBD; SETNAM 49174 LDA #4 ; Filenummer 49176 TAX ; istgleich Gerätenummer Drucker 49177 LDY #0 ; Sekundäradresse 49179 JSR $FFBA; SETPAR 49182 JSR $FFC0; OPEN 4,4,0 Zwei Dinge haben wir dabei gelernt. Erstens spielt die Reihenfolge des Aufrufs von SETNAM und SETPAR keine Rolle. Beim Drucker haben wir erst die Angaben zum Filenamen und dann die Angaben zu den Fileparametern gemacht, anders als gewohnt. Wichtig ist nur, daß beide Routinen vor dem OPEN bereits aufgerufen wurden. Zweitens ist es wie auch in Basic problemlos möglich, mehrere Files auf einmal zu öffnen. Diese müssen sich lediglich in der Filenummer unterscheiden, damit wir uns später auf sie beziehen können. Jetzt schalten wir File 2 (SEQ-Datei) auf einen Eingabekanal und holen uns ein Zeichen. 49185 LDX #2 ; Filenummer 49187 JSR $FFC6; CHKIN 49190 JSR $FFE4; GETIN Planen wir im Voraus. Später wird unser Programm prüfen müssen, ob das Dateiende erreicht ist. Wie checken den Inhalt des Status. Wie das geht, wissen Sie ja schon: Speicherzelle 144 auslesen. Das Programm kann damit allerdings nicht zu lang warten, da sich der Status während späterer Operationen, beispielsweise bei der Zeichenausgabe zum Drucker noch ändern kann. Also lesen und speichern wir ST jetzt: 49193 LDX 144 ; Statusbyte 49195 PHP ; auf den Stack Wir verwenden das X-Register, da sich im Akku ja noch das auszugebende Zeichen von GETIN befindet. Der LDX-Befehl setzt das Zero-Flag des Prozessors, wenn eine Null gelesen wurde (Dateiende nicht erreicht). PHP sichert die Prozessorflags zur späteren Untersuchung auf den Stack (PHush Processorstatus), bis wir sie brauchen. Bevor wir jetzt allerdings das Zeichen drucken können, müssen wir den Eingabekanal mit CLRCHN wieder schließen. Fragen Sie nicht, es scheint bei Commodore-Computern einfach notwendig zu sein. Dabei müssen wir allerdings vorsichtig sein: Der CLRCHN-Aufruf ändert den Inhalt des Akkumulators, das Zeichen geht verloren. Deshalb pushen wir es auf den Stack. 49196 PHA ; Zeichen retten 49197 JSR $FFCC; CLRCHN Der Stack enthält nun zwei Dinge: Erstens das gerade gelesene Zeichen und zweitens den Prozessor-Status (nicht mit dem Statusbyte ST verwechseln! Der PHP-Befehl legt nicht den Inhalt des X-Registers auf den Stack, sondern unter anderem eine Information darüber, ob der letzte Lesebefehl in 49193 Null ergab!). Wenn wir damit anfangen, Werte vom Stack zu holen, bekommen wir zuerst die Werte, die zuletzt dorthin geschrieben wurden - in unserem Fall das Zeichen. Die Druckerausgabe enthält keine Geheimnisse, hier ist der Ausschnitt: 49200 LDX #4 ; Druckerfile 49202 JSR $FFC9; CHKOUT Ausgabekanal öffnen 49205 PLA ; Zeichen vom Stack retten 49206 JSR $FFD2; und zum Drucker schicken 49209 JSR $FFCC; CLRCHN Ausgabekanal schließen Gibt es noch gültige Daten, die wir aus dem Eingabekanal lesen müssen? Der folgende Code prüft das: 49212 PLP ; Prozessorstatus zurückholen 49213 BEQ 49185; weitere Daten, dann oben weiter Sind keine Zeichen mehr in der Datei, können wir beide Files schließen: Zum Beispiel erst das Druckerfile, dann die SEQ-Datei: 49215 LDA #4 ; Drucker 49217 JSR $FFC3; CLOSE 4 49220 LDA #2 ; Diskette 49222 JMP $FFC3; CLOSE 2 und fertig Das war alles, was wir brauchen. Dieses kurze Utility können Sie nun allgemein verwenden. Um beispielsweise die oben angelegte Datei zu drucken, geben Sie den Befehl SYS 49152,"TEST,S,R",8 Solche File-Lister haben in der Praxis eine große Bedeutung, wenn ohne Datenverlust Dateien ausgelesen werden sollen. Sie sind übrigens bei der Ausgabe nicht nur auf SEQ-Files beschränkt. Auch PRG- und vor allem USR-Files lassen sich listen, indem Sie die Kennung ,S im Filenamen entsprechend in ,P oder ,U ändern. Vielleicht bauen Sie ja auch noch eine Art »Schalter« ein, mit dem man die Ausgabe wahlweise auf Bildschirm und/oder Drucker legen kann. Laden einer Datei Bisher haben wir noch nicht versucht, ein File an einen bestimmten Speicherplatz zu laden. Natürlich gibt es das Gegenstück zum LOAD-Befehl auch in Maschinensprache, und zwar in Form der LOAD-Routine mit der Adresse $FFD5. Auch hier müssen Sie erst mit SETPAR und SETNAM oder aber GETPAR Filenamen, Gerätenummer und Sekundäradresse festlegen, die logische Filenummer spielt keine Rolle. Der Inhalt des Akkumulators beim Aufruf der Routine entscheidet darüber, ob geladen wird (A=0) oder ein VERIFY ausgeführt (A ungleich 0). Ist die Sekundäradresse nicht Null, so wird das File »absolut« geladen, also an die Stelle, die auf Diskette gespeichert ist. Sie kennen diese Betriebsart, wenn Sie in Basic mit LOAD "NAME",8,1 etwa Tools an eine vorgegebene Stelle im Speicher laden. Man kann aber auch »relativ« laden, dem Computer also sagen: »Ignoriere die auf Diskette gespeicherte Ladeadresse und lade das File auf jeden Fall an Adresse xxx«. Diese Betriebsart findet beim Laden von Basicprogrammen Verwendung, da lassen Sie hinter LOAD die ,1 einfach weg. Für die Sekundäradresse wird Null gesetzt. In Basic wird dann immer an die Adresse geladen, die in den Speicherzellen 43/44 steht, normalerweise der Basic-Anfang 2049. In Assembler können wir der LOAD-Routine die Adresse mitgeben. Schreiben wir doch einmal ein Utility, mit dem man Hires-Grafiken unabhängig, ab wo sie gespeichert wurden immer nach 8192 laden kann. Dazu holen wir uns erst mit CHKKOM und GETPAR die Fileparameter. Dann setzen wir die Sekundäradresse (gespeichert in $B9) auf Null, um relativ zu laden. Die Ladeadresse 8192 (Highbyte: 32, Lowbyte: 0) übergeben wir im X- und Y-Register, im Akku eine Null, um zu laden, nicht zu vergleichen. Fertig sieht das so aus: ; Beispiel 6: Grafiklader 49152 JSR $AEFD; CHKKOM Komma holen 49155 JSR $E1D4; GETPAR Parameter holen 49158 LDA #0 ; LOAD-Flag 49160 TAX ; Lowbyte von 8192 49161 LDY #32 ; Highbyte von 8192 ($2000) 49163 STA $B9 ; Sekundäradresse Null 49165 JMP $FFD5; LOAD, Grafik in den Speicher laden Mehr ist es nicht! Jetzt könnten Sie beispielsweise mit SYS 49152,"DATEINAME",8 ein Bild (PRG-File) nach 8192 laden. Soll die auf Diskette gespeicherte Adresse berücksichtigt werden, setzen Sie einfach die Speicherzelle $B9 (Sekundäradresse, dezimal 185) auf einen Wert ungleich Null. Die Übergabe einer Adresse in X und Y kann dann entfallen. Speichern Was nun noch fehlt, ist die Möglichkeit, einen beliebigen Speicherbereich auf Diskette zu speichern. In Basic speichert der SAVE-Befehl das Basicprogramm. Dessen Grenzen sind in den Speicherzellen-Paaren 43/44 (Anfang) und 45/46 (Ende) erfaßt. Wir wollen ein Grafikbild, das im Speicher von 8192 ($2000) bis 16383 ($3FFF) einschließlich steht, speichern. Vor dem Aufruf der SAVE-Routine ($FFD8) müssen Sie erst wieder mit SETPAR und SETNAM oder aber in unserem Fall GETPAR die Datei-Parameter festlegen. Dann wird im X- und Y-Register das High- und Lowbyte der um eins erhöhten Endadresse übergeben. Die Startadresse des zu speichernden Bereiches übergeben wir in einem beliebigen Speicherzellen-Paar der Zeropage (in unserem Fall etwa Adressen 2 und 3), dessen Adresse wiederum im Akku übergeben wird. Die Sekundäradresse ist beim Speichern ebenso wie die Filenummer ohne Bedeutung. Das alles klingt sehr umständlich, ist es aber gar nicht, wie das folgende Beispiel beweist: ; Beispiel 7: Grafik speichern 49152 JSR $AEFD; CHKKOM Komma holen 49155 JSR $E1D4; GETPAR 49158 LDX #0 ; bis $4000 ausschließlich speichern (Lowbyte 0) 49160 LDY #64 ; Highbyte von $4000 49162 STX 2 ; ab $2000 speichern (Lowbyte 0) 49164 LDA #32 ; Highbyte von $2000 49166 STA 3 ; merken 49168 LDA #2 ; Startadresse in Speicherzellen 2 und 3 49170 JMP $FFD8; SAVE-Routine: Bild speichern Na sehen Sie, gar keine Schwierigkeit. Die SAVE-Routine erzeugt auf Diskette ein PRG-File mit in diesem Fall 33 Blocks Länge, das im normalen Format (erst zwei Bytes Ladeadresse, hier etwa 8192, dann die Datenbytes aus dem Speicher) das Grafikbild enthält. Das war's! Zum Abschluß noch ein Hinweis zu den Routinen SETPAR (in der Fachliteratur auch oft SETLFS genannt) und SETNAM. Wie Sie wissen, dienen die beiden Routinen dazu, vor Dateibefehlen die File-, Gerätenummer, Sekundäradresse sowie den Dateinamen zu definieren. Werfen wir einen Blick hinter die Kulissen: Hier je ein komplettes Assemblerlisting, wie SETPAR und SETNAM intern funktionieren: ************************** SETPAR Fileparameter setzen FFBA 4C 00 FE JMP $FE00 SETPAR-Sprung FE00 85 B8 STA $B8 logische Filenummer FE02 86 BA STX $BA Geräteadresse FE04 84 B9 STY $B9 Sekundäradresse FE06 60 RTS und fertig ************************** SETNAM Filenamen setzen FFBD 4C F9 FD JMP $FDF9 SETNAM-Sprung FDF9 85 B7 STA $B7 Länge FDFB 86 BB STX $BB Adresse low FDFD 84 BC STY $BC Adresse high FDFF 60 RTS und fertig Die Routinen SETPAR und SETNAM schreiben also nur die Inhalte der Register A, X und Y in je drei Speicherzellen, es werden also im Prinzip nur je drei POKEs ausgeführt. Was lernen wir daraus? Richtig, es ist nicht immer optimal, JSR $FFBA oder $FFBD aufzurufen. Betrachten Sie das Beispiel 5 (File-Lister). Hier sollte ab Adresse 49158 eigentlich nur die File- und Gerätenummer auf 2 gesetzt werden, auch wenn der Anwender etwas anderes oder gar nichts angegeben hat. Da sich beim Aufruf von SETPAR in 49163 jedoch ein definierter Wert auch im X-Register (Gerätenummer) befinden muß, mußten wir umständlich in 49158 die alte Gerätenummer in das Register laden, nur damit sie dann von SETPAR in $FE02 wieder gepoket werden kann. Einfacher wäre es also hier (und übrigens auch in Beispiel 4) gewesen, wenn wir den Teil von 49158 bis 49163 ersetzt hätten durch LDA #2 STA $B8 ; logische Filenummer STA $B9 ; Sekundäradresse Dadurch hätten wir zwei Bytes gespart. Ebenso könnte man die Befehlsfolge LDA #0 ; kein Filename JSR $FFBD; SETNAM die beim Eröffnen eines Druckerfiles die Länge des Filenamens auf Null setzt (vergleiche z.B. Beispiel 3 ab 49163) durch die beiden Befehle LDA #0 ; kein Filename STA $B7 ; Länge des Filenamens ersetzen. Ersparnis: Ein Byte. Außerdem läuft die Alternative erheblich schneller als die »Kochrezept-Version«. Damit wären wir am Ende unseres kleinen Streifzugs durch die gar nicht so weite Welt der Ein/Ausgabe in Assembler angelangt. Experimentieren Sie doch noch ein wenig mit dem Gelernten, das kann sicher nicht schaden! Zum Abschluß noch eine tabellarische Übersicht über die behandelten Betriebssystem-Routinen. Der Stern bei der Adreß-Angabe weist darauf hin, daß es sich nicht um eine sogenannte »Kernal-Routine« handelt, daß also die Adresse ausschließlich für den C 64 gilt. Name Adresse Funktion AXOUT $BDCD = 48589* 16-Bitzahl ausgeben CHKIN $FFC6 = 65478 Kanal für Eingabe öffnen CHKKOM $AEFD = 44797* Komma holen CHKOUT $FFC9 = 65481 Kanal für Ausgabe öffnen CHRIN $FFCF = 65487 Zeicheneingabe (siehe unten) CHROUT $FFD2 = 65490 Zeichenausgabe CLALL $FFE7 = 65511 Alle Dateien und Kanäle schließen CLOSE $FFC3 = 65475 Datei schließen CLRCHN $FFCC = 65484 Kanäle schließen CRLF $AAD7 = 43735* Return ausgeben GETIN $FFE4 = 65508 Zeicheneingabe (siehe unten) GETPAR $E1D4 = 57812* LOAD/SAVE-Parameter holen LOAD $FFD5 = 65493 Datei laden OPEN $FFC0 = 65472 Datei öffnen SAVE $FFD8 = 65496 Speicherbereich speichern SETNAM $FFBD = 65469 Filenamen setzen SETPAR $FFBA = 65466 File-, Gerätenummer und Sekundäradresse setzen SPACE $AB3F = 43839* Leerzeichen ausgeben Merke: Bei Eingabe von einem File sind GETIN und CHRIN gleichwertig, in diesem Fall ist aus technischen Gründen GETIN vorzuziehen. Bei Eingabe von Tastatur liest GETIN ein Zeichen aus dem Tastaturpuffer und liefert eine Null, wenn keine Taste gedrückt wurde, während bei CHRIN ein Eingabecursor erscheint und auch längere Texte erfaßt werden können. Wichtige Speicherzellen (C 64): $90 = 144 Statusvariable ST $B7 = 183 Länge des Filenamens $B8 = 184 logische Filenummer $B9 = 185 Sekundäradresse $BA = 186 Gerätenummer $BB = 187 Adresse des Filenamens LOW $BC = 188 Adresse des Filenamens HIGH Multitask - Mehrere Maschinenprogramme gleichzeitig ablaufen lassen Welcher C64-Programmierer würde es sich nicht wünschen, mehrere Maschinenprogramme gleichzeitig ablaufen lassen zu können? Mit dem hier vorgestellten Tool »Multitask« wird das zum Kinderspiel. Bis zu 31 Assemblerroutinen laufen mit nur leicht verringerter Geschwindigkeit quasi gleichzeitig ab, auf Wunsch kann dabei sogar noch in Basic weiterprogrammiert werden. von Nikolaus M. Heusler Die Routine wird mit LOAD "MT 49152",8,8 geladen. Danach sollten Sie NEW eingeben, um alle Zeiger richtigzustellen. Andernfalls könnte die Fehlermeldung ?OUT OF MEMORY ERROR erscheinen. Als nächstes lädt man die Routinen, die gleichzeitig ablaufen sollen, in den Speicher. Mit dem Befehl SYS 49152, ad1, ad2, ad3, ad4, ... werden nun beliebig viele solcher Maschinenprogramme (Minimum 1, Maximum 31) fast gleichzeitig gestartet. Sofern sie sich nicht gegenseitig stören (siehe unten), laufen sie quasi parallel ab. Die Startadressen der Routinen werden nach dem Komma übergeben: ad1, ad2, ad3 und so weiter. Geben Sie dabei einfach die Adressen an, die sonst auch hinter SYS stehen würden, um die Routinen einzeln zu aktivieren. So würde etwa der Befehl SYS 49152, 20000, 32000 zwei Maschinenprogramme ab 20000 und 32000 gleichzeitig starten. Wenn in dieser Parameterliste noch das Kaufmannsund (&) steht, kehrt der SYS 49152 nach dem Start der Maschinenprogramme nach Basic zurück. Jetzt kann programmiert werden, während die Assemblerroutinen im Hintergrund laufen (besonders praktisch für Tools und Programmierhilfen oder ähnliches)! Im obigen Fall also etwa: SYS 49152, 20000, 30000, & Die Anwendung des & kann beliebig erfolgen, also auch zum Beispiel SYS 49152, &, 20000, 30000 oder SYS 49152, 20000, &, 30000 Anstelle der Zahlen können natürlich auch Variablen oder Rechenausdrücke für die Startadressen verwendet werden. Allerdings darf keine der Maschinenroutinen, die gestartet werden sollen, an Adresse 0 beginnen. SYS 49152,...,0,... ist also verboten. Die Routine fängt Fehleingaben ab, es erscheint ein ?ILLEGAL QUANTITY ERROR. Hier ein praktisches Beispiel für die Anwendung: 30000 INC 53280 30003 JMP 30000 Startet man dieses Programm mit SYS 30000, flimmert der Bildschirmrahmen in einer Endlosschleife. Soll dieser Effekt auftreten, während Basic läuft, wenden Sie einfach Multitask an: SYS 49152,30000,& Nun könnte gleichzeitig dazu noch ein Sprite horizontal bewegt werden, solange der Feuerknopf eines Joysticks in Port 2 gedrückt wird: 35000 LDA #101 35002 STA 53269 35005 STA 53248 35008 STA 53249 35011 LDA #1 35013 STA 2040 35016 LDA 56320 35019 AND #16 35021 BNE 35016 35023 INC 53248 35026 JMP 35016 Im Bereich von 35000 bis 35015 wird das Sprite sichtbar auf den Monitor gebracht. Ab 35016 beginnt die Endlosschleife, die für die Bewegung bei zuständig ist. SYS 49152,35000,30000,& läßt diese Routine ablaufen - gleichzeitig mit Basic und dem oben gezeigten Flimmern! Bei den Maschinenprogrammen, die von Multitask ausgeführt werden, handelt es sich also meistens um Endlosschleifen. Dennoch ist eine Funktion eingebaut, die auch Ausstiege mit RTS verkraftet. Näheres dazu weiter unten. Einige Anregungen für Routinen, die Sie miteinander und zusammen mit Basic aktivieren könnten: Tastenklick, eingeblendete Echtzeituhr, Escape-Funktion (Löschen des Quote-Modus bei besonderer Tastenkombination), verbesserter Editor, Reset auf Tastendruck, ein Sprite, das »von alleine« bewegt wird, während ein Basic-Spiel läuft, und vieles mehr. Als Beispiel für die Anwendung mag auch das Demo dienen. Es wird mit LOAD "MT.DEMO",8 geladen und mit RUN gestartet. Das Basicprogramm lädt nun noch das steuernde Maschinenprogramm, die Unterroutinen und einige Spritedaten nach. Sodann erscheint die Frage, ob Basic weiter ablaufen soll. Drücken Sie die Taste <1> oder <2>. Es kann nun einige Sekunden dauern, bis wirklich alle Maschinenroutinen ablaufen, dann erscheint ein galoppierendes animiertes buntes Pferd auf dem Schirm. Es wird von einigen Maschinenroutinen ab 10000 gesteuert: 10000 horizontale Bewegung 10050 vertikale Bewegung 10100 Animation 10150 Pferd sichtbar machen 10200 (interne Warteschleife) 10250 Farbänderung Bei allen Routinen (bis aus 10150 und 10200) handelt es sich um Endlosschleifen wie oben erklärt. Jede dieser Routinen kann also mit SYS gestartet werden. Geben Sie SYS 10150 ein, wird nur das Pferd eingeschaltet. Starten Sie jetzt die vertikale Bewegung mit SYS 10050, fährt das Pferd einfach nur nach oben und unten, ohne sonstige Effekte. Das im Demoprogramm erzeugte Sammelsurium wird demnach zum Beispiel mit SYS 49152, 10150,10000,10050,10100,10250,& gestartet. Das Zeichen & am Ende bewirkt den Basic-Rücksprung. Im Prinzip können mit dieser Routine somit beliebige Assemblerroutinen, die an sich Endlosschleifen darstellen, miteinander ablaufen. Sie müssen allerdings aus technischen Gründen einigen Bedingungen entsprechen: Zum einen dürfen keine IRQ-Manipulationen wie SEI oder Verbiegen des IRQ-Vektors vorgenommen werden. Andernfalls kann es passieren, daß etwa der Task, der den Interrupt sperrt, nicht mehr verlassen und als einziger ausgeführt wird. CLI dagegen ist erlaubt. Ebenso ist die Veränderung des Prozessorports (Adresse 1) zu vermeiden. Auch sind natürlich Komplikationen zu erwarten, wenn mehrere Maschinenprogramme die gleichen Speicheradressen verwenden oder gar im selben Bereich arbeiten. Das Utility selbst belegt auch bestimmte Speicherstellen, und zwar den Bereich 49152-49546, $E000-$FFFF unter dem RAM und die Zeropageadressen 2 und 3. Außerdem sollten Operationen mit Peripheriegeräten (Floppy, Drucker, Band) vermieden werden, während das Multitasking aktiv ist. Mit SYS 49155 wird der Multitask-Betrieb wieder abgeschaltet. Unter Umständen ist es günstig, die IRQ-Geschwindigkeit und damit die Tast-Wechselgeschwindigkeit zu verändern. Dazu dient der Befehl SYS 49158,X X ist ein Wert zwischen 1 und 255, der Wert 0 wirkt wie 256. Je größer X gewählt wird, desto langsamer wechselt der C 64 die Tasks. Lassen Sie den Parameter X weg, wird der Standardwert 60 eingesetzt: SYS 49158 Bei diesem Utility ist es interessant, zu erfahren, wie ungefähr es intern funktioniert. Genauere Information kann der interessierte Leser dem kommentierten Quelltext entnehmen. Grundlage für das Multitasking ist der Systeminterrupt (IRQ). Bei jedem IRQ unterbricht der C 64 das momentan laufende Maschinenprogramm, um eine Interruptroutine abzuarbeiten. In diesem Fall handelt es sich um eine neue Routine. Diese holt sich zunächst die Adresse vom Stack, an der das aufrufende Programm unterbrochen wurde, und speichert diese. Einer Tabelle wird die Startadresse des ersten zu startenden Programmes entnommen und auf den Stack geschrieben. Wenn der Computer jetzt die IRQ-Routine verläßt, findet er die neue Adresse auf dem Stack und macht mit dem nächsten Programm weiter - bis zum nächsten IRQ. Auf diese Weise kommen alle gewählten Routinen nacheinander je einmal dran. Danach wird von vorn begonnen. Da die IRQs sehr häufig (normal 60 mal in der Sekunde) auftreten, wird der Eindruck erweckt, die Programme laufen gleichzeitig ab. Neben der Rettung der Startadressen ist es erforderlich, die drei Prozessorvariablen A, X und Y sowie den Stackpointer, den Stack (Adresse 256 bis 511) und das Statusregister zu speichern. Dazu dient ein reservierter Speicherbereich ab $E000 unter dem Kernal-ROM gemäß untenstehender Speicherbelegung. Dadurch bleibt in den Tasks neben der Möglichkeit, ganz normal alle Prozessor-Register zu benutzen, sogar der Stack voll und ganz erhalten. Befehle wie PLA und PHA dürfen wie gewohnt ausgeführt werden (siehe dazu die untenstehende Bemerkung zum Stack). Am Ende der IRQ-Routine wird allerdings noch die normale System-IRQ-Routine ausgeführt, damit Effekte wie das Cursorblinken und der Editor weiterhin erhalten bleiben. Ein Problem stellt sich noch, wenn eines der Maschinenprogramme keine Endlosschleife ist, sondern mit RTS endet. Da es dann keine sinnvolle Rücksprungadresse auf dem Stack finden würde, wäre ein Absturz unvermeidbar. Daher erzeugt das Utility beim ersten Aufruf jeder Routine eine künstliche Rücksprungadresse, die auf eine Endlosschleife zeigt, und schreibt sie auf den Stack. Endet ein Task mit RTS, wird als nächstes diese Endlosschleife ausgeführt. Der Task ist also abgeschlossen, stört aber nicht die Ausführung der übrigen Programme. Ähnlich funktioniert die Auswahlmöglichkeit, ob das Basic weiter ablaufen soll. Wählen Sie diese Option, kehrt der Befehl SYS 49152 nach der Ausführung einfach mit RTS in den Basic-Editor zurück. Dieser ist jetzt einer der auszuführenden Tasks. Soll kein Basic ablaufen, endet SYS 49152 in einer Endlosschleife. Vor dem ersten Aufruf jedes Tasks wird außerdem der Stackpointer auf 247 gesetzt, damit das Maschinenprogramm den vollen Stack zur Verfügung hat. Für den Programmierer ist dies jedoch nicht von Bedeutung. Wir wünschen Ihnen viel Spaß mit diesem neuartigen Multitask-Gefühl. Was Sie alles damit machen können, liegt voll und ganz bei Ihnen und Ihrer Phantasie. Genießen Sie die umfangreichen Möglichkeiten dieser neuen Technik! Speicherbelegung (hexadezimal): 0002-0003 temporär: Zeiger auf Startadressen-Tabelle c000-c18a Maschinenprogramm c000-c008 Sprungtabelle c009 Init c01b Parameterschleife c086 Endlosschleife, falls Basic ausgeschaltet c08f Ende Multitasking c095 IRQ-Speed setzen c0a4 Endlosschleife für Task-Ende mit RTS c0a7 neue IRQ-Routine c0b0 nächsten Task suchen c0c2 neue Adresse merken c0cd alte Adresse speichern c0df neue Register merken c0fd alte Register speichern c119 Stacks vertauschen c131 ab hier einige Selbstmodifikationen c139 Zeiger auf nächsten Task c147 Stackpointer vorbereiten c14f Endlosschleife bei RTS vorbereiten c15c neue Adresse setzen c166 neue Register setzen c181 neue Hardware-NMI-Routine c188 Flag: Basic eingeschaltet c189 Anzahl Tasks c18a Flag: Task bereits einmal aufgerufen e000-e03f Startadressen-Tabelle e040-e05f Tabelle: A-Register der Tasks e060-e07f Tabelle: X-Register der Tasks e080-e09f Tabelle: Y-Register der Tasks e0a0-e0bf Tabelle: Status-Register der Tasks e0c0-e0df Tabelle: Stackpointer der Tasks e100-feff Stackinhalte der Tasks Das NSS-Kernal: Runderneuert! An diesen Beitrag werden Sie vielleicht in naher Zukunft jeden Tag erinnert werden, wenn Sie Ihren Computer einschalten: Aus dem C 64 wird nun doch ein richtiger Profi-Computer! Ein neues Betriebssystem putzt den alten Kasten mächtig heraus. Was halten Sie davon: Directory und andere Floppy- und Druckerfunktionen auf Tastendruck, Renew-Routine, Schnell-Lader mit 16 facher Geschwindigkeit, Funktionstastenbelegung, Renew-Routine und viele Sonderfunktionen für den Programmierer und Anwender. Das neue Kernal ist eine Hardware-Erweiterung. Dazu muß im C 64 ein IC ausgewechselt werden. Das neue Kernal, das Sie von uns als Datei erhalten, muß wie unten beschrieben in ein Eprom gebrannt werden, welches dann gegen ein ROM im C 64 ausgetauscht wird. Ab jetzt sind die neuen Funktionen sofort nach dem Einschalten des C 64 verfügbar. Sollte es wider Erwarten dennoch einmal Probleme mit anderen Programmen geben, läßt sich diese Low-Cost Erweiterung mit einem Schalter einfach abschalten. Betriebssystem - Beschreibung Tastenfunktionen Fastload on/off (wird angezeigt) RENEW + CLR (Anzeige: »RENEW OK«) FloppyIRQ hochsetzen => schnellere Kopfbewegung (Anzeige: »IMPROVED...«), funktioniert unter Umständen nicht gleich beim ersten Mal Die SAVE-Routine speichert nun auch das RAM unter dem Basic-ROM (Anzeige: »SAVE RAM«) Alle neuen Tasten aus; Rückgängigmachen mit Führt ein unterbrochenes LIST fort «LOAD ":*" ,8,1 {RETURN} SYS {RETURN}» Directory ohne Programmverlust Fehlerkanal anzeigen Floppybefehl eingeben (Abschluß mit ) «LOAD............,8,1» - Laden aus dem Directory Wie F7, zusätzich und SYS LIST SAVE " RUN sendet Text zum Drucker 4, Sek. Adr. 0 sendet Text zum Drucker 4, Sek. Adr. 7 Prompts: alleine: »>«, mit : »]«, mit : »)« am Zeilenende erfolgt automatisch (ohne ) Wann reagieren diese Tasten nicht? Wenn mindestens eine dieser Bedingungen zutrifft: · Abgeschaltet (POKE (0),175 oder wegen ) · Programm-Modus aktiv (PEEK (157)=0) · INSERT-Modus aktiv (PEEK (216) > 0) · Hochkommamodus aktiv (PEEK (212) > 0) · Computer wartet gerade nicht auf Eingabe (Routine ab $E5CA, Veränderung: $E5E7) Sonstiges 1. Peripheriegeräte: · Fastload (EXOS-Version) lädt 12-14 mal so schnell von Diskette 1541 · Angabe »,8,1« kann bei LOAD und VERIFY entfallen · LOAD "NAME",8,0,ADR lädt Programmfile ab ADR · LOAD "NAME",8 ohne Sekundäradresse lädt absolut (,8,1) · LOAD zeigt (außer im Programmodus oder bei PEEK (1) ungleich 55) an, wohin geladen wird (dezimal) · SAVE "Klammeraffe:" funktioniert! (Anzeige: SCRATCHING...) Das Programm wird erst gelöscht (S:) und dann normal gespeichert · Bei LOAD ,8,1 kann NEW in den meisten Fällen entfallen · Bei VERIFY wird sofort nach dem ersten Fehler abgebrochen 2. Bedienung des C 64: · Bildschirmfarben: Rahmen und Hintergrund dunkelgrau, Schrift weiß · Cursorgeschwindigkeit erhöht · Tastenrepeat beim Einschalten für alle Tasten (PEEK (650)=235) 3. Basic-Programmierung: · Kein Listschutz mehr wirksam (Ausnahme: Nullbyte nach Zeilennummer) · hält Scrollen an, verlangsamt nicht mehr so stark · SYS ohne Zahl startet das letztgeladene Programm an der Adresse, an die es geladen wurde (oder mit RUN, wenn Adresse = DEEK (43)). Die Ladeadresse merkt sich das System in DEEK (671) (ehemals IRQ-Vektor bei Cassettenbetrieb) · Durch Druck auf und können Sie ein Maschinenprogramm über den Vektor 671/2 starten (z.B. Spritekiller möglich!) 4. Hardware: · : Gleichzeitig mit : -Schutz überlistet : Klingeln ertönt (SID-Test) : Autostart (siehe oben) RAM-Test entfällt (Reset wesentlich schneller) CIAs programmiert auf 50 Hz (Routine ab $FDA3) · + überlistet -Schutz · Grafik ab $E000 wird bei oder nicht zerstört · Versionsnummer (PEEK(65408)) = 66 5. Korrektur von Systemfehlern: · Bildschirmlöschroutine problemlos · Das Bildschirmlöschen geht etwas schneller 6. Einschränkungen: · Tape kann nicht mehr benutzt werden · WICHTIG: Kein VERIFY bei aktiviertem Fastload möglich · Die RS 232-Schnittstelle kann nicht mehr benutzt werden · Das Directory kann nicht mit dem Schnell-Lader geladen werden. Es sollte nur mit geladen werden. Interna POKE 0, PEEK (0) OR 128 Tasten aus POKE 0, PEEK (0) OR 64 Fastload aus POKE 0, PEEK (0) AND 127 Tasten an POKE 0, PEEK (0) AND 191 Fastload an schaltet beide Funktionen an Also: PEEK (0): Bit 7: Tasten (1 = aus, 0 = an) Bit 6: Fastload (1 = aus, 0 = an) Einbau Das entsprechende File ist auf ein Eprom vom Typ 27128 zu brennen (Eprom-Brenner). Dieses Eprom ist in einen handelsüblichen Adaptersockel zu stecken (zum Beispiel von REX Datentechnik, Hagen, Bestellnummer 9598), der dann anstelle des Kernal-ROMs (Bezeichnung U4) in den C 64 (alte Version) eingebaut wird. U4 findet sich, wenn Sie den C 64 aufklappen, als der mittlere der drei kleineren 24-poligen Chips in der oberen Reihe links unter dem Cassettenport und rechts vom Userport. Falls das System in ein 27128 gebrannt wird, soll das neue System in der unteren Bank 0 ($0000-$1FFF) und das Original-Kernal in Bank 1 (oben, $2000-$3FFF) stehen. Der Einbau sollte nur vom Fachmann vorgenommen werden! Das NSS-Kernal eignet sich nicht zum Betrieb in einer ROM-Steckkarte für den Expansion-Port, da hier die Einblendung in den Bereich ab $8000 erfolgt. Für den Einbau in einen neuen C 64 muß zusätzlich noch der Basic-Interpreter in das Eprom 27128 gebrannt werden, ein Umschalten ist dann nicht ohne weiteres möglich. Brennen des Eproms Um das Kernal in ein handelsübliches Eprom zu brennen, benötigen Sie neben dem Eprom 2764 einen geeigneten Eprom-Brenner. Jetzt wird das File »NSS KERNAL 2764« unter Beachtung der Hinweise in der Anleitung zum Brenner in das Eprom gebrannt. Soll bei Bedarf auf das alte Betriebssystem umgeschaltet werden können, verwenden Sie ein Eprom vom Typ 27128 und brennen in dieses das File »NSS KERNAL 27128«. Zur Umschaltung beachten Sie die Hinweise in der Anleitung zum Adaptersockel. Sicherheitsvorschriften für CMOS-ICs CMOS-ICs sind sehr empfindliche elektronische Bausteine. Daher sollten sie mit besonderer Vorsicht behandelt werden. Diese Chips sind unter anderem sehr empfindlich gegen statische Aufladung, daher sollten Sie Berührungen vor allem der elektrischen Anschlüsse (»Beinchen«) vermeiden. Der schwarze Stoff (Leitgummi) schützt gegen Aufladungen, er muß jedoch vor dem Betrieb entfernt werden. Auch sollten diese Bausteine keinen extremen Temperaturen oder Schwankungen ausgesetzt werden. Ebenfalls sind größere mechanische Belastungen (z.B. Stöße, Reibung) zu vermeiden. Das IC darf nur bei ausgeschaltetem Rechner eingesetzt werden. Eproms werden durch UV-Licht gelöscht. Daher sollten Sie nicht den Schutzaufkleber abziehen, und intensive Sonnenstrahlung oder die Bestrahlung durch UV-Lampen, etwa Höhensonnen, vermeiden. Bestell-Service Sollte es Ihnen zu mühsam oder nicht möglich sein, die Datei in ein Eprom zu brennen, können Sie beim Verlag ein einbaufertiges gebranntes Eprom komplett mit Adapterplatine erhalten. Das Bauteil muß dann nur noch an Stelle des alten ROMs in den C 64 eingesetzt werden. Der Preis für den Zusatz beträgt DM 79,- (zahlbar im Voraus in bar oder per Scheck oder bequem per Nachnahme). Geben Sie bei der Bestellung bitte an, ob Sie einen neuen oder alten C 64 besitzen. Die Adresse: IPV Ippen & Pretzsch Verlags GmbH Pressehaus Bayerstraße 57-59 8000 München 2 Tel. 089/8542412 Fax. 089/8545837 Dieses Angebot ist leider nicht mehr gueltig. Der IPV Verlag ist nicht mehr unter dieser Anschrift erreichbar. Hinweis: Der Einbau des Bauteils in Ihren C 64 ist nur möglich, falls das Kernal-ROM (Position U4 beim alten und neuen C 64) gesockelt ist, da man sonst das alte IC nicht ohne weiteres entfernen kann! Falls nicht, müssen Sie das alte Original-IC auslöten und durch einen Sockel ersetzen. Bitte beachten Sie, daß durch diesen Eingriff jegliche Garantieansprüche am Computer verlorengehen. Jetzt wird's kalt: Eisberg Ganze 32 Fehler- und Störungsmeldungen hält der C 64 für den Programmierer bereit. Aus eigener Erfahrung wissen Sie, wie ärgerlich es ist, wenn einen der Computer so besserwisserisch und kalt abserviert. Aber Sie sitzen am »längeren Hebel«! Schalten Sie die Fehlermeldungen doch einfach ab - mit »Eisberg«. Man kann eingeben, was man will, es erscheinen einfach keine Fehlermeldungen mehr. Dieses nur drei Blocks kurze Gag-Programm hat jedoch durchaus auch praktischen Nutzen. Machen auch Sie Ihre Programme professioneller! Laden Sie das Programm »Eisberg« (oft ist es gar nicht so einfach, einen guten Namen für ein neues Programm zu finden) mit dem Befehl LOAD "EISBERG",8 Der Start erfolgt mit RUN, Assembler-Kenntnisse sind also zur Anwendung dieses Maschinenprogramms nicht notwendig. Eine Einschaltmeldung erscheint. Ab jetzt sind alle Basic-Fehlermeldungen sowie die Störungs-Hinweise ?REDO FROM START und ?EXTRA IGNORED bei INPUT-Befehlen abgeschaltet. Sie können eingeben, was Sie wollen, es erscheint einfach keine Fehlermeldung mehr: PRINT 1/0 HALLO A = SIN TI$ = "ANDREAS" RETURN:RETURN NEXT 1 GOSUB 1 PRINT FNX(0) POKE -1,4834 PRINT 1E99 LOAD "$",30 PRINT VAL(18) A$ = 8 CONT DIM O(10),O(11) PRINT O(1000) INPUT PRINT ASC("") GOTO 65000 Bei allen diesen Befehlen wirft der Computer sonst gnadenlos irgend eine Fehlermeldung aus. Mit aktiviertem Eisberg wird der »defekte« Befehl entweder einfach gar nicht ausgeführt, sondern übersprungen, oder der C 64 gibt ein unsinniges Ergebnis aus. In einigen Fällen - und darin liegt der praktische Wert von diesem Hilfsprogramm - wird der Befehl sogar »kulant« ausgeführt, der Computer nimmt einen anderen Befehl an, dessen Wirkung der vom Programmierer gewollten nahekommt. Beispiel GOTO-Befehl: Beziehen Sie sich mit GOTO 90 auf eine nicht existierende Programmzeile, sucht sich das Programm die Zeile mit der nächst höheren Nummer und springt diese an. Ist im Beispiel die Zeile 90 nicht existent, aber dafür Zeile 100, so geht es in Zeile 100 weiter (oder in der nächsten Zeile, die im Programm auf 90 folgt). Ein weiterer ärgerlicher Fehler, der in Basic manchmal auftritt, ist der ?ILLEGAL QUANTITY ERROR, den die ASC-Funktion auf einen Leerstring angewandt ausgibt. Beim Lesen aus Dateien werden aber für Nullbytes leere Strings erzeugt. Die ASC-Funktion wurde daher so umgebaut, daß ein leerer String den ASCII-Code Null hat. Komplizierte Konstruktionen wie 10 GET#2,A$ 20 A=ASC(A$+CHR$(0)) um eine Datei zu analysieren können Sie sich in Zukunft sparen. Oder es soll mit GET A eine Menüabfrage realisiert werden. Gewöhnlich wird die Betätigung einer alphanumerischen Taste durch einen ?SYNTAX ERROR quittiert, nicht aber mit Eisberg. Interessante mathematische Effekte lassen sich beobachten. Die Teilung durch Null, mathematisch als Unendlich definiert, ergibt beim C 64 eine sehr große Zahl, also sogar fast das korrekte (?) Ergebnis. Die Logarithmus-Funktion ist nur für positive Zahlen definiert. Gibt man einmal PRINT LOG(0) ein, erscheint kein ?ILLEGAL QUANTITY ERROR mehr, sondern eine negative Zahl. Wird diese als Argument der Umkehrfunktion EXP gesetzt, ist das Ergebnis fast Null. Im Grunde genommen liegt also nur ein Rundungsfehler vor. Ähnliche Effekte treten bei Anwendung der transzendenten Funktionen auf. In anderen Fällen arbeitet das Programm zwar fehlerhaft, aber es steigt nicht aus. Beispielsweise erscheint die ?STRING TOO LONG-Meldung bei zu langen Texten nicht mehr, es werden einfach alle Zeichen ab Nr. 256 abgeschnitten. Bei zu hohen Werten etwa hinter POKE verwendet der Computer nur die Bits, die ihn interessieren. POKE 4,900 wirkt also wie POKE 4,132, da das Lowbyte von 900 gerade 132 ist. Gleiches gilt für die Adreßangabe bei SYS, POKE, WAIT und PEEK. Die Liste läßt sich beliebig fortsetzen. RETURN ohne GOSUB, zu komplizierte Verschachtelungen, falsche oder fehlende Parameter, Dateifehler, fehlende Doppelpunkte oder Kommas, nichts bringt den Computer mehr aus der Ruhe. Fertige und ausgetestete (!) Programm werden so noch professioneller, da im Falle eines Bedienungs- oder übersehenen Programmierfehlers kein Ausstieg mit einer Fehlermeldung mehr erfolgt. Es soll betont werden, daß alle Funktionen des C 64 absolut unverändert normal arbeiten, wenn keine Fehler auftreten. Am Lauf eines fehlerfreien Programms oder Algorithmus wird sich also rein gar nichts ändern, wenn Eisberg aktiviert ist. Eisberg bleibt auch nach einem Warmstart mit aktiv. Es läßt sich nur mit einem Reset oder dem Befehl POKE 1,55 ausschalten. Danach erfolgt der Neustart, falls sich das Steuerprogramm noch im Speicher befindet, mit SYS 51200 Zur Erklärung der internen Vorgänge: Nach dem Laden und Starten kopiert sich Eisberg in einen Bereich von 51200 bis 51711 ($C800 bis $C9FF) und startet sich dort. Jetzt werden das Basic- und das Betriebssystem-ROM in die darunterliegenden RAMs kopiert. Dort nimmt das Programm umfangreiche Änderungen vor. An vielen Stellen werden Branch-Befehle, die bei Störungen eine Fehlermeldung auslösen, unwirksam gemacht. Manche Routinen, die auf Fehlbedienung prügen, werden einfach mit einem RTS unwirksam gemacht. An einigen Stellen baut Eisberg Sprungbefehle ein, die in eine Routine münden, die das Ende des aktuellen Basicbefehle suchen (DATA-Befehl) und dann die Interpreterschleife aufrufen. Diese Routine ab $A19E (dort standen vorher die Original-Fehlermeldungstexte) bewirkt, daß ein fehlerhafter Befehl einfach nur übersprungen wird, es erfolgt kein Programmabbruch. Diese Technik hat gegenüber der Methode, einfach die Zentralroutine zur Ausgabe einer Fehlermeldung auf den Basicstart zu verbiegen, den Vorteil, daß ein fehlerhaftes Programm weder mit noch ohne Meldung beendet, sondern einfach beim nächsten Befehl fortgesetzt wird. Nach den Änderungen schaltet Eisberg mit POKE 1,53 die ROMs aus und die RAMs ein. Dort befinden sich jetzt modifizierte Versionen von Kernal und Basic, die ab sofort ablaufen. Der Bereich ab 51200 wird jetzt nicht mehr benötigt und steht ebenso wie der Basicspeicher anderen Anwendungen offen. Absturz? Nein Danke! »Uncrash« hilft Computer abgestürzt, Programm futsch? Selbst schuld! Hätten Sie vorher »Uncrash« aktiviert, hätten Sie das Schlimmste vielleicht verhindern können. Sowohl Basic- wie auch Maschinenprogrammierer werden dieses kleine Utility besonders schätzen, das den C 64 praktisch absturz-steril macht. Mit diesem Programm werden Sie, wenn überhaupt, nur noch selten wegen eines Absturzes Daten verlieren. Enthalten ist eine Renew-Routine, die auch die Variablenwerte wiederherstellt. Einer der großen Vorzüge des C 64 gegenüber anderen Homecomputern ist die Möglichkeit, ihn völlig an die eigenen Bedürfnisse anzupassen. Mit seinen Vektoren und dem Prozessorport haben Sie als Programmierer weitgehenden Einfluß auf die internen Vorgänge. Diese offene Architektur macht den Computer allerdings auch sehr verwundbar gegen falsche Programmierung. Ein einziges falsches Kommando und Totenstille kehrt ein. Manchmal arbeitet das Gerät nach weiter - aber nicht immer. Sie können den Rechner aus- und wieder einschalten, das hilft garantiert, löscht aber ebenso sicher die gespeicherten Daten, inklusive Ihr Programm samt seiner Variablen und Tools, mit denen Sie vielleicht arbeiten. Das kann schon sehr frustrierend sein. Manche C 64-Besitzer haben mittlerweile einen Reset-Taster installiert, mit dem ein echter Kaltstart durchgeführt werden kann. C 128-Anwender haben einen solchen Knopf »ab Werk« am Computer. Ob Sie diesen Zusatz Ihr eigen nennen oder nicht, Sie profitieren in jedem Fall von »Uncrash«. Es handelt sich dabei um ein kurzes Maschinenprogramm. Sie brauchen jedoch keinerlei Assemblerkenntnisse, um damit arbeiten zu können. Das Programm ist in der Lage, bestimmte Abstutzsituationen selbstständig zu erkennen und zu verhindern. Es erscheint unglaublich, aber Uncrash erkennt sogar bestimmte Basicbefehle, die einen Absturz bewirken würden und führt sie gar nicht aus. Sollte sich der Computer wirklich einmal aufgehängt haben, gibt es auf Tastendruck zwei Stufen, wieder herauszukommen. Einzige Bedingung ist, daß Sie Uncrash vor Beginn der Session installiert haben. Dazu laden Sie das Programm mit LOAD "UNCRASH",8 Obwohl das Programm aus Gründen des Koforts und der Geschwindigkeit vollständig in Maschinensprache verfaßt ist, brauchen Sie keine Assemblerkenntnisse, um damit arbeiten zu können. Die Bedienung erfolgt wie gewohnt in Basic. Starten Sie nach dem Laden das Utility mit RUN. Es ist jetzt aktiviert, eine Meldung erscheint. Soll das Tool geladen und aktiviert werden, während bereits ein Basicprogramm im Speicher steht, das bei obigem Manöver natürlich verloren gehen würde, besteht auch die Möglichkeit, Uncrash mit LOAD "UNCRASH 52809",8,1 absolut von Diskette zu laden. Nachdem Sie dann mit NEW alle Zeiger wieder richtiggestellt haben, aktivieren Sie das Tool mit SYS 52809 Die Meldung »UNCRASH« erscheint auch diesmal, und der Bildschirm ändert seine Farben. Als kleiner Bonus werden diese Farben auch später nach jedem erscheinen, Sie können also mit POKE 53106, Cursorfarbe POKE 53111, Rahmenfarbe POKE 53116, Hintergrundfarbe Ihre persönlichen Lieblingsfarben einstellen. Nach der Aktivierung schlummert das Hilfsprogramm vor sich hin, bis Sie ihm mitteilen, daß der Computer abgestürzt ist. Tun Sie das, indem Sie die RESTORE-Taste drücken. Oft reicht das aus, um den Computer wieder zum Leben zu erwecken. Manche Probleme sind indes so gravierend, daß »härtere« Maßnahmen vonnöten sind: Der Kaltstart. Bei Uncrash gibt es eine spezielle Tastenkombination, die den Kaltstart auslöst. Halten Sie die Tasten <1>, <2> und gleichzeitig gedrückt und betätigen dann . Diese vier Tasten zusammen gedrückt bewirken erstens, daß Uncrash sich selbst abschaltet. Zum zweiten wird das Basicprogramm im Speicher gelöscht. Der Computer löst einen Reset aus. Um nun sowohl Uncrash wie auch Ihr Programm wiederherzustellen, geben Sie einfach nochmals SYS 52809 ein. Sie werden feststellen, daß das Basicprogramm mitsamt all seinen Variablen und Feldern wieder da ist. Jetzt könnte man zum Beispiel die Variablenwerte auf dem Bildschirm ausgeben und versuchen, damit festzustellen, wodurch der Absturz zustandekam. Möchten Sie das Programm nicht wiederherstellen, definieren Sie nach dem Kaltstart vor dem SYS-Befehl einfach eine beliebige Basic-Variable, etwa X = 1 Dies kann dann erforderlich sein, wenn vermutlich verstellte Basiczeiger den Hänger bewirkt haben. Die Renew-Funktion ist auch allein verfügbar. Dazu geben Sie einfach SYS 52812 ein. Wir wollen nun einmal das Tool einem harten Test unterziehen. Die folgenden POKE-Befehle bewirken bei einem ungesicherten C 64 garantiert einen Absturz, aus dem man so einfach nicht mehr herauskommt. Ist jedoch Uncrash aktiviert, werden einige der fatalen POKEs gar nicht ausgeführt. Ist der Computer dennoch abgestürzt, kommen Sie wie beschrieben ganz einfach aus der Mißlage heraus: POKE 1,51 I/O abschalten POKE 1,48 BASIC abschalten (wird nicht ausgeführt) POKE 115,0 Alle Befehle abschalten POKE 648,0 Tastatur abschalten POKE 770,128 Direktmodus abschalten POKE 772,121 BASIC aufhängen POKE 56322,0 Tastatur abschalten Wichtig ist, daß Sie niemals die RESTORE-Taste während eines Kaltstarts drücken. Das könnte sonst die Ursache für einen Absturz sein, den nicht einmal mehr Uncrash beheben kann. Es gibt noch eine Einschränkung. Uncrash ist leider nicht in der Lage, Abstürze zu beheben, die auftreten, wenn der Prozessor auf illegale OP-Codes trifft. Es gibt keine Möglichkeit, einen solchen Absturz zu verhindern oder rückgängig zu machen. Wenn Sie natürlich einen Reset-Taster Ihr eigen nennen, können Sie diesen betätigen und danach mit SYS 52809 das verlorene Programm zurückholen. Noch ein technischer Hinweis: Das Programm belegt keinerlei Basic-Speicher, sondern arbeitet im Bereich von $CE49 bis $CFFF (52809 bis 53247). Hier befindet sich das Programm mit seinen Variablen ab $CFE2. Es werden keinerlei andere Speicherzellen belegt. Insgesamt bietet Uncrash einen gehörigen Schutz vor Störungen, ohne den Sie nicht mehr das Haus verlassen sollten! Anleitung zum »Quickie-Generator« Dieses (völlig jugendfreie) Programm dient dazu, Daten im Speicher (z.B. Grafikdaten oder Maschinenprogramme) in einen Basic-Data-Lader zu konvertieren. Die fertigen Programme können ganz normal unter Basic mit LOAD geladen und mit RUN gestartet werden, das Merken umständlicher SYS-Befehle entfällt. Dabei werden die Daten nicht numerisch gespeichert, sondern es wurde ein guter Kompromiß getroffen, damit das erzeugte Programm kurz ist, schnell arbeitet und leicht abzutippen ist. Der Generator eignet sich daher dazu, fertige kurze Maschinenprogramme in 20-Zeiler für den gleichnamigen Wettbewerb des 64'er-Magazins zu konvertieren. Aber auch viele andere Anwendungen lassen sich finden. Der »Quickie-Generator« wurde mit sich selbst behandelt. Daher kann er einfach mit LOAD "QUICKIE-GENERATO",8 RUN aktiviert werden. Damit haben Sie die 15-Zeiler-Version dieses Programmes geladen und gestartet. Für die Anwendung in der Praxis eignet sich allerdings besser die Version, die absolut auf Diskette gespeichert ist, sie wird mit LOAD "QUICK-GEN $7000",8,8 NEW geladen. In jedem Fall sollten Sie jetzt die zu konvertierenden Daten in den Speicher laden. Zur Sicherheit geben Sie vorher ein: POKE 56,112:CLR damit der Generator nicht von Daten überschrieben wird. Er belegt den Speicher von 28672 bis 29101 einschließlich. In der Zeropage werden die Zellen 2 bis 4, 181, 182 sowie 247 bis 253 belegt. Der Generator kann jetzt, nachdem Sie sicherheitshalber mit NEW den Basicspeicher leergefegt haben, mit SYS 28672,A,E,S,Z,V aktiviert werden. Dabei gibt A die Anfangsadresse des zu konvertierenden Bereiches an, E die Endadresse (einschließl.), S die Startadresse, mit der das konvertierte Maschinenprogramm gestartet werden kann, Z die erste Zeilennummer und V die Schrittweite der erzeugten Basic-Zeilennummern. Sollen die konvertierten Daten nicht mit SYS gestartet werden, setzen Sie für S irgend einen Wert ein und löschen dann in der zweiten erzeugten Zeile des SYS-Befehl, bevor Sie den »Quickie« speichern. A und müssen folgender Bedingung entsprechen: 0 <= A <= E <= 65535 Während der Konvertierung sehen Sie, wie das Programm am Bildschirm Zeile für Zeile aufgebaut wird. Bitte drücken Sie während dieser Phase auf keinen Fall eine Taste, sondern warten, bis die Konvertierung abgeschlossen ist. Danach erscheint ein Hinweis, wie viele Zeilen erzeugt wurden (wichtig für den 20-Zeiler Wettbewerb: Es dürfen nicht mehr als 20 Zeilen sein) und der Vermerk »OK«. Jetzt steht das erzeugte Programm im Speicher, es kann bei Bedarf weiter bearbeitet oder auf Diskette gespeichert werden. Zum Schluß noch einige kurze Anmerkungen zur internen Funkt