SAVE

Aus C64-Wiki
Zur Navigation springenZur Suche springen
SAVE
Syntax: SAVE [<Programmname>] [,<Gerätenummer> [,<Sekundäradresse>]]
Parameter
<Programmname>: Zeichenketten-Ausdruck, der den Programmnamen enthält
<Gerätenummer>: numerischer Ausdruck im Wertebereich von 1 bis 255
<Sekundäradresse>: numerischer Ausdruck im Wertebereich von 0 bis 255
Einordnung
Typ: Anweisung
Kontext: BASIC-Editor
Aufgabe: Programme auf Datenträger speichern
Abkürzung: sA
Token: $94 (148)
Verwandte Befehle
LOAD, VERIFY

Anmerkung: Dieser Artikel beschreibt den BASIC-Befehl SAVE unter BASIC V2 des Commodore 64.


Mit dem BASIC-Befehl SAVE werden BASIC-Programme, die sich im RAM-Speicher des Commodore 64 befinden, auf Datasette oder Diskette oder einen anderen Datenträger wie z.B. eine Festplatte als Programmdateien (PRG) permanent abgespeichert. Der Befehl SAVE kann im Eingabemodus oder - eher unüblich - auch in BASIC-Programmen verwendet werden.

Programmname[Bearbeiten | Quelltext bearbeiten]

Der Programmname muss zwingend beim Abspeichern von Dateien auf Diskette oder Festplatte angegeben werden. Für ihn gelten die in Dateiname angegebenen Eigenschaften. Bei anderen BASIC-Dialekten erfolgt gegebenenfalls eine Fehlermeldung, wenn der Dateiname nicht zwischen der erforderliche Mindest- oder Maximallänge liegt.

Das Abspeichern auf Datasetten kann auch namenlos erfolgen. Sinnvollerweise sollte aber bei jedem Speichervorgang ein Name vergeben werden, das erleichtert nicht nur dem Benutzer das schnellere Auffinden der Dateien. Programme, die auf Datasetten gesichert werden, werden immer doppelt abgespeichert, was eine Fehlerkorrektur beim späteren Einlesen erlaubt.

Auf einem Floppy-Laufwerk führt dies bei einer bereits vorhandenen, gleichnamigen Datei zu einem Fehler. Lediglich die STATUS-Variable weist den Wert -125 (Bit 7, 1 und 0 sind gesetzt) auf. Mancher Floppy-Speeder, wie etwa SpeedDOS, gibt hier dennoch eine Fehlermeldung, z. B. ?NOT OUTPUT FILE ERROR aus. Der Fehlerkanal des Laufwerks quittiert die Aktion mit dem Fehler 63, FILE EXISTS,00,00. Ein Überschreiben einer bestehenden Datei kann aber dennoch mit dem speziellen REPLACE-Format (ein vorangestelltes "@:") im Dateinamen erreicht werden, was allerdings bei diversen Firmware-Versionen fehlerhaft implementiert ist.

Gerätenummer[Bearbeiten | Quelltext bearbeiten]

Mit der Gerätenummer wird bestimmt, auf welches Gerät das Programm gespeichert wird. Fehlt die Gerätenummer, so wird auf das Gerät mit der Nummer 1, die Datasette, zugegriffen. Der Versuch, auf ein Gerät abzuspeichern, das nicht vorhanden bzw. eingeschaltet ist, wird mit der Fehlermeldung ?DEVICE NOT PRESENT ERROR quittiert.

Sekundäradresse[Bearbeiten | Quelltext bearbeiten]

Es gibt bei SAVE mit Gerätenummer >1 keine Wirkung der Sekundäradresse. Sie wird einfach überlesen.
Intern wird die jeweilige Datei vom Laufwerk (beim seriellen Zugriff) immer mit der Sekundäradresse $61/97 geöffnet.

Datasette;

  • Durch die Angabe der Sekundäradresse 0 (oder keiner Sekundäradresse) nach der Gerätenummer 1 wird ein Flag auf Band geschrieben, dass dem LOAD-Befehl angezeigt, dass ein BASIC-Programm (Ladeadresse immer 2049/$0801) folgt.
  • Durch die Angabe der Sekundäradresse 1 nach der Gerätenummer 1 wird ein Flag geschrieben, dass dem LOAD-Befehl angezeigt, dass ein Maschinenspracheprogramm (Ladeadresse aus dem Beginn des Files holen) folgt. Das ist im allgemeinen nur im Zusammenspiel mit dem POKE-Trick (siehe Beispiele) sinnvoll.
  • Durch die Angabe der Sekundäradresse 2 oder 3 nach der Gerätenummer 1 wird eine Marke für BAND-ENDE hinter das Programm geschrieben. Das signalisiert dem Computer, dass nach einem LOAD-Befehl nur bis zu dieser Stelle gesucht werden soll. Wenn ein LOAD-Befehl aufgerufen wird und der Computer entdeckt diese Markierung, bevor das gewünschte Programm gefunden wurde, meldet er ?FILE NOT FOUND ERROR.

Hinweise[Bearbeiten | Quelltext bearbeiten]

Die maximale BASIC-Programmlänge, die SAVE unterstützt, beträgt etwa 39 KByte bzw. 153 Blöcke. Das heißt insbesondere, dass längere, per LOAD geladene Maschinenspracheprogramme, die "unter" das BASIC-ROM ab Adresse $A000 reichen, nicht per LOAD/SAVE zu kopieren sind. Hier kann man auf Laufwerksbefehle oder sonstige Hilfsprogramme zurückgreifen.


Beispiele[Bearbeiten | Quelltext bearbeiten]

Einzeiler[Bearbeiten | Quelltext bearbeiten]

SAVE "DATEINAME",8

Speichert das aktuelle BASIC-Programm auf Diskette in Diskettenlaufwerk mit Gerätenummer 8.

SAVE "@:DATEINAME",8

Speichert das aktuelle BASIC-Programm auf Disketten und überschreibt gegebenenfalls die bereits existierende Datei.
Achtung, Datenverlust insbesondere bei 1541-I möglich! Diverse Floppy-Firmware-Versionen implementieren diesen Befehl fehlerhaft, siehe REPLACE.

SAVE

Namenloses Speichern des aktuellen BASIC-Programms auf Datasette.

SAVE "DATEINAME",1

Speichert das aktuelle BASIC-Programm mit Dateinamen auf Datasette.

SAVE A$,1

Speichert das aktuelle BASIC-Programm mit dem Namen, der in der Variablen A$ festgelegt ist, auf Datasette.

SAVE "DATEINAME",1,2

Speichert das aktuelle BASIC-Programm mit Dateinamen auf Datasette und setzt dahinter eine Marke für BAND-ENDE.

Beliebigen Adressbereich abspeichern[Bearbeiten | Quelltext bearbeiten]

POKE43,0:POKE44,192:POKE45,0:POKE46,208:POKE55,255:POKE56,255:SAVE"MS",8,1

Speicherbereich 49152 bis 53247 ($C000 bis $CFFF) auf Diskette abspeichern - als Einzeiler nutzen!
Erklärung: In den Speicherzellen 43/44 und 45/46 speichert der BASIC-V2-Interpreter normalerweise die Startadresse bzw. Endadresse+1 des aktuellen BASIC-Programms als Low- bzw. High-Byte (siehe Zeropage). Diese Adressen werden hier modifiziert und damit die SAVE-Routine "getäuscht". Damit es keinen ?OUT OF MEMORY ERROR gibt, wird das Ende des BASIC-RAMs auf $FFFF gesetzt (Speicherstelle 55/56). Liegt der abzuspeichernde Speicherbereich unterhalb von 40960 ($A000), werden die Veränderungen in den Speicherstellen 55/56 nicht benötigt. Dieser Trick funktioniert nicht für den Speicherbereich $A000-$BFFF, da SAVE in diesem Bereich immer das BASIC-ROM sieht und speichert, nicht das RAM darunter. Nach dem Abspeichern müssen die Standardwerte der o.g. Speicherstellen wieder zurückgesetzt werden, um normal mit dem C64 weiterarbeiten zu können!
In der Praxis wird kein Programmierer diesen Trick benutzen, da zum Umgang mit und Speichern von beliebigen Speicherbereichen die entsprechenden Funktionen eines Maschinensprachemonitors oder BASIC-Erweiterungen mit BSAVE oder BLOAD wesentlich bequemer sind.

Dieser Trick kann allerdings in reinen BASIC-Programmen benutzt werden, die entsprechenden Speichercode, i.d.R. Maschinenspracheprogramme, generieren, um das Programm entsprechend abzuspeichern, sofern man dafür die Datei nicht direkt per PRINT# anlegen will, was keine POKEs erfordert (siehe Beispiele bei PRINT#).
Wegen der Versetzung des Speicherbereichs muss kurzzeitig im Direktmodus mittels vorgegebene programmierte Tastatureingabe gearbeitet werden:

10 REM ### SPEICHERROUTINE FUER 49152 BIS 53247 ($C000 BIS $CFFF) ###
11 PRINT CHR$(147)"SPEICHERN (J/N)?"
12 GET A$: IF A$="N" THEN END
13 IF A$<>"J" GOTO 12
20 LA=0:HA=192:LE=0:HE=208:NA$="MSV1"
21 AL=PEEK(43):AH=PEEK(44):EL=PEEK(45):EH=PEEK(46):VL=PEEK(55):VH=PEEK(56)
22 PRINTCHR$(147);
23 PRINT"POKE43,"AL":POKE44,"AH":POKE45,"EL":POKE46,"EH;
24 PRINT":POKE55,"VL":POKE56,"VH":GOTO30"
25 PRINT"POKE43,"LA":POKE44,"HA":POKE45,"LE":POKE46,"HE;
26 PRINT":POKE55,255:POKE56,255":PRINT"SAVE"CHR$(34)NA$CHR$(34)",8,1"
27 POKE631,19:POKE632,17:POKE633,17:POKE634,13:POKE635,145:POKE636,145
28 POKE637,13:POKE638,19:POKE639,13
29 POKE 198,9:END
30 REM PROGRAMMAUSFUEHRUNG HIER FORTSETZEN ...

Durch Modifizierung kann es entsprechend angepasst werden!

  • Zeile 11 bis 13: Abfrage, ob gespeichert werden soll.
  • Zeile 20: Variablen für Speichermodifizierung und Dateinamen setzen.
  • Zeile 21: Aktuelle Speicherbereichsgrenzen sichern.
  • Zeile 20 bis 26: Befehle für das modifizierte Abspeichern und Rücksetzen auf das aktuelle BASIC-Programm auf den Schirm schreiben: Auf Schirmzeile 3 ist das Adresssetzen, Schirmzeile 5 das SAVE, Schirmzeile 1 enthält die Adressenwiederherstellung.
  • Zeile 27 bis 29: Programmierte Tastatureingabe erzeugen: Positioniere am Schirm zu Zeile 3, Eingabetaste, rauf zu Zeile 5, Eingabetaste, Home-Position, Eingabetaste (Codes entsprechend den zu den Tasten gehörenden Steuerzeichen)
POKE43, 1 :POKE44, 8 :POKE45, 41 :POKE46
, 10 :POKE55, 0:POKE56, 160 :GOTO30
POKE43, 0 :POKE44, 192 :POKE45, 0 :POKE4
6, 208 :POKE55,255:POKE56,255
SAVE"MSV1",8,1

Nach der obigen initialen Ausgabe, passiert das Abspeichern und endet mit folgender Ausgabe:

POKE43, 1 :POKE44, 8 :POKE45, 41 :POKE46
, 10 :POKE55, 0:POKE56, 160 :GOTO30
POKE43, 0 :POKE44, 192 :POKE45, 0 :POKE4
6, 208 :POKE55,255:POKE56,255
READY.SV1",8,1
READY.
SAVING MSV1
READY.

Der Cursor befindet sich dann in der Zeile mit dem hervorgehobenen "READY."
Bei Zeile 30 wird mit der Ausführung fortgesetzt. Statt dem GOTO30 in Zeile 24 wäre auch die Variante mit RUN möglich, wenn die bisher angelegten Variablen und Felder nicht mehr gebraucht werden.

Speichern im Programm[Bearbeiten | Quelltext bearbeiten]

Das folgende einfache Programm könnte von einer Datasette geladen worden sein und könnte sich unter Programmkontrolle auf Diskette abspeichern lassen.

10 REM INTERESSANTES TOOL VON KASSETTE
20 SAVE "DIESPROGRAMM",8: REM SPEICHERE AUF DISKETTE
30 REM HIER GEHT ES WEITER