CODING ★ Der Gläsernen CPC ★

Gläsernen CPC (CPC Amstrad International)
★ Ce texte vous est présenté dans sa version originale ★ 
 ★ This text is presented to you in its original version ★ 
 ★ Este texto se presenta en su versión original ★ 
 ★ Dieser Text wird in seiner Originalfassung präsentiert ★ 

Auch diesmal beginnen wir mit einem sehr einfachen Projekt: Der Reparatur der DEC$-Funktion.

Wie Sie wahrscheinlich schon wissen, ist sie im CPC 464 zwar vorgesehen, funktioniert aber, aufgrund eines kleinen Programmfehlers, nicht richtig.

Gedacht war es eigentlich so:

DEC$(< numerischer Ausdruck >, < Formatierungsstring >)

und sollte den numerischen Ausdruck als formatierte Zeichenkette zurückgeben, wobei der Formatierungsstring genau wie bei PRINT USING angegeben wird.

Wenn der CPC nun bei der Berechnung eines Ausdrucks auf eine Basic-Funktion (Code &FF) trifft, so wird routinemäßig überprüft, ob das folgende Argument mit einer offenen Klammer beginnt. Aus unerfindlichen Gründen wird dieserTest zu Beginn der DEC$-Routine aber noch einmal ausgeführt, so daß man beim CPC 464 immer zwei offene Klammem setzen muß, um einen Syntax-Error zu vermeiden.

Da die INCODE-Routine unseres XBASIC-Programms jedoch dafür sorgt, daß die Tabelle der neuen Kommandos und Funktionen bereits vor der internen Standardtabelle
durchsucht wird, stellt es kein Problem dar, die DECS-Funktion mit einem anderen Token zu versehen und neu zu definieren. Zunächst ist wieder eine Eintragung in der BEFTAB-Tabelle fällig:

DM ”DEC”
DB &A4 ;”$”+&80
DB &20 ;neues Token

Hier können Sie die vom CPC 464 nicht benutzten Codes &20 - &39 als Token einsetzen; es können also insgesamt 32 zusätzliche oder geänderte Basic-Funktionen eingebunden werden. Trifft der Interpreter auf einen dieser Codes, so wird die XBASIC-Routine FNBER (Funktionsberechnung) aufgerufen, die den Error abfängt und den CPC dazu bringt, die Adresstabelle FNADR für neue Funktionen zu verwenden. Ähnlich wie bei den Kommandoadressen ist hier die erste Eintragung für das Token &20 zuständig, die zweite Eintragung für den Code &21 usw.

Wir brauchen hier jetzt also nur die Adresse der normalen DEC$-Routine einzutragen, und zwar so, daß der unnötige Test auf ”(” einfach übersprungen wird. Im ROM-Listing findet man zu Beginn der Adresse &F8EA die Sequenz:

CALL &DD37
DB &28

und da haben wir ihn schon, den Übeltäter! Die Routine &DD37 testet, ob das nächste Zeichen im Basic-Programm mit dem auf den CALL folgenden Data-Byte identisch ist; &28 ist der ASCII-Code für ”(". Ist alles in Ordnung, so wird der Ablauf nach dem Prüfbyte fortgesetzt, andernfalls gibt es einen Syntax-Error. Also lassen wir unsere neue DEC$-Funktion einfach 4 Bytes später ein-springen, und damit sieht die Eintragung in der Adresstabelle so aus:

FN ADR DW &F8EE

Assemblieren Sie das Ganze einmal probeweise, und Sie werden sehen: jetzt funktioniert DEC$ genauso, wie es sein sollte!

Und da wir gerade so gut in Form sind, können wir gleich eine weitere Basic-Funktion verbessern. Nichts gegen das Schneider-Basic - aber schauen Sie sich doch einmal an, was man auf dem ZX Spectrum mit der VAL-Funktion veranstalten kann:

10 LET x=PI/4
20 LET a$=”sin(x)”
30 PRINT VAL(a$)

Ohne zu zögern, wird der Computer die Formel berechnen und das Ergebnis 0.707107 anzeigen. Damit ist es zum Beispiel möglich, auf elegante Art Funktionen per INPUT in ein Mathematikprogramm einzugeben. Läßt

man dieses Programm jedoch auf dem CPC laufen, so erscheint eine dumpfe Null auf dem Bildschirm; unser gutes Stück kann nämlich mit VAL leider nur Strings bearbeiten, die aus Ziffern bestehen. Doch das soll sich ändern!

Zunächst wieder die übliche Zeremonie: Tragen Sie in die Befehlstabelle:

DM ”VA”
DB&CC ;”L”+&80 DB &21 ;neues VAL-Token

ein. und in die Adresstabelle für Funktionen muß dann nach der Adresse für DEC$:

DW VAL ;Adr. der VAL-Routine folgen. Und jetzt bitte etwas Konzentration - die neue VAL-Routine hat es nämlich in sich: Wir holen uns die zu dem Funklionsargument gehörenden Stringparameter (Adresse, Länge), wandeln den String in den Interpretercode um und lassen dann die Routine "Ausdruck berechnen” darauf los. Abschließend wird noch getestet, ob wirklich etwas Numerisches dabei herausgekommen ist. Soweit der Rohbau - und hier noch ein paar spezielle Punkte, die zu beachten sind:

— Der Interpreter hat bereits geprüft, ob nach VAL eine offene Klammer folgt. Wir müssen sicher stellen, daß am Ende des Ausdrucks eine Klammer zu steht.
— Falls der Ausdruck einen Leerstring (” ”) ergibt, soll der Wert 0 zurückgegeben werden.
— Für die Umwandlung in den Interpretercode muß der String durch eine 0 als Endmarkierung ergänzt werden. Damit wir aber nicht den Beginn des folgenden Strings damit kaputt schreiben, wird der Inhalt dieser Speicherstelle aufbewahrt und nach der Aktion wieder eingesetzt.

Das Listing ”VAL-Routine” demonstriert. wie diese Ideen in die Praxis umgesetzt werden. Falls noch Unklarheiten auftreten sollten, so wird Ihnen die Übersicht "wichtige Inter-preter-Routinen” weiterhelfen.

So - und zum Abschluß soll noch ein interessantes Projekt vorgestellt werden, das wir Ihnen dann zur weiteren Bearbeitung übergeben möchten. Es handelt sich um eine komfortable Eingaberoutine für den CPC 464. Zwar stellt das Schneider-Basic bereits den INPUT-Befehl zur Verfügung, doch insbesondere der professionelle Programmierer ist damit nicht recht glücklich. Nur zu leicht passiert es, daß eine zu lange Eingabe oder die Fehlermeldung "Redo from Start”, Teile einer sorgfältig geplan-
ten Eingabemaske überschreibt, und außerdem läßt sich der Cursor nicht auf ein bestimmtes Eingabefeld beschränken.

Wie kann man hier Abhilfe schaffen? Die grundlegende Idee ist, eine Basic-Funktion zu definieren, die eine Art Mischung aus INPUT und INKEY$ darstellt und zum Beispiel so ausse-hen könnte:

a$=GETKEY$ (z) wobei z die maximale Länge der Eingabe bestimmt. Natürlich soll dabei auch der Cursor und die eingegebenen Zeichen auf dem Bildschirm erscheinen. Nach ENTER wird die Eingabe in a$ übernommen und der Programmablauf fortgesetzt. Schreiten wir also sofort zur Tat. Die Eintragungen in die Befehls- und Adresstabellen brauchen wir an dieser Stelle wohl nicht mehr zu erläutern - beachten Sie bitte nur, daß es sich hier um eine Basic-Funktion handelt.

Die GETKEY$-Routine baut sich wie folgt auf: Zunächst brauchen wir die maximale Länge als 8-Bit-Wert, dann folgt der obligatorische Test auf Danach werden in einer kleinen Schleife, mit Hilfe der Betriebssystem-Routine KM READ CHAR, solange Zeichen aus dem Tastaturpuffer gelesen, bis er leer ist. Diese Maßnahme verhindert, daß bereits vorher eingegebene Zeichen ungewollt übernommen werden.

Die nächsten Schritte sind leicht zu durchschauen: Der Cursor wird eingeschaltet, und die Routine sammelt Zeichen von der Tastatur ein, bis jemand ENTER (ASCII-Code 13) drückt. Falls die maximale Länge erreicht ist, werden keine weiteren Eingaben akzeptiert. Da noch nicht klar ist, wie lang die Eingabe insgesamt sein wird, werden alle Zeichen zunächst in den CPC-Eingabepuf-fer übernommen.

Interessant wird es in dem Programmteil, der mit dem Label ”READY' ge-kennzeich net ist. Er demonstriert, wie dem Interpreter ein neuer String zur weiteren Bearbeitung übergeben wird.

Zunächst muß er angemeldet werden, indem wir die Länge der Routine &FC19 übergeben. Sie reserviert den nötigen Platz im RAM und gibt uns die Adresse dieses Bereichs im DE-Register zurück. Danach werden die Zeichen dort eingetragen, und die Routine &FBBA sorgt schließlich für die endgültige Übernahme in die interne Stringverwaltung, die übrigens ziemlich kompliziert ist - leider müssen wir uns hier auf die notwendigsten Hinweise beschränken.

Wenn Sie die GETKEY$-Routine auf die übliche Weise in das XBASIC-System einbinden, assemblieren und initialisieren, können Sie sich mit dem folgenden kurzen Programm
von der Funktionsweise überzeugen:

10 CLS: LOCATE 12,12
20 a$=GETKEY$(5)
30 PRINT a$

Störend macht sich nur noch bemerkbar, daß keine Möglichkeit zur Eingabekorrektur besteht Hier ein paar Hinweise dazu, wie sich ein Rückwärtslöschen mit DEL einbauen läßt:

  • Die DEL-Taste ist mit dem ASCII-Code 127 belegt.
  • Das Steuerzeichen CHR$ (8) setzt den Cursor eine Stelle zurück.
  • Das Steuerzeichen CHR$ (16) löscht das Zeichen auf Cursorposition.

... und den Rest möchten wir Ihrer Kreativität überlassen, denn damit sind wir am Ende dieser Folge des "Gläsernen CPC" angelangt. Womöglich werden Sie noch den einen oder anderen Hinweis vermissen; aber es ist leicht einzusehen, daß wir nicht alle Feinheiten eines 16 kByte umfassenden Maschinenprogramms im Rahmen dieses Artikels klären können. Er soll hauptsächlich eine Starthilfe geben - und wenn Sie für eigene Projekte noch weitere Informationen brauchen, so nehmen Sie sich am besten ein kommentiertes ROM-Listing vor und suchen sich einen möglichst ähnlichen Befehl als Beispiel; das ist meistens sehr aufschlußreich.

Und jetzt gibt es noch Zweierlei 2u vermelden - eine gute und eine schlechte Nachricht. Welche wollen Sie zuerst lesen? Okay, also hier die Schlechte, dann haben wir es hinter uns: Diese Folge ist unwiderruflich die letzte Folge des "Gläsernen CPC", da eine neue Serie in Planung ist, die noch etwas Vorbereitungszeit braucht - aber Sie dürfen jetzt schon gespannt sein!

Allerdings möchten wir uns von Ihnen nicht ohne ein gehöriges Feuerwerk verabschieden, und das ist die gute Nachricht: In diesem Heft finden Sie eine hochkarätige Basic-Erweiterung für den CPC 464, in der alle "Highlights” der vergangenen Folgen des "Gläsernen CPC” zusammengefaßt wurden, nebst einigen zusätzlichen Bonbons, die es gewaltig in sich haben - schauen Sie sich das Programm einmal an!

Wenn Sie Lust haben, diese Erweiterung noch um ein paar eigene Ideen zu bereichern - warum nicht? Die nötigen Grundlagen dazu wurden in dieser Folge besprochen, und es bleibt nur noch die Frage, wie Sie an den Assembler-Quellcode für das Programm kommen. Auf einen Abdruck in diesem Heft haben wir verzichtet, da er enorm viel Platz beansprucht. Und abgesehen davon - das Abtippen der circa 26 kByte wäre sicher auch kein reines Vergnügen. Doch wozu gibt es schließlich die DATABOX? In der Kassetten- und Diskettenausgabe zu diesem Heft finden Sie den kommentierten Quellcode in Form von REM-Zeilen. Der CPC International-Assembler (Heft 1/86) kann ihn in dieser Form direkt verarbeiten, ansonsten hilft ein Abspeichern im ASCII-Format und notfalls ein kleines Konvertierungsprogramm, um ihn für andere Assembler aufzubereiten.

Und das wär's dann - wir hoffen, daß Ihnen der "Gläserne CPC" viele Anregungen für eine kreative Arbeit mit Ihrem Schneider-Computer gegeben hat!

Wichtige Interpreterroutinen

1. &DEBB String in Interpretercode wandeln
Einsprung: Stringadresse in HL
Aussprung: Startadresse Puffer (&0040) in HL
Das Stringende muß durch ein Nullbyte markiert sein. DE bleibt unverändert.

2. &CEFB Ausdruck berechnen
Beim Einsprung muß in HL der Basic-Programmzeiger stehen.
Beim Aussprung sind die Speicherstellen ab Adresse &B0C1 in Abhängigkeit vom Ergebnistyp wie folgt belegt:
Integer: (&B0C1)=2, ab &B0C2 steht der 2-Byte Integerwert.
String: (&B0C1)=3, ab &B0C2 steht die 2-Byte Adresse des Stringdescriptors.
Fließkomma: (&B0C1)=5, ab &B0C2 steht der 5-Byte Fließkommawert. Das BC-Registerpaar bleibt unverändert.
Ein ab &B0C1 abgelegtes Ergebnis kann mit folgenen Routinen weiterverarbeitet werden:

3. &FBDA Stringparameter holen
Einsprung: Ergebnis ab &B0C1
Aussprung: Länge des Strings in A,B.
Adresse des Strings in DE
Falls das Ergebnis kein String war, erfolgt ein Fehleraussprung mit "Type Mismatch”. Bei einem Leerstring wird das Zero-Flag gesetzt. HL bleibt unverändert.

4. FF2D Test auf numerisches Ergebnis
Einsprung: Ergebnis ab &B0C1
Aussprung: Integer → Carry=1, Integerwert in HL
Fließkomma → Carry=0, Adresse der Fließkommazahl in HL
String → Fehleraussprung mit "Type Mismatch”.

In den folgenden Routinen ist die Ausdrucksberechnung bereits enthalten. Palls das Ergebnis nicht numerisch ist oder nicht im angeforderten Bereich liegt, wird "Type Mismatch” bzw. "Improper Argument” ausgegeben. Der Programmzeiger muß sich beim Einsprung in HL befinden und wird beim Lesen des Ausdrucks entsprechend weitergesetzt.

5. &CE91 16-Bit-Wert holen
Aussprung: 16-Bit-Wert in DE
BC bleibt unverändert

6. &CE86 Integerwert mit Vorzeichen holen
Aussprung: Integerwert in DE
BC bleibt unverändert

7. &CE67 8-Bit-Wert holen
Aussprung: 8-Bit-Wert in A
BC bleibt unverändert

8. &C1FB 8-Bit-Wert < A holen
Einsprung: Maximalwert+1 in A
Aussprung: 8-Bit-Wert in A
BC,DE bleiben unverändert
Das Ergebnis einer Basic-Funktion muß dem Interpreter für weitere Berechnungen zur Verfügung gestellt werden, indem es ab Adresse &B0C1 abgelegt wird (siehe 2.). Dabei helfen folgende Routinen:

9. &FF0A Akkuinhalt als Integerzahl übernehmen
Einsprung: Zahl in A
Aussprung: Integerzahl in HL BC,DE bleiben unverändert

10. &FF0D Integerzahl in HL übernehmen
Einsprung: Integerwert in HL
F,BC,DE,HL bleiben unverändert.
Falls eine Basic-Funktion einen Text zurückgibt, muß er zunächst im Speicher abgelegt werden:

11. &FC19 Platz für String reservieren
Einsprung: Länge des Strings in A
Aussprung: Adresse des reservierten Bereichs in DE.
AF,BC,HL bleiben unverändert Nachdem der Text dort eingetragen wurde, wird er mit folgender Routine in die interne Verwaltung übernommen:

12. &FBBA String übernehmen
Einsprung: Keine Bedingung
BC bleibt unverändert Fehlermeldungen können über die folgende Einsprungadresse erzeugt werden:

13. &CA94 Error ausgeben
Einsprung: Fehlernummer in E
(Siehe CPC-Bedienungshandbuch, Anhang VIII)
Die Folge:
LD E,2
JP &CA94
gibt zum Beispiel einen Syntax-Error aus. Dabei spielt es keine Rolle, in welchem Zustand sich der Z 80-Stack zum Zeitpunkt des Fehleraussprungs befindet, da er ohnehin neu initialisiert wird.

(M. Uphoff), CPCAI

★ PUBLISHER: CPC Amstrad International
★ YEAR: 1986
★ LANGUAGE:
★ LiCENCE: ???
★ COLLECTION: CPC AMSTRAD INTERNATIONAL 1986
★ AUTHOR: M. Uphoff
 

Page précédente : Gläsernen CPC
★ AMSTRAD CPC ★ DOWNLOAD ★

Type-in/Listing:
» Der  Glaesernen  CPC    (86-06)    (CPC  Amstrad  International)    GERMANDATE: 2021-08-12
DL: 114
TYPE: PDF
SiZE: 177Ko
NOTE: 2 pages/PDFlib v1.6

★ AMSTRAD CPC ★ A voir aussi sur CPCrulez , les sujets suivants pourront vous intéresser...

Lien(s):
» Coding » Gläsernen CPC : Fill-routinen (CPC Amstrad International)
» Coding » CROSSDEV - SDCC - Developper en C par Stephbb75
» Coding » AMSLIVE : La rubriques programmation
» Coding » Etude du FDC par Michel Maignot
» Coding » Cours et initiation du Magazine Micro News
» Coding » Cours et initiation du Fanzine SOS Programmeurs
Je participe au site:
» Pour ce titre nous ne disposons de fichier executable sur CPC (Saisie du listing) , alors si vous avez ça dans vos cartons ou vous désirez usé vos petit doigts boudinés sur votre clavier faites le nous savoir.
» Vous avez des infos personnel ?
» Vous avez remarqué une erreur dans ce texte ?
» Aidez-nous à améliorer cette page : en nous contactant via le forum ou par email.

CPCrulez[Content Management System] v8.7-desktop
Page créée en 027 millisecondes et consultée 519 fois

L'Amstrad CPC est une machine 8 bits à base d'un Z80 à 4MHz. Le premier de la gamme fut le CPC 464 en 1984, équipé d'un lecteur de cassettes intégré il se plaçait en concurrent  du Commodore C64 beaucoup plus compliqué à utiliser et plus cher. Ce fut un réel succès et sorti cette même années le CPC 664 équipé d'un lecteur de disquettes trois pouces intégré. Sa vie fut de courte durée puisqu'en 1985 il fut remplacé par le CPC 6128 qui était plus compact, plus soigné et surtout qui avait 128Ko de RAM au lieu de 64Ko.