Linsen-Kürbis-Aufstrich

Zutaten:

250 g Hokkaidokürbis
1 TL Salz
70 g Teller- oder Berg- Linsen
1 EL Zitronensaft
50 ml Orangensaft
1 EL Currypulver
½ TL Kreuzkümmel
Etwas Salz und Pfeffer zum Würzen

Zubereitung:

Hokkaido-Kürbis samt Schale in kleine Würfel schneiden. In einem Topf mit Wasser und Salz ca. 10 Minuten gar dünsten. Kürbiswürfel mit Hilfe einer Kelle aus dem Wasser seihen. In das Kochwasser die Linsen geben und bei mittlerer Hitze ca. 15 Minuten garkochen. Linsen in einem Sieb abgießen. Kürbis und Linsen in ein hohes Gefäß füllen. Zitronensaft, Orangensaft und Gewürze zugeben und fein pürieren. Mit Salz und Pfeffer abschmecken.

Hält sich ca. 10 Tage im Kühlschrank


Du magst meine Rezepte und kochst sie gerne nach?? Dann freue ich mich über einen kleinen Obolus für meine Gewürze-Kasse. Besten Dank!  🙂

[Übersicht]

Avocado-Hummus

Zutaten:

1 Dose Kichererbsen
1 EL Sesampaste (Tahine)
1 reife Avocado (ca. 120g Fruchtfleisch)
2 Limetten
1 EL gehackter Koriander nach Belieben
Etwas Salz und Pfeffer zum Würzen
2 – 3 EL Wasser

 

Zubereitung:

Kichererbsen auf einem Sieb abtropfen lassen. Avocado halbieren, Stein entfernen und das Fruchtfleisch lösen. Kicherbsen und Avocado in ein hohes Gefäß geben. Limetten auspressen. Saft, Koriander und Sesampaste zugeben und zu einem feinen Mus pürieren. Mit Salz und Pfeffer würzen. Eventuell für eine cremigere Konsistenz 2-3 EL Wasser zufügen.

Hält sich ca. 3 Tage im Kühlschrank


Du magst meine Rezepte und kochst sie gerne nach?? Dann freue ich mich über einen kleinen Obolus für meine Gewürze-Kasse. Besten Dank!  🙂

[Übersicht]

Mediterraner Tomatenaufstrich

Zutaten

100 g  Sonnenblumenkerne
100 g getrocknete Tomaten (in Olivenöl)
2 EL  Tomatenmark
1 EL Hefeflocken
½ TL  Kräuter der Provence
1 – 2 Prisen  Chiliflocken nach Belieben
70 ml Gemüsebrühe

Etwas Salz und Pfeffer zum Würzen

Zubereitung

Die Sonnenblumenkerne mind. 3 Std., am besten aber über Nacht, in einem Gefäß bedeckt mit Wasser quellen lassen. Kerne auf einem Sieb abtropfen lassen und in ein hohes Gefäß (z.B. Rührbecher) geben. Tomaten in kleine Stücke schneiden und zu den Sonnenblumenkernen geben. 2 EL des Öls, Tomatenmark, Hefeflocken sowie die Kräuter zugeben. Mit dem Pürierstab alles fein pürieren Gemüsebrühe nach und nach zufügen. Mit Salz und Pfeffer abschmecken.

Hält sich ca. 10 Tage im Kühlschrank.


Du magst meine Rezepte und kochst sie gerne nach?? Dann freue ich mich über einen kleinen Obolus für meine Gewürze-Kasse. Besten Dank!  🙂

[Übersicht]

Fasten-Gemüsebrühe

Rezept für Fastenbrühe nach Buchinger

  • Die Suppe sollte komplett ohne Salz gewürzt werden.
  • Keine Gemüsebrühwürfel verwenden, da sie Salz und Natriumglutamat erhalten können.
  • Die Basisbrühe immer selbst aus Gemüse in Bio-Qualität auskochen.

Die Brühe kannst du auf Vorrat herstellen und in Schraubgläsern oder Saftflaschen aus Glas abfüllen. Im Kühlschrank hält sich die Gemüsebrühe bis zu 1 Woche frisch. Folgende Zutaten werden für die Brühe benötigt:

  • 3 Liter Wasser
  • frische oder getrocknete Kräuter wie Thymian, Rosmarin, Salbei, Liebstöckel
  • ½ Teelöffel Kümmel
  • ½ Teelöffel Nelken
  • ½ Teelöffel Wacholderbeeren
  • 2 Lorbeerblätter
  • 1 Zwiebel, gehackt
  • 2-3 Knoblauchzehen
  • 600 g Gemüse wie Lauch, Kartoffeln, Möhren, Pastinaken, Fenchel, Sellerie oder Zucchini

Zubereitung

Das Gemüse fein schneiden oder mit einer Küchenmaschine raffeln, mit den Gewürzen und Kräutern ins Wasser geben, zum Kochen bringen und ca. 30 Minuten leise köcheln lassen. Die Gemüsezutaten der Brühe kannst du gerne nach Lust und Laune variieren. Ausschalten und für 4 Stunden ziehen lassen.

Nun die Brühe abseihen und das Gemüse beiseite stellen. Gemüsebrühe in vorbereitete Schraubgläser füllen, heiß verschließen und auf dem Deckel stehend abkühlen lassen.

Abgeseihte Zutaten nicht wegwerfen – aus dem Gemüse lässt sich leicht ein leckerer Brotaufstrich herstellen!

Um den Geschmack etwas zu verändern, kannst du auch mal eine Prise geriebene Muskatnuss, Currymischung, Tomatenmark oder auch einen Spritzer Orangen- oder Zitronensaft hinzufügen.

Die Fastengemüsebrühe enthält Vitamine, Mineralien und Spurenelemente. Diese unterstützen den fastenden Körper, der sich von Schadstoffen, besonders Säuren, befreit. Sie führt ihm für diesen Vorgang wichtige basische Stoffe zu, die die Säuren abpuffern.

BlitzBasic mit AmiBlitz3 - ein Tutorial für Amiga-Programmierer www.mbergmann-sh.de

BlitzBasic für Einsteiger – Grundrechenarten und eigene Funktionen

Rechner sind zum Rechnen da – das ist ihr Kerngeschäft und da bildet der Amiga keine Ausnahme. BlitzBasic/AmiBlitz3 bringt bereits eine große Anzahl an mathematischen Bibliotheksfunktionen für alle Anwendungsfälle mit, die sich bei Bedarf jederzeit um selbstgeschriebene, eigene Funktionen erweitern lassen – und darum geht es in diesem Teil unseres Tutorials.

Die Grundrechenarten

Um einfache Berechnungen anzustellen, bedarf es keiner umfangreichen Mathe-Bibliotheken und -funktionen. BlitzBasic beherrscht ohne weiteren Aufwand Addition (+), Subtraktion (-), Multiplikation (*) und Division (/). Um eine Berechnung durchzuführen genügt es, zwei Zahlen mit dem entsprechenden Operator zu verknüpfen und das Ergebnis einer Variablen zuzuweisen. Beispiele:

summe.w = 47 + 11     ; Addition
summe.w = 50 - 8      ; Subtraktion
produkt.w = 33 * 3    ; Multiplikation
quotient.q = 42 / 3   ; Division
quotient.q = 42 / 0   ; Division durch Null nicht erlaubt!

 

Priorität von Rechenoperationen

Tauchen in einem Term (einer Anweisung) unterschiedliche Rechenoperationen auf, so muss man die Priorität der einzelnen Operationen beachten. Die Hierarchie ist wie folgt aufgebaut:

  1. Potenzierung
  2. Multiplikation und Division („Punktrechnung“)
  3. Addition und Subtraktion („Strichrechnung“)

Beachtet man diese Rangordnung nicht, so kann es zu unerwarteten Seiteneffekten aufgrund falscher Ergebnisse kommen. Beispiel:

meinErgebnis.w = 5 + 5 * 3

Erwartetes Ergebnis: 30
Tatsächliches Ergebnis: 20

Überrascht? Wir haben in diesem Beispiel die Faustregel „Punkt- vor Strichrechnung“ nicht beachtet und denken uns: 5 + 5 = 10, 10 * 3 = 30. Der Computer macht alles richtig und rechnet stattdessen: 5 * 3 = 15, 5 + 15 = 20.

Klammerung von Termen

Um die Priorität einer verketteten Berechnung zu ändern, setzt man runde Klammern entsprechend der gewünschten Priorisierung:

meinErgebnis.w = (5 + 5)* 3 

Erwartetes Ergebnis: 20 
Tatsächliches Ergebnis: 20

Jetzt werden tatsächlich 5 + 5 addiert, bevor die Multiplikation durchgeführt wird.

Die Wahl eines „passenden“ Datentyps

Wenn man das Ergebnis einer Berechnung einer Variablen zuweisen möchte, dann muss man sich bereits im Vorfeld Gedanken darüber machen, welche Art von Zahlen und Zahlengrößen dabei anfallen können. Die Zahl muss ja schließlich auch in die Variable hinein passen. Werden nur sehr kleine Zahlen als Ergebnis erwartet? Kann ich mich auf Ganzzahlen beschränken, oder sind Fließkommazahlen zu erwarten? Wie groß kann ein Ergebnis ausfallen, falls sich die Werte der Berechnung ändern?

Der Datentyp einer Variable bestimmt, ob eine abzulegende Zahl fehlerfrei dargestellt werden kann (siehe Anhang A) oder nicht. Ausschlaggebend ist dabei sein Wertebereich. Ist er zu klein bemessen, dann könnte die Variable überlaufen und falsche Resultate liefern. Bemisst man ihn zu groß, so verschwendet man Ressourcen. Weist man eine Fließkommazahl einem Ganzzahlen-Typen zu, dann gehen die Nachkommastellen verloren, was wiederum zu Fehlern im Programm führen kann. Gerade bei der Division zweier Zahlen muss z.B. regelmäßig mit einem Ergebnis in Form einer Fließkommazahl gerechnet werden. Du siehst, es erfordert Hirnschmalz. Der Leitsatz zur Wahl eines passenden Datentyps könnte etwa so lauten: „So viel wie nötig, aber so wenig wie möglich“.

Das Listing „calc1.ab3“ führt die Grundrechenarten vor und zeigt kleine Unterschiede zwischen Berechnungen mit Ganzzahlen und solchen mit Fließkommazahlen auf:

; -----------------------
; File:calc1.ab3
; Grundrechenarten
; Version: 1.0
; -----------------------
OPTIMIZE 1 ; Optimierung für Amiga mit Turbokarte/A1200
SYNTAX 1   ; strenge Syntaxprüfung

; Amiga Version String und das Compilerdatum
!version {"calc1 1.0 (\\__DATE_GER__)"}

; Variablen deklarieren
DEFTYPE .l l_zahl1,l_zahl2, l_result   ; Datentyp: Long
DEFTYPE .f f_zahl1, f_zahl2, f_result  ; Datentyp: Float

; Variablen initialisieren
l_zahl1 = 3201
l_zahl2 = 500
f_zahl1 = 3201.5
f_zahl2 = 500.2

; Addition
l_result = l_zahl1 + l_zahl2
f_result = l_zahl1 + l_zahl2
NPrint "Addition (integer) Ergebnis          : " + Str$(l_result)
NPrint "Addition (float) Ergebnis            : " + Str$(f_result)
NPrint "Addition (float-Werte) Ergebnis      : " + Str$(f_zahl1 + f_zahl2)
NPrint ""

; Subtraktion
l_result = l_zahl1 - l_zahl2
f_result = l_zahl1 - l_zahl2
NPrint "Subtraktion (integer) Ergebnis       : " + Str$(l_result)
NPrint "Subtraktion (float) Ergebnis         : " + Str$(f_result)
NPrint "Subtraktion (float-Werte) Ergebnis   : " + Str$(f_zahl1 - f_zahl2)
NPrint ""

; Multiplikation
l_result = l_zahl1 * l_zahl2
f_result = l_zahl1 * l_zahl2
NPrint "Multiplikation (integer) Ergebnis    : " + Str$(l_result)
NPrint "Multiplikation (float) Ergebnis      : " + Str$(f_result)
NPrint "Multiplikation (float-Werte) Ergebnis: " + Str$(f_zahl1 * f_zahl2)
NPrint ""

; Multiplikation
l_result = l_zahl1 / l_zahl2
f_result = l_zahl1 / l_zahl2
NPrint "Division (integer) Ergebnis          : " + Str$(l_result)
NPrint "Division (float) Ergebnis            : " + Str$(f_result)
NPrint "Division (float-Werte) Ergebnis      : " + Str$(f_zahl1 / f_zahl2)
NPrint ""

End

Ausgabe:

Addition (integer) Ergebnis : 3701
Addition (float) Ergebnis : 3701
Addition (float-Werte) Ergebnis : 3701.699

Subtraktion (integer) Ergebnis : 2701
Subtraktion (float) Ergebnis : 2701
Subtraktion (float-Werte) Ergebnis : 2701.3

Multiplikation (integer) Ergebnis : 1600500
Multiplikation (float) Ergebnis : 1600500
Multiplikation (float-Werte) Ergebnis: 1601390

Division (integer) Ergebnis : 6
Division (float) Ergebnis : 6.401999
Division (float-Werte) Ergebnis : 6.400439

Programmanalyse:

  • in den Zeilen 13 bis 20 deklarieren und initialisieren wir, wie gewohnt, die Variablen des Programms. Verwendet werden Ganzzahlenwerte (Integerwerte) vom Typ Long und große Fließkommawerte vom Typ Float.
  • die Zeilen 23 bis 28 führen Additionen durch und geben anschließend deren Summen aus. Dabei addiert die Berechnung in Zeile 24 zwei Ganzzahlen und weist die Summe einer Float-Variablen zu. Beachte: Die Ausgabe zeigt trotzdem lediglich eine Ganzzahl an.
  • die Ausgabe in Zeile 27 erfolgt mit einer direkt an NPrint übergebenen, mittels Str$ in einen String umgewandelten Berechnung mit zwei Fließkommazahlen. Die Ausgabe zeigt hier, wie erwartet, eine Fließkommazahl als Ergebnis an.
  • Analog zum Gesagten erfolgt in den Zeilen 31 bis 38 die Subtraktion, in den Zeilen 39 bis 44 die Multiplikation und in den Zeilen 46 bis 52 die Division.

Erinnerung: Print und NPrint erwarten bei der Verwendung von aus Zahlen und Strings zusammengesetzten Parametern, dass die Zahlen in einem zusammengesetzten String ebenfalls als String vorliegen! Darum wandeln wir solche Zahlen per Str$ um.

Anstatt des „großen“ Typs Float hätten wir hier auch den kleineren Typ Quick verwenden können. Beide Typen unterscheiden sich allerdings sowohl in ihrem Wertebereich, als auch in ihrer Genauigkeit bezüglich ihrer Anzahl an Nachkommastellen. Das kurze Listing „floatcalc.ab3“ veranschaulicht die Unterschiede beider Datentypen:

; --------------------------
; File:floatcalc.ab3
; Division von Float-Zahlen
; Version: 1.0
; --------------------------
OPTIMIZE 1
SYNTAX 1

; Amiga Version String und das Compilerdatum
!version {"floatcalc 1.0 (\\__DATE_GER__)"}

; Variablen deklarieren
DEFTYPE .q q_zahl1,q_zahl2, q_result   ; Datentyp: Quick
DEFTYPE .f f_zahl1, f_zahl2, f_result  ; Datentyp: Float

; Variablen initialisieren
q_zahl1 = 3201.5123456
q_zahl2 =  500.7123478
f_zahl1 = 3201.5123456
f_zahl2 =  500.7123456

; Division
q_result = q_zahl1 / q_zahl2
f_result = f_zahl1 / f_zahl2
NPrint "Division (quick) Ergebnis: " + Str$(q_result)
NPrint "Division (float) Ergebnis: " + Str$(f_result)
NPrint ""

End

 

Ausgabe:

Division (quick) Ergebnis: 6.3939
Division (float) Ergebnis: 6.393915

Zum Ablauf dieses Programms gibt es nicht viel zu sagen. Wir initialisieren die Variablen jeweils mit den gleichen Inhalten. Quick liefert als Ergebnis der Berechnung eine Zahl mit 4 Nachkommastellen, bei Float sind es 6.

Aufgaben:

  1. Versuche spaßeshalber einmal, alle Variablen mit zusätzlichen Nachkommastellen zu initialisieren und compiliere das Programm erneut. Beachte die Fehlermeldung des Compilers.
  2. Initialisiere eine Quick-Variable mit dem Wert 37900001.5123456 und compiliere das Programm. Was sagt der Compiler?
  3. Schreibe ein Programm mit einer Quick-Variablen und weise dieser den Wert 32767.1 zu. Gib diesen Wert aus. Addiere nun 1.0 zum Wert und gib die Variable erneut aus. Was passiert?

Modulo – der Rest einer Division

Modulo ist eine mathematische Operation, die den Rest einer ganzzahligen Division bezeichnet. Programmierer verwenden diese Operation z.B. zur Prüfung, ob eine ganzzahligen Division einen Nachkommaanteil besitzt. Ist dies der Fall, so liefert die Operation den Wert 1 zurück, andernfalls 0. BlitzBasic verwendet den Befehl MOD, um die Operation durchzuführen. Beispiele:

rest.w = 4 MOD 3  ; Ergebnis: 1, es gibt einen Rest
rest.w = 4 MOD 2  ; Ergebnis: 0, es gibt keinen Rest

Das Listing „modulus.ab3“ demonstriert die Verwendung:

; -----------------------
; File: modulus.ab3
; Rest einer Division
; Version: 1.0
; -----------------------
OPTIMIZE 1
SYNTAX 1

; Amiga Version String und das Compilerdatum
!version {"modulus 1.0 (\\__DATE_GER__)"}

DEFTYPE .w modulus, zahl1, zahl2

; Werte eingeben
NPrint "Rest einer Division testen"
NPrint "Gib zwei Ganzzahlen ein!"
Print "Erste Zahl:  "
zahl1 = Edit(10)
Print "Zweite Zahl: "
zahl2 = Edit(10)
NPrint""

; Modulus-Operation
modulus = zahl1 MOD zahl2

; Auswertung
If (modulus = 0)
  NPrint "Die Division hat keinen Rest."
Else
  NPrint "Die Division weist einen Rest auf."
EndIf

End

Programmanalyse:

  • in den Zeilen 16 bis 20 fragen wir den Benutzer nach der Eingabe von zwei Ganzzahlen und lesen diese jeweils in den Zeilen 18 und 20 ein. Dazu verwenden wir die Funktion Edit(), das Gegenstück für Zahlen zu Edit$() (Letzteres haben wir bereits in anderen Programmen verwendet, um Zeichenketten einzulesen). Der Parameter in Klammern gibt dabei die Anzahl zulässiger Ziffern an – hier sind es 10.
  • Zeile 24 führt die Modulus-Operation aus und weist deren Resultat der Variablen modulus zu.
  • in den Zeilen 27 bis 31 untersuchen wir mit einer if…else…endif-Abfrage, ob ein Rest vorliegt und geben eine entsprechende Meldung aus. WENN der Wert der Variablen modulus Null beträgt, so gibt es keinen Rest – ANDERNFALLS existiert ein Rest (später mehr zu vergleichenden Abfragen).

Potenzierung

Eine Potenz  ist das Ergebnis des Potenzierens (der Exponentiation), das wie das Multiplizieren seinem Ursprung nach eine abkürzende Schreibweise für eine wiederholte mathematische Rechenoperation ist. Wie beim Multiplizieren ein Summand wiederholt addiert wird, so wird beim Potenzieren ein Faktor wiederholt multipliziert. Dabei heißt die Zahl, die zu multiplizieren ist, Basis. Wie oft diese Basis als Faktor auftritt, wird durch den Exponenten angegeben. Man schreibt:

BlitzBasic verwendet zur Potenzierung das Zeichen „^“. Auch diese Rechenoperation schauen wir uns an einem Beispiel an – „power.ab3“:

; -----------------------
; File: power.ab3
; Potenzieren
; Version: 1.0
; -----------------------
OPTIMIZE 1
SYNTAX 1

; Amiga Version String und das Compilerdatum
!version {"power 1.0 (\\__DATE_GER__)"}

DEFTYPE .w potenz, basis, faktor

; Werte eingeben
NPrint "Potenzieren:"
NPrint "Gib zwei Ganzzahlen ein!"
Print "Basis:  "
basis = Edit(5)
Print "Faktor: "
faktor = Edit(5)
NPrint""

; Potenz-Operation
potenz = basis ^ faktor

; Ausgabe
NPrint "Die Potenz von " + Str$(basis) + " hoch " + Str$(faktor) + " ist " + Str$(potenz)

End

Ausgabe:

Potenzieren:
Gib zwei Ganzzahlen ein!
Basis: 2 
Faktor: 16 

Die Potenz von 2 hoch 16 ist 65536

Zum Programmaufbau gibt es nicht viel zu sagen. Den Datentyp der Variablen haben wir mit Long Word (.l) angegeben – Word (.w) wäre zu klein, da beim Potenzieren sehr große Zahlen entstehen können. Den Ablauf dieses Programms solltest du inzwischen ohne weitere Erläuterung verstehen können.

 

Prozeduren, Statements und Funktionen

Eine Prozedur (Procedure) ist eine Möglichkeit, Routinen (wie z.B. wiederkehrende Berechnungen) in eigenständige Teile des Programms zu „verpacken“. Sobald eine Routine in eine Prozedur verpackt ist, kann sie von deinem Hauptcode aus aufgerufen werden. Parameter können übergeben werden, und ein optionaler Wert wird an den Hauptcode zurückgegeben. Da eine Prozedur ihren eigenen lokalen Variablenbereich enthält, kannst du sicher sein, dass keine deiner Haupt- oder globalen Variablen durch den Aufruf der Prozedur verändert wird. Diese Eigenschaft bedeutet, dass Prozeduren sehr portabel sind, d.h. sie können in andere Programme portiert werden, ohne dass es zu Konflikten mit dort verwendeten Variablennamen gibt.

Einfache Prozeduren geben keine Werte an ihren Aufrufer zurück und werden als Statements bezeichnet. Prozeduren, die Werte zurück liefern, heißen unter BlitzBasic Funktionen. Procedure ist also lediglich der Oberbegriff für Beides.

Funktionen und Statements unter BlitzBasic haben die folgenden Eigenschaften:

  • Die Anzahl der Parameter ist auf 6 begrenzt.
  • Gosub und Goto zu Labels außerhalb des Codes einer Prozedur sind streng verboten.
  •  Alle lokalen Variablen, die innerhalb einer Prozedur verwendet werden, werden bei jedem Aufruf neu initialisiert. Ihre Werte sind also nur so lange gültig, wie die Prozedur läuft.

Statements

Ein Statement definiert man nach folgender Schablone:

Statement Name{Parameter}
   ... Anweisungen ...
End Statement

Der Name des Statements ist frei wählbar. Einem Statement können innerhalb der geschweiften Klammern bis zu 6 Parameter mitgegeben werden, die Statement-intern weiterverarbeitet werden. Einem Statement muss nicht zwingend ein Parameter übergeben werden – in dem Fall bleiben die geschweiften Klammern leer. Variablen innerhalb eines Statements sind stets lokal, d.h. nur innerhalb des Statements gültig – es sei denn, man macht sie mit dem Schlüsselwort SHARED allgemein zugänglich.

Das Listing „statement.ab3“ verwendet ein Statement, um den Fakultätsfaktor einer Zahl fünfmal auszugeben.
Beachte, dass bei Verwendung der strengen Syntaxprüfung mittels OPTION 1 sämtliche Variablen im Vorfeld deklariert werden müssen! Außerdem müssen sie in diesem Fall mit ihrem vollen Namen inklusive der Extension (hier: .l) angesprochen werden.

; ----------------------------
; File: statement.ab3
; Funktion ohne Rueckgabewert
; Version: 1.0
; ----------------------------
OPTIMIZE 1
SYNTAX 1

; Amiga Version String und das Compilerdatum
!version {"statement 1.0 (\\__DATE_GER__)"}

DEFTYPE .l k             ; globale Variable: k

; ein Statement definieren
Statement fact{n.l}
  DEFTYPE .l a, k        ; Lokale Variablen: a, k

  a.l = 1
  For k.l = 2 To n.l
    a.l = a.l * k.l
  Next

  NPrint a
End Statement

; Hauptteil
For k.l = 1 To 5
  fact{k.l}      ; Aufruf des Statements
Next

End

Ausgabe:

1
2
6
24
120

Programmanalyse:

  • Zeile 12 deklariert die im Hauptteil (außerhalb des Statements) verwendete globale Variable als Long Word.
  • die Zeilen 15 bis 24 definieren das Statement fact{n.l}.
  • Zeile 15 ist der Kopf des Statements, bestehend aus dem Schlüsselwort Statement, dem Namen (fact) und der Parameterliste in geschweiften Klammern. Sie enthält nur einen Parameter: n. Beachte, dass aufgrund der strengen Syntaxprüfung der Parameter n mit einem Datentyp deklariert werden muss.
  • die Zeilen 16 bis 23 sind der Rumpf des Statements, der in Zeile 24 mit der Anweisung End Statement abgeschlossen wird.
  • Zeile 16 deklariert die lokalen Variablen des Statements als Long Word.
  • Zeile 18 initialisiert die lokale Variable a.l mit dem Wert 1.
  • in den Zeilen 19 bis 21 wird mittels einer for…next-Schleife (später mehr dazu!) der Wert der Variablen a.l mit sich selbst multipliziert.
  • der berechnete Wert wird in Zeile 23 ausgegeben.
  • Auch im Hauptteil ab Zeile 27 wird eine for…next-Schleife verwendet. Sie läuft fünf mal und ruft bei jedem Durchlauf einmal das Statement fact{n.l} auf. Würde man also den Zähler der Schleife erhöhen, so würden dementsprechend mehr Zahlen ausgegeben werden. Versuche es spaßeshalber: Ersetze die Zahl 5 in Zeile 27 mit der Zahl 10 und compiliere und starte das Programm erneut.
    Anmerkung: Das geht nur bis maximal zur Zahl 16 gut – ab 17 läuft die Variable über!

Funktionen

Im Gegensatz zu Statements liefern Funktionen über die Anweisung Function Return einen weiter verarbeitbaren Wert an den Aufrufer zurück. Eine Funktion definiert man nach folgender Schablone:

Funktion Name{Parameter}    
   ... Anweisungen ... 
   Function Return Variable  ; Rückgabewert
End Funktion

Unser Beispiel für ein Statement lässt sich ohne Aufwand auch als Funktion realisieren. Dabei geben wir die berechnete Zahl nicht gleich direkt aus, sondern übergeben sie dem Aufrufer im Hauptteil des Programms. Das Listing „function.ab3“ zeigt, wie es funktioniert:

; ----------------------------
; File: function.ab3
; Funktion mit Rueckgabewert
; Version: 1.0
; ----------------------------
OPTIMIZE 1
SYNTAX 1

; Amiga Version String und das Compilerdatum
!version {"function 1.0 (\\__DATE_GER__)"}

DEFTYPE .l k       ;Globale Variablen deklarieren

; Funktion definieren
Function fact{n.l}
  DEFTYPE .l a, k  ; Lokale Variablen deklarieren

  a.l = 1
  For k.l = 2 To n.l
    a.l = a.l * k.l
  Next

  Function Return a.l ; Rueckgabewert
End Function

; Hauptteil
For k.l = 1 To 5
  NPrint fact{k.l}  ; Rueckgabewert drucken
Next

End

Die Programmlogik ist nahezu identisch zum vorherigen Listing – allerdings geben wir nun in Zeile 23 den berechneten Wert mit Function Return an den Aufrufer (NPrint) in Zeile 28 zurück.

Zugriff auf globale Variablen

Manchmal ist es notwendig, dass eine Prozedur auf eine oder mehrere globale Variablen eines Programms zugreifen kann. Zu diesem Zweck erlaubt der SHARED-Befehl, bestimmte Variablen innerhalb einer Prozedur als globale Variablen zu behandelt. Dazu ein schnelles Beispiel:

Statement example{}
  SHARED k
  NPrint k
End Statement
For k=1 To 5
  example{}
Next

Per SHARED-Befehl teilst du dem Compiler mit, dass die Prozedur die globale Variable k verwenden soll, anstatt eine lokale Variable k zu erzeugen. Versuche dasselbe Programm ohne den SHARED-Befehl: Jetzt ist k innerhalb der Prozedur eine lokale Variable und wird daher jedes Mal 0 sein, wenn die Prozedur aufgerufen wird.

Rekursion

Der von den lokalen Variablen einer Prozedur verwendete Speicher ist nicht nur für die eigentliche Prozedur, sondern für jeden Aufruf der Prozedur reserviert. Jedes Mal, wenn eine Prozedur aufgerufen wird, wird ein neuer Speicherblock zugewiesen und erst nach Beendigung der Prozedur wieder freigegeben. Dies hat zur Folge, dass eine Prozedur sich selbst aufrufen kann, ohne ihre eigenen lokalen Variablen zu beschädigen. Das ermöglicht ein Phänomen, das als Rekursion bekannt ist. Hier ist eine neue Version der faktoriellen Funktion, die Rekursion verwendet:

; ----------------------------
; File: recursion.ab3
; rekursiver Funktionsaufruf
; Version: 1.0
; ----------------------------
OPTIMIZE 1
SYNTAX 1

; Amiga Version String und das Compilerdatum
!version {"recursion 1.0 (\\__DATE_GER__)"}

DEFTYPE .l n       ;Globale Variablen deklarieren

; Funktion definieren
Function fact{n.l}
  If n.l > 2 Then n.l = n.l * fact{n.l - 1} ; Rekursiver Aufruf
  Function Return n.l ; Rueckgabewert
End Function

; Hauptteil
For n.l = 1 To 5
  NPrint fact{n.l}  ; Rueckgabewert drucken
Next

End

Dieses Beispiel beruht auf dem Konzept, dass die Berechnung der Fakultät einer Zahl eigentlich die Zahl, multipliziert mit dem Faktor von Eins weniger als die Zahl darstellt (Zahl – 1, vergl. Zeile 16).

Zusammenfassung

In diesem Teil des Tutorials haben wir gelernt

  • wie man unter BlitzBasic die Grundrechenarten und den Modulo-Operator verwendet und wie man Zahlen potenziert.
  • wie die Hierarchie der Rechenoperationen aufgebaut ist und wie man sie durch Klammerung verändern kann.
  • auf was es bei der Wahl des Datentyps für eine Variable ankommt.
  • wie man einen numerischen Wert mittels des Edit()-Befehls einliest.
  • das bei Zuweisung einer Fließkommavariablen an eine Ganzzahlvariable der Nachkommaanteil verloren geht.
  • das Prozeduren ein Oberbegriff für Statements und Funktionen sind.
  • das man Prozeduren maximal 6 Parameter übergeben kann.
  • das Statements im Gegensatz zu Funktionen keinen Rückgabewert liefern.
  • das Variablen innerhalb von Prozeduren lokaler Natur sind und nur innerhalb der jeweiligen Prozedur Gültigkeit besitzen.
  • Das lokale Variablen für andere Prozeduren und das Hauptprogramm nicht sichtbar sind, mittels des Schlüsselwortes SHARED aber sichtbar gemacht werden können.
  • das Prozeduren sich selbst rekursiv aufrufen können, wobei die Werte lokaler Variablen erhalten bleiben.

Ausblick

Im kommenden Teil des Tutorials werden wir uns Kontrollstrukturen zur Fallunterscheidung und Verzweigung, Wiederholungsschleifen, Wahrheitswerte und Vergleichsoperatoren näher betrachten.


[Zurück zur Übersicht] | [zurück] | [vowärts]

Kohlrabi-Cremesuppe - Rezept www.mbergmann-sh.de

Kohlrabi-Cremesuppe

…mit Knoblauch-Kräuter-Croutons

Zutaten:

1 große Zwiebel
3 Zehen Knoblauch
600 g Kohlrabi
400 g Kartoffeln
1 EL Butter
800 ml Gemüsebrühe (am besten selbst gekocht, alternativ Bio-Instantbrühe)
1 Bd. frische Petersilie oder Schnittlauch
100 g Sahne (30 % Fett)
1 EL Zitronensaft
2 Prisen Muskatnuss /frisch gerieben)
1 TL provenzalische Kräuter
Pfeffer, Salz aus der Mühle

1 altbackenes Brötchen
2 EL Olivenöl

Zubereitung

  1. Zwiebel und Knoblauch abziehen und fein würfeln. Kohlrabi waschen, schälen und in ca. 2 cm große Stücke schneiden. Kartoffeln waschen, schälen und ebenfalls in 2 cm große Stücke schneiden.
  2. Butter in einem Topf zerlassen und Zwiebeln, Knoblauch, Kartoffeln und Kohlrabi darin rundherum bei kleiner Hitze anbraten. Mit der Gemüsebrühe ablöschen, einmal aufkochen lassen und bei mittlerer Hitze zugedeckt etwa 15-20 Minuten köcheln lassen. In der Zwischenzeit Kräuter abbrausen, trockenschütteln und fein hacken.
  3. Nach der Garzeit das Gemüse mit einem Pürierstab fein pürieren. Die Sahne unterrühren und die Suppe mit Zitronensaft, Muskatnuss, Kräutern, Pfeffer und etwas Meersalz abschmecken.
  4. Für die Croutons das Brötchen in Würfel schneiden, mit Kräutern bestreuen und 1 EL Öl darüber träufeln.
  5. In der gusseisernen Pfanne 1 EL Öl heiß werden lassen, dann die Brötchenwürfel beigeben und bei reduzierter Hitze von allen Seiten knusprig braun braten.
  6. Suppe in vorgewärmten Tellern anrichten, mit den Croutons und etwas gehackter Petersilie bestreuen, sofort servieren.

Guten Appetit!


Du findest meine Rezepte lecker und verwendest sie gern? Dann freue ich mich über einen kleinen Obolus für meine Gewürze-Kasse. Besten Dank!  🙂

[Zurück zur Übersicht]

BlitzBasic mit AmiBlitz3 - ein Tutorial für Amiga-Programmierer www.mbergmann-sh.de

BlitzBasic für Einsteiger – Variablen, Konstanten und Datentypen

Wer in den frühen Jahren der IT z.B. auf dem Commodore 64 in BASIC programmiert hat, der brauchte sich keine Gedanken um die Interna von Variablen und Konstanten zu machen. Es gab Variablen für Strings und Zahlen – und damit basta. Das hat sich mit modernen BASIC-Dialekten aus guten Gründen drastisch geändert.

Variablen belegen per se ein Stück zusammenhängenden Arbeitsspeicher (RAM) pro Stück. Aus heutiger Sicht ist es deshalb nicht effizient, für jede Variable eine gleich große Menge Arbeitsspeicher zu vergeuden. Manchmal möchte man nur mit sehr kleinen Zahlen arbeiten, ein andermal  mit Fließkommazahlen und wieder ein anderes Mal benötigt man Platz für sehr große Zeichenketten (Strings). Das ist der Punkt, an dem Datentypen ins Spiel kommen.

Wenn man für eine Variable immer nur so viel Speicher reserviert, wie tatsächlich gebraucht wird, dann verschwendet man weniger knappe Ressourcen (RAM) – aber es ergibt sich daraus noch ein weiterer Vorteil: Kleine Ganzzahlen werden vom Computer schneller verarbeitet, als z.B. große Fließkommazahlen.

Es ist auch unter BlitzBasic/AmiBlitz3 möglich, beim Schreiben von Programmen völlig darauf zu verzichten, sich mit Datentypen auseinanderzusetzen. Der Compiler geht dann intern einfach davon aus, dass er den Default-Datentyp verwenden soll. Unter AmiBlitz3 ist das QUICK (vergl. Anhang A – primitive Datentypen). Dieser Datentyp verbraucht entsprechend viel Ressourcen, da er ja groß genug für alle anfallenden Arten von Zahlen sein muss. Effizienter ist es da natürlich, sich die benötigte Größe der verwendeten Variablen vorher zu überlegen und sie mit einem passenden Datentyp zu deklarieren.

Variablen und ihr Datentyp

Eine Variable ist ein abstrakter Behälter für einen Wert, der bei der Ausführung eines Computerprogramms auftritt. Im Normalfall wird eine Variable im Quelltext durch einen Namen bezeichnet und hat eine Adresse im Speicher des Computers. Der durch eine Variable repräsentierte Wert (und gegebenenfalls auch die Größe) kann – im Unterschied zu einer Konstante – zur Laufzeit des Programms verändert werden. Variablen dienen also dazu, veränderbare Werte zu speichern.

Unter BlitzBasic/AmiBlitz3 definiert man eine Variable mittels des Schlüsselworts DEFTYPE nach dem folgenden Schema:

DEFTYPE .Datentyp Variablenname
; -- Beispiel, deklariert eine Variable vom Typ String: --
DEFTYPE .s altesKinderlied
altesKinderlied = "Alle meine Entchen"

Es ist auch mögliche, eine Variable direkt, ohne DEFTYPE zu deklarieren:

altesKinderlied.s = "Alle meine Entchen"

Der Variablenname ist im Rahmen syntaktischer Vorgaben frei wählbar. Er sollte aussagekräftig den Zweck der Variablen wiedergeben („sprechender“ Name). Erlaubt sind alphanumerische Zeichen und der Unterstrich mit den folgenden Ausnahmen:

  • der Variablenname darf nicht gleichlautend mit einem Schlüsselwort sein.
  • das erste Zeichen darf keine Ziffer sein.
  • Umlaute sind nicht erlaubt.
  • Sonderzeichen außer dem Unterstrich sind nicht erlaubt.
    Ausnahmen: Sonderzeichen, die zur Identifizierung eines Datentypen gehören, dürfen am Anfang oder Ende des Variablennamens verwendet werden.

Beispiele:

; Erlaubt:
meinString$, meinString.s
meine_variable1
aepfelZaehler

; Verboten:
mein$tring
1teVariable
äpfelZähler

Der Datentyp legt den Speicherverbrauch einer Variablen fest.

Primitive Datentypen

BlitzBasic/AmiBlitz3 verfügt über 7 Basis-Datentypen – die sogenannten primitiven Datentypen. Die Sprache verfügt auch über die Möglichkeit, aus diesen Typen erweiterte, die sogenannten zusammengesetzten Datentypen, zu erstellen – doch dazu später mehr.

Jedem primitiven Datentyp ist ein bestimmter Wertebereich zu eigen, in dessen Rahmen er Zahlen und Zeichen darstellen kann. Die Größe dieses Wertebereich bestimmt seinen Speicherverbrauch (vergl. Anhang A – primitive Datentypen).

Byte (.b)

Dieser Datentyp verarbeitet kleine Ganzzahlen (Integerwerte) im Wertebereich von -128 bis +127 (-128 … 0 … +128) und verbraucht 1 Byte (8 Bits) Speicher. Er eignet sich z.B. gut als Zählervariable in kurzen Zählschleifen oder zur numerischen Darstellung des ASCII-Zeichensatzes.
Beispiel: DEFTYPE .b kleinerZaehler =  0

Word (.w)

Dieser Datentyp verarbeitet mittelgroße Ganzzahlen im Wertebereich von -32768 bis +32767 (-32768 … 0 … +32767) und verbraucht 2 Bytes (16 Bits) Speicher.
Beispiel: DEFTYPE .w fatNumber =  22000

Long / Long Word (.l)

Dieser Datentyp verarbeitet sehr große Ganzzahlen im Wertebereich von -231  bis +231 und verbraucht 4 Bytes (32 Bits) Speicher.
Beispiel: DEFTYPE .l veryfatNumber =  4711081542

Quick (.q)

Dieser Datentyp verarbeitet kleine Fließkommazahlen im Wertebereich von -32768 bis +32767 unter Verwendung eines festen Dezimalpunkts und verbraucht 4 Bytes (32 Bits) Speicher, erlaubt bis zu 10 Nachkommastellen. Er ist schneller als die Emulation der Float-Typen in Software, aber langsamer als Integer und langsamer als Float-Typen auf einer Hardware-FPU.
Beispiel: DEFTYPE .q smallFloatNumber = 4711.0815

Float (.f)

Dieser Datentyp verarbeitet große, einfachpräzise Fließkommazahlen im Wertebereich von -9*1018 bis +9*1018-1 und verbraucht 4 Bytes (32 Bits) Speicher. Er eignet sich besonders zur Verwendung als einfachpräzise Fließkommazahl, wie sie von den Standard-Fließkommabibliotheken des Amiga unterstützt wird und arbeitet mit +/-23bits+/-7 bits (10 Nachkommastellen)Dieser Datentyp ist sehr langsam in Software zu emulieren, aber sehr schnell, wenn Hardware-FPU verwendet wird. Er arbeitet langsamer als Ganzzahlen.
Beispiel: DEFTYPE .f largeFloatNumber = 471143.0815

Double Float (.d)

Dieser Datentyp verarbeitet sehr große, doppeltpräzise Fließkommazahlen mit riesigem Wertebereich und verbraucht 8 Bytes (64 Bits) Speicher, 9 Nachkommastellen. Keine Software-Emulation möglich, daher muss eine Hardware-FPU vorhanden sein, um diesen Datentyp nutzen zu können! Nicht unterstützt in Blitz Basic 2.1 und früher. Langsamer als einfachpräzise Float-Typen. Typische Anwendungsfälle wären ein Programm zur Berechnung von Zinsen über lange Zeiträume oder eine ähnliche Banking-Software und alle Anwendungen, die wissenschaftliche Berechnungen mit Bedarf an hoher Rechengenauigkeit durchführen.
Beispiel: DEFTYPE .d hugeFloatNumber = 471143.0815

Hinweis: Der Inhalt einer Variablen des neuen Datentyps Double Float kann nicht korrekt mit Print und NPrint ausgegeben werden! Beide Befehle liefern nur den ganzzahligen Anteil des Wertes einer Variablen dieses Datentyps – die Stellen nach dem Dezimalpunkt werden von beiden Befehlen unterschlagen. Derzeit unterstützt noch keine einzige BlitzLib diesen Datentypen, sodass er hier nur der Vollständigkeit halber aufgeführt ist! Wenn es vermeidbar ist, dann verwende diesen Datentyp nicht.
Benutze stattdessen den Datentyp Float.

String (.s oder $)

Dieser Datentyp verarbeitet Zeichenketten aus 8-Bit-Zeichen im Speicher, die automatisch durch ein Nullzeichen (\0) abgeschlossen werden und verbraucht 4 Bytes (32 Bits).
Beispiel 1: DEFTYPE .s myStringVar_1
myStringVar_1 = „Ich bin eine Zeichenkette!“
Beispiel 2: myStringVar_2.s = „Ich auch! Ich auch!“
Beispiel 3: myStringVar_3$ = „Und ich erst!“

Datentypen deklarieren

Bei der Deklaration von Datentypen unterscheidet man zwischen der Inline-Deklaration, der expliziten Deklaration und der globalen Festlegung eines bestimmten Default-Datentyps:

  • Inline: ergebnis.q = 4711.42 (die Variable wird mit dem angegebenen Typen – hier: QUICK – versehen und gleichzeitig mit einem Wert initialisiert)
  • Explizit: DEFTYPE .q ergebnis (die Variable – und nur diese – ist vom angegeben Typ. Hier: QUICK)
  • Global: DEFTYPE .q (alle nicht inline oder explizit deklarierten Variablen sind vom Typ, der hier angegeben wurde – in diesem Fall QUICK)

Das Listing „typesize.ab3“ demonstriert die Deklaration und Initialisierung der primitiven Datentypen und gibt deren Speicherbedarf in Bytes und Bits aus. Beachte, dass dieses Listing aufgrund der Verwendung des Datentyps DOUBLE FLOAT nur auf Amigas mit FPU compiliert werden kann!

; ---------------------------------
; Listing: typesize.ab3
; Speicherverbrauch von Datentypen
; Version 1.0
;
; HARDWARE-FPU ERFORDERLICH!
; ---------------------------------
OPTIMIZE 3 ; FPU zuschalten
SYNTAX 1   ; strenger Syntax-Check

; -- Variablendeklaration mit DEFTYPE --
DEFTYPE .b byteVar
DEFTYPE .w wordVar
DEFTYPE .l longVar
DEFTYPE .q quickVar
DEFTYPE .f floatVar
DEFTYPE .d doubleVar
DEFTYPE .s stringVar, byteRes, bitRes

; Amiga Version string und das Compilerdatum
!version {"typesize 1.0 (\\__DATE_GER__)"}

; Variablen initialisieren
byteVar   = -128
wordVar   = 32767
longVar   = 4711081542
quickVar  = 4711.0815234567
floatVar  = 471143.0815421112
doubleVar = 47114384.420815471
stringVar = "BlitzBasic macht Freude."

; Werte ausgeben
byteRes = Str$(SizeOf .b)
bitRes  = Str$((SizeOf .b) * 8)
Print "Speicherverbrauch BYTE: " + byteRes + " Byte ("
NPrint bitRes + " Bits)"
Print "Wert: "
NPrint byteVar
NPrint ""

byteRes = Str$(SizeOf .w)
bitRes  = Str$((SizeOf .w) * 8)
Print "Speicherverbrauch WORD: " + byteRes + " Byte ("
NPrint bitRes + " Bits)"
Print "Wert: "
NPrint wordVar
NPrint ""

byteRes = Str$(SizeOf .l)
bitRes  = Str$((SizeOf .l) * 8)
Print "Speicherverbrauch LONG: " + byteRes + " Byte ("
NPrint bitRes + " Bits)"
Print "Wert: "
NPrint longVar
NPrint ""

byteRes = Str$(SizeOf .q)
bitRes  = Str$((SizeOf .q) * 8)
Print "Speicherverbrauch QUICK: " + byteRes + " Byte ("
NPrint bitRes + " Bits)"
Print "Wert: "
NPrint quickVar
NPrint ""

byteRes = Str$(SizeOf .f)
bitRes  = Str$((SizeOf .f) * 8)
Print "Speicherverbrauch FLOAT: " + byteRes + " Byte ("
NPrint bitRes + " Bits)"
Print "Wert: "
NPrint floatVar
NPrint ""

byteRes = Str$(SizeOf .d)
bitRes  = Str$((SizeOf .d) * 8)
Print "Speicherverbrauch DOUBLE FLOAT: " + byteRes + " Byte ("
NPrint bitRes + " Bits)"
Print "Wert: "
NPrint doubleVar  ; ACHTUNG: NPrint und Print drucken nur den ganzzahligen 
                  ; Anteil des Wertes!
NPrint "ACHTUNG: Ungelöstes Ausgabe-Problem!"
NPrint ""

byteRes = Str$(SizeOf .s)
bitRes  = Str$((SizeOf .s) * 8)
Print "Speicherverbrauch STRING: " + byteRes + " Byte ("
NPrint bitRes + " Bits)"
Print "Wert: "
NPrint stringVar
NPrint ""

End

Ausgabe:

Speicherverbrauch BYTE: 1 Byte (8 Bits)
Wert: -128

Speicherverbrauch WORD: 2 Byte (16 Bits)
Wert: 32767

Speicherverbrauch LONG: 4 Byte (32 Bits)
Wert: 416114246

Speicherverbrauch QUICK: 4 Byte (32 Bits)
Wert: 4711.5781

Speicherverbrauch FLOAT: 4 Byte (32 Bits)
Wert: 471143.5625

Speicherverbrauch DOUBLE FLOAT: 8 Byte (64 Bits)
Wert: 47114384
ACHTUNG: Ungelöstes Ausgabe-Problem!

Speicherverbrauch STRING: 4 Byte (32 Bits)
Wert: BlitzBasic macht Freude.

Programmanalyse:

Das Programm benutzt zwei neue Befehle: Str$() und SizeOf. Str$() wandelt einen numerischen Wert in einen String um. Sizeof liefert den Speicherverbrauch eines Datentyps in Bytes zurück.

Wir verwenden Str$, um den (numerischen) Rückgabewert von Sizeof einer String-Variable zuweisen zu können, die dann bei der Ausgabe durch Print und NPrint zusammen mit anderen Zeichenketten zu einer neuen Zeichenkette zusammengesetzt wird (String Concatenation).

Ablauf:

  • In Zeile 8 sorgen wir mit OPTIMIZE 3 dafür, dass neben der Optimierung für die MC68020 CPU auch die FPU verwendet wird (siehe Abschnitt „Optimierte Programme erzeugen“ im Artikel „Das erste Programm„). Das ist nötig, da wir u.a. den Datentyp DOUBLE FLOAT verwenden, der nur auf einer physisch vorhandenen FPU und erst ab AmiBlitz3 verwendet werden kann. BlitzBasic v2 und älter kennen diesen Datentypen nicht.
  • Zeile 9 schaltet die strenge Syntax-Prüfung ein, bei der alle Variablen vor ihrer ersten Verwendung per DEFTYPE deklariert werden müssen.
  • In den Zeilen 12 bis 18 deklarieren wir per expliziter Deklaration die im Programm verwendeten Variablen mit einem Datentyp.
  • Zeile 21 legt den Versions-String fest, der bei Abfrage mit dem DOS-Befehl version meinProgramm full in einer Shell Auskunft über die Versionsnummer und das Erstellungsdatum eines Programms gibt.
  • In den Zeilen 24 bis 30 weisen wir einigen der zuvor deklarierten Variablen Werte zu (Initialisierung).
  • Die Zeilen 33 bis 39 geben Speicherverbrauch und Inhalt der BYTE-Variablen byteVar aus:
  • In Zeile 33 wandeln wir die per SizeOf .b abgefragte Speichergröße (Anzahl Bytes) mittels Str$ in eine Zeichenkette um und weisen sie der String-Variablen byteRes zu.
  • In Zeile 34 verfahren wir analog, berechnen hier aber die Anzahl Bits durch Multiplikation mit dem Faktor 8 ( 1 Byte = 8 Bits). Das Ergebnis der Berechnung wird der String-Variablen bitRes zugewiesen.
  • In Zeile 35 geben wir per Print (ohne Zeilenvorschub) eine Teilmeldung aus. Sie setzt sich aus mehreren Teilstrings zusammen, die wir mit dem Verknüpfungsoperatur „+“ zu einem Gesamtstring für die Ausgabe zusammensetzen.
  • In Zeile 36  geben wir mit NPrint (mit Zeilenvorschub) einen weiteren zusammengesetzten String aus, der die Ausgabe der Speichergröße abschließt.
  • Zeile 37 druckt per Print eine weitere Meldung ohne Zeilenvorschub, an welche dann in Zeile 38 per NPrint der Wert (Inhalt) der Variablen byteVar angehängt und anschließend ein Zeilenvorschub ausgeführt wird.
  • Zeile 39 druckt mittels einem an NPrint übergebenen Leerstring einen weiteren Zeilenvorschub (ohne Text).
  • Analog zu den Zeilen 33 bis 39 werden in den Zeilen 41 bis 89 nacheinander die Speichergrößen und Inhalte für die übrigen Datentypen ausgegeben.
  • Das Programm endet in Zeile 91 mit der Anweisung End.

Speicherüberlauf 

Wir haben gelernt, dass jeder Datentyp einen bestimmten Wertebereich besitzt, der die Größe der darstellbaren Inhalte einer Variablen bestimmt. Was aber, wenn dieser Wertebereich überschritten wird? Nun, in diesem Fall kommt es zum Speicherüberlauf. Bei numerischen Variablen hat das zur Konsequenz, dass ihr Inhalt nicht mehr mit dem vermuteten Wert übereinstimmt, was wiederum zu unvorhergesehenem Programmverhalten führt.

Wenn ein Wertebereich überschritten wird, so wird (normalerweise) kein Fehler erzeugt. Stattdessen wird der Wert auf das andere Ende des Wertebereichs umgeschlagen. Dies kann dazu führen, dass einige sehr schwer zu findende Fehler in deinen Code eingeschleust werden!

Ein Beispiel: Der Datentyp BYTE kann Ganzzahlen im Bereich zwischen -128 und + 127 darstellen. Wenn eine BYTE-Variable den Wert +127 besitzt und man addiert nochmal 1 dazu, so ist der Inhalt nicht, wie man vermuten könnte, +128, sondern -128. Das entspricht der unteren Grenze des Wertebereichs. Addiert man nun eine weitere 1 hinzu, so ist der Wert -127.

Im negativen Wertebereich verhält sich das genauso: Wenn eine BYTE-Variable den Wert -128 besitzt und man subtrahiert davon 1 weg, so ist der Inhalt nicht, wie man vermuten könnte, –129, sondern +127. Das entspricht der oberen Grenze des Wertebereichs. Subtrahiert man nun eine weitere 1, so ist der Wert +126. Das Listing „overflow.ab3“ verdeutlicht das eben Gesagte:

; ---------------------------------
; Listing: overflow.ab3
; Ueberlauf von Datentypen
; Version 1.0
; ---------------------------------
OPTIMIZE 1 ; MC68020+ Optimierungen
SYNTAX 1   ; strenger Syntax-Check

; -- Variablendeklaration mit DEFTYPE --
DEFTYPE .b byteVar

; Amiga Version string und das Compilerdatum
!version {"overflow 1.0 (\\__DATE_GER__)"}

; Variable initialisieren
byteVar   = 127 ; positive Obergrenze

; Titel ausgeben
NPrint "=============="
NPrint "-- Overflow --"
NPrint "=============="
NPrint ""

; Wert ausgeben (positiver Bereich)
NPrint "positiver Wertebereich:"
Print "byteVar hat den Anfangswert: "
NPrint byteVar
NPrint "Addiere 1..."
byteVar = byteVar + 1
Print "byteVar hat nun den Wert "
NPrint byteVar
NPrint "Addiere weitere 1..."
byteVar = byteVar + 1
Print "byteVar hat nun den Wert "
NPrint byteVar
NPrint ""

; Wert zuruecksetzen auf Untergrenze
byteVar = -128

; Wert ausgeben (negativer Bereich)
NPrint "Negativer Wertebereich:"
Print "byteVar hat den Anfangswert "
NPrint byteVar
NPrint "Subtrahiere 1..."
byteVar = byteVar - 1
Print "byteVar hat nun den Wert "
NPrint byteVar
NPrint "Subtrahiere weitere 1..."
byteVar = byteVar - 1
Print "byteVar hat nun den Wert "
NPrint byteVar
NPrint ""

NPrint "Habe fertig."
End

Ausgabe:

==============
-- Overflow --
==============

positiver Wertebereich:
byteVar hat den Anfangswert: 127
Addiere 1...
byteVar hat nun den Wert -128
Addiere weitere 1...
byteVar hat nun den Wert -127

Negativer Wertebereich:
byteVar hat den Anfangswert -128
Subtrahiere 1...
byteVar hat nun den Wert 127
Subtrahiere weitere 1...
byteVar hat nun den Wert 126

Habe fertig.

Zum Programmablauf gibt es eigentlich nichts zu sagen – alle vorkommenden Anweisungen und Abläufe haben wir bereits besprochen.

Konstanten

Eine Konstante (von lateinisch constans ‚feststehend‘) in einem Computerprogramm ist ein Behälter für einen Wert, der nach der Zuweisung nicht verändert werden kann. Im Gegensatz zu Variablen ist der einmal festgelegte Wert einer Konstanten zur Laufzeit des Programms bindend.

Ein Rautezeichen (#) vor einem Variablennamen bedeutet, dass es sich um eine Konstante handelt (nicht mehr um eine Variable!) Der Wert einer Konstante ist immer eine Ganzzahl. Anders als in anderen Hochsprache, wie z.B. C/C++, kann man in BlitzBasic keine Konstanten mit anderen Datentypen definieren.

Konstanten haben die folgenden Eigenschaften:

  • Sie sind schneller als Variablen und benötigen keinen Speicherplatz.
  • machen Programme besser lesbar als Zahlen
  • Können in Assembler verwendet werden
  • Können mit bedingten Kompilierauswertungen verwendet werden
  • Können nur Integer-Werte enthalten
  • Erleichtert das Ändern einer konstanten Menge, die in einem Programm verwendet wird
  • Können nur über den Quellcode zur Kompilierzeit, aber NICHT zur Laufzeit geändert werden

Neben der Option, eigene Konstanten zu definieren, bringt BlitzBasic schon viele „eingebaute“ Konstante, wie bspw. die Kreiszahl Pi mit. Der wohl wichtigste Aspekt von Konstanten aus der Sicht eines BASIC-Programmierers ist aber wohl, dass alle „magischen Zahlen“, die im Code auftauchen, durch sinnvolle Worte wie #width ersetzt werden können („sprechende“ Namen!).

Das Listing „constants.ab3“ demonstriert die Verwendung von Konstanten.:

; -------------------------
; File: constants.ab3
; Zeigt die Verwendung von
; Konstanten
; Version: 1.0
; -------------------------
OPTIMIZE 1
SYNTAX 1

; Amiga Version String und das Compilerdatum
!version {"constants 1.0 (\\__DATE_GER__)"}

; Konstanten definieren:
#width  = 5
#height = 5

; Variablen deklarieren:
DEFTYPE .w area

; Flaeche berechnen:
area = Abs(#width * #height)

; Ergebnis ausgeben:
Print "Die Flaeche aus " + Str$(#width)
Print " m mal " + Str$(#height)
NPrint " m betraegt " + Str$(Abs(area)) + " qm"
; Interne Konstante Pi ausgeben:
NPrint "Der Wert der Kreiszahl PI ist " + Str$(Pi)
End

Ausgabe:

Die Flaeche aus 5 m mal 5 m betraegt 25 qm
Der Wert der Kreiszahl PI ist 3.141592

Programmanalyse:

Das Programm verwendet den neuen Befehl Abs(). Er dient zur Umwandlung vorzeichenbehafteter Zahlen in vorzeichenlose Zahlen. Wir verwenden ihn zur Umwandlung des in der Variablen area gespeicherten Wertes, der als Produkt der Multiplikation zweier Konstanten sonst u.U. als negative Zahl ausgegeben werden könnte.

  • in den Zeilen 14 und 15 definieren wir die Konstanten #width und #height. Sie werden später zur Berechnung einer Fläche herangezogen.
  • in Zeile 18 deklarieren wir die Variable area als Variable vom Typ WORD.
  • in Zeile 21 berechnen wir die Summe der Fläche und weisen das Ergebnis der Variablen area zu.
  • die Zeilen 24 bis 26 dienen der Ausgabe der berechneten Werte. Dabei benutzen wir in Zeile 26 den zuvor erklärten Befehl Abs() zur Umwandlung des in area gespeicherten Wertes – just to make sure…
  • in Zeile 28 geben wir den Wert der internen Konstante Pi aus.
  • Das Programm endet mit Zeile 29.

Zusammenfassung:

In diesem Teil des Tutorials haben wir gelernt

  • Was Datentypen und Variablen sind, welche Datentypen es gibt und wie man Variablen deklariert und initialisiert.
  • das der neue Datentyp DOUBLE FLOAT nur mit AmiBlitz3 verwendet werden kann, eine vorhanden FPU voraussetzt – und das man ihn besser nicht verwenden sollte, was sich aber in einer späteren Version von AmiBlitz3 noch ändern kann.
  • was Konstanten sind und wie man sie definiert und verwendet.
  • dass Konstanten nur Ganzzahlen aufnehmen können und keinen Speicherplatz belegen.

Ausblick

Im nächsten Teil des Tutorials werden wir uns eingehend mit den Grundrechenarten und eigenen Funktionen unter BlitzBasic beschäftigen.

 

[Zurück zur Übersicht] | [zurück] | [vowärts]

BlitzBasic mit AmiBlitz3 - ein Tutorial für Amiga-Programmierer www.mbergmann-sh.de

BlitzBasic für Einsteiger – das erste Programm

Erste Schritte mit BlitzBasic – Programmeingabe und Übersetzung

Jedes gute Tutorial für Programmierer beginnt mit dem wohl langweiligsten Programm auf diesem Planeten: Hello, World.

Bevor wir jedoch loslegen, gibt es noch etwas Organisatorisches zu erledigen: Wir brauchen ein Projektverzeichnis für die im Lauf dieses Tutorials anfallenden Dateien. Erstelle dazu zunächst ein Hauptverzeichnis irgendwo auf deiner Festplatte. Dort werden wir dann bei Bedarf weitere Unterordner für Projekte anlegen und unsere Listings dort passenden abspeichern.

Beispiel:

makedir Work:ab3-Tutorial
makedir Work:ab3-Tutorial/001_hello

 

Starte nun AmiBlitz3 und gib im Editor-Fenster das folgende Listing buchstabengetreu, aber ohne Zeilennummern ein:

; ---------------------------
; Listing: hello1.ab3
; Hallo, Welt mit BlitzBasic
; Version 1.0
; ---------------------------

Print "Hallo, Welt!"
End

Speichere dein Programm (<Amiga> + <S>) unter dem Namen „hello1.ab3“ in deinem Projektverzeichnis 001_hello für unser Tutorial. Der Suffix „.ab3“ ist der Standard, um ein Listing als zu AmiBlitz3 gehörende Quelldatei zu kennzeichnen.

Stelle sicher, das die Option zum Starten des Debugger deaktiviert ist. Verwende die Tastenkombination <Amiga> + <#>, um dein Programm zu compilieren und zu starten. Du erhältst die folgende Ausgabe:

AmiBlitz3 BlitzBasic Tutorial www.mbergmann-sh.de

Betrachten wir uns Programm und Ausgabe einmal genauer:

  • Die Zeilen 1 bis 5 enthalten einen erklärenden Kommentar zum Programm. Kommentare werden in BlitzBasic mit dem Semikolon eingeleitet und gelten jeweils für eine Zeile. Alles, was in einem Kommentar steht, wird vom Compiler ignoriert.
  • Zeile 7 gibt mit dem Schlüsselwort Print die in Anführungszeichen gesetzte Meldung aus. Es erfolgt kein Zeilenvorschub!
  • Das Programm endet in Zeile 8 mit dem Schlüsselwort End.

Wenn du bereits Erfahrungen mit anderen BASIC-Dialekten gemacht hast, dann wirst du dich vielleicht wundern, warum nach dem Print-Befehl keine neue Zeile erzeugt wird. Nun, in BlitzBasic gibt es dafür den Befehl NPrint, der explizit einen Zeilenvorschub nach der Ausgabe erzeugt. Der Syntax ist mit dem von Print nahezu identisch.

Ändere unser erstes Programm nun so ab, dass es dem folgenden Listing entspricht und speichere es anschließend unter „hello2.ab3“ im gleichen Verzeichnis wie eben:

; ---------------------------
; Listing: hello2.ab3
; Hallo, Welt mit BlitzBasic
; Version 2.0
; ---------------------------

NPrint "Hallo, Welt!"
NPrint "Ich kann auch mit Zeilenvorschub..."
End

Drücke wieder <Amiga> + <#>, um dein Programm zu compilieren und zu starten. Diesmal sieht die Ausgabe des Programms so aus:

Ein Programm mit Variablen

Variablen dienen dazu bestimmte Werte, wie etwa Strings (Zeichenketten) oder Zahlenwerte, für die weitere Verwendung im Programm zwischen zu speichern. Sie werden im Arbeitsspeicher (RAM) angelegt. Sie besitzen einen Datentyp, der darüber entscheidet, welche Art von Wert eine Variable aufnehmen kann.

Lege für unser nächstes Projekt den Ordner 002_myname an. Gib dann das folgende Listing ein und speichere es  als „myname1.ab3“ im eben erstellten Ordner.

; ---------------------------
; Listing: myname1.ab3
; Ein Programm mit Variablen
; Version 1.0
; ---------------------------

meinName$ = "Callimero"  ; eine String-Variable deklarieren

NPrint "Hallo, Welt!"
Print "Mein Name ist "
Print meinName$
NPrint "."
NPrint "Nun ist es heraus..."
End

Ausgabe:

Hallo, Welt!
Mein Name ist Callimero.
Nun ist es heraus...
Program terminated.
Press <ENTER> to return to to the IDE...

Programmanalyse:

Unser Programm verwendet eine Variable vom Datentyp String. Das erkennt man schnell am an den Variablennamen angehängten Dollarzeichen ($). Stringvariablen nehmen alle Arten von alphanumerischen Zeichen und Leerstellen auf, sodass man ganze Sätze in einer String-Variablen ablegen kann. Eine String-Variable deklariert man, indem man ihr einen Variablenname mit angehängtem $ gibt. Bei einer vollständigen Definition weist man dann dieser Variablen mittels des Zuweisungsoperators (=) einen Text zu. Dieser wird zwischen Anführungszeichen gesetzt (In unserem Programm haben wir das in Zeile 7 getan). Beispiel:

  meinString$ = "Alle meine Entchen"
  • Die Zeilen 1 bis 5 enthalten einen erläuternden Kommentar zum Programm.
  • in Zeile 7 deklarieren wir eine String-Variable (kenntlich am angehängten „$“ hinter dem Variablennamen) mit dem Inhalt „Calimero“. Hinter der Variablendeklaration steht ein erläuternder Kommentar.
  • Zeile 9 gibt die Meldung „Hallo, Welt!“, gefolgt von einem Zeilenvorschub, aus.
  • In Zeile 10 geben wir mit Print (ohne Zeilenvorschub) die Meldung „Mein Name ist “ aus. Wir machen das so, weil wir in der selben Zeile weitere Textausgaben anhängen möchten. Beachte das Leerzeichen am Ende des Strings – es sorgt dafür, dass die nächste Print-Ausgabe nicht direkt am letzten Wort der Meldung klebt.
  • Zeile 11 hängt den in der zuvor in der String-Variablen meinName$ gespeicherten String „Callimero“ an.
  • Zeile 12 schließt den zuvor begonnen Satz mit einem Punkt ab und gibt einen Zeilenvorschub aus.
  • Zeile 13 gibt den Satz „Nun ist es heraus…“ aus und führt einen weiteren Zeilenvorschub durch.
  • Das Programm endet mit dem Schlüsselwort End in Zeile 14.

Ein Programm mit Benutzereingabe

Bis jetzt haben wir dem Computer alles, was er „sagen“ soll, fest vorgegeben. Wie aber können wir ihm die Werte, mit denen er arbeiten soll, auch zur Laufzeit mitteilen? Nun, unter BlitzBasic gibt es dafür mehrere infrage kommende Möglichkeiten. Für die Abfrage in Shell-Programmen kommen hier die beiden Schlüsselwörter Edit$ (für Strings) und Edit (für Zahlenwerte) in Frage. Das Listing „myname2.ab3“ illustriert das. Gib es ein, speichere es und führe es aus.

; ---------------------------
; Listing: myname2.ab3
; Ein Programm mit Variablen
; Version 2.0
; ---------------------------

meinName$ = "Callimero"  ; eine String-Variable deklarieren

NPrint "Hallo, Welt!"
Print "Mein Name ist "
Print meinName$
NPrint "."
NPrint "Nun ist es heraus..."
NPrint ""                ; gibt eine Leerzeile aus

; -- Benutzereingabe mit Input --
Print "Wie lautet dein Name? "
deinName$ = Edit$(30)

; -- Ausgabe --
greetStr$ = "Tach auch, " + deinName$ + "!"
NPrint greetStr$

End

Ausgabe:

Hallo, Welt!
Mein Name ist Callimero.
Nun ist es heraus...

Wie lautet dein Name? Micha B. 
Tach auch, Micha B.!

Programmanalyse:

  • Zeile 17 – Ausgabe der Aufforderung, den Namen einzugeben. Wir verwenden Print, damit die Eingabemarke nach dem folgenden Edit$-Befehl nicht in einer neuen Zeile ausgegeben wird.
  • In Zeile 18 weisen wir die Benutzereingabe per Edit$ der Variablen deinName$ zu. Der Syntax von Edit$ lautet
    Edit$([Default Text,] Eingabelänge in Zeichen)
  • In Zeile 21 setzen wir mit dem Pluszeichen aus mehreren Strings einen neuen String zusammen (String Concatenation). Der zusammengesetzte String wir der Stringvariablen greetStr$ zugewiesen.
  • Zeile 22 gibt den Inhalt der Variable greetStr$ aus.

Überprüfen von Variablen durch den Compiler

AmiBlitz3 verfügt – im Gegensatz zum alten BlitzBasic v2.1 – über die Möglichkeit, dem Compiler mitzuteilen, dass er eine strikte Syntaxprüfung vornehmen und u.a. verwendete Variablen vor ihrer Benutzung auf korrekte Verwendung überprüfen soll. Eine strikte Syntaxprüfung hat große Vorteile bei der Programmentwicklung, denn es erspart es dir von vorn herein, durch falsch genutzte Variablen und Funktionen schwer aufzuspürende Bugs in deinem Programm einzubauen. Die strikte Syntaxprüfung schaltest du mit dem compilerinternen Befehl SYNTAX am Anfang deines Quelltexts ein. Der Befehl übernimmt einen numerischen Wert für die Intensität der Prüfung:

  • SYNTAX 0 – Prüfung abschalten, Variablen müssen nicht vor der ersten Verwendung deklariert werden (wie BlitzBasic2)
  • SYNTAX 1 – Variablen müssen zwingend mit DEFTYPE deklariert werden
  • SYNTAX 2 – Variablen müssen bei der ersten Verwendung mit DEFTYPE deklariert werden

Es bleibt dir überlassen, ob du in deinen eigenen Programmen dieses Feature nutzen möchtest, allerdings rate ich dir dazu, wenigstens SYNTAX 2 zu verwenden. Der gute Grund: Man verliert nicht so leicht den Überblick über seine Variablen und ihren Zweck, wenn man sich von Anfang an daran gewöhnt, diese bereits am Anfang eines Programms oder wenigstens vor der ersten Verwendung zu deklarieren, anstatt sie wild während des Programmierens zu erfinden. Ich persönlich komme aus der C/C++ Welt und bin ohnehin daran gewöhnt, meinem Compiler von Anfang an mitzuteilen, welche Variable für welchen Zweck zu verwenden ist. Darum bevorzuge ich SYNTAX 1.

Ergänze unser eben geschriebenes Programm um den Eintrag SYNTAX 1 direkt nach dem einleitenden Kommentar, speichere es unter „myname3.ab3“ und führe es aus. Wie nicht anders erwartet, wartet es mit einer Fehlermeldung auf:

Mit SYNTAX 1 haben wir festgelegt, dass Variablen zwingend mit DEFTYPE deklariert werden müssen. Also tun wir das auch:

; -- Variablendeklaration mit DEFTYPE --
DEFTYPE .s meinName$, deinName$, greetStr$

Die Compiler-Anweisung DEFTYPE (Default Type) bestimmt den Datentyp von Variablen. Der Parameter .s gibt im vorliegenden Fall an, dass es sich bei den anschließend aufgezählten Variablen um String-Variablen handelt (siehe Anhang A – Primitive Datentypen).

Der Amiga Version-String

Auf dem Amiga kann man die Versionsinformationen eines systemkonformen Programms mit dem Version-Befehl in einer Shell abfragen. Dazu muss natürlich auch ein entsprechender Version-String vorhanden sein. So definiert man ihn:

; Amiga Version String und das Compilerdatum
!version {"MyName 3.0 (\\__DATE_GER__)"}

Hier noch einmal das vollständige, geänderte Listing:

; ---------------------------
; Listing: myname3.ab3
; Ein Programm mit Variablen
; Version 3.0
; ---------------------------
SYNTAX 1

; -- Variablendeklaration mit DEFTYPE --
DEFTYPE .s meinName$, deinName$, greetStr$

; Amiga Version String und das Compilerdatum
!version {"MyName 3.0 (\\__DATE_GER__)"}

meinName$ = "Callimero"  ; eine String-Variable initialisieren

NPrint "Hallo, Welt!"
Print "Mein Name ist "
Print meinName$
NPrint "."
NPrint "Nun ist es heraus..."
NPrint ""                ; gibt eine Leerzeile aus

; -- Benutzereingabe mit Input --
Print "Wie lautet dein Name? "
deinName$ = Edit$(30)

; -- Ausgabe --
greetStr$ = "Tach auch, " + deinName$ + "!"
NPrint greetStr$

End

Compiliere das Programm diesmal über das Menü Compiler->Create Executable und gib als Ziel für das ausführbare Programm RAM: und als Dateinamen myname an. Öffne danach eine Shell und überprüfe die Versionsnummer:

RAM Disk:> version RAM:myname file full
MyName 3.0 (16.03.25)

Optimierte Programme erzeugen

Jeder möchte, dass sein Programm so schnell wie möglich arbeitet. AmiBlitz3 unterstützt die Optimierung von Programmen mit dem compilerinternen Schlüsselwort OPTIMIZE n. Es sollte ganz am Anfang des zu optimierenden Quellcodes stehen und nimmt einen Zahlenwert als Parameter n:

  • OPTIMIZE 1 – optimiert für die Motorola MC68020 CPU
  • OPTIMIZE 2 – verwende eine vorhanden FPU (Achtung: ein so optimiertes Programm wird auf Amigas ohne FPU abstürzen!)
  • OPTIMIZE 4 – schaltet den Modus für neuen Syntax (AmiBlitz3) zu

Kombinierte Optimierungsstufen lassen sich durch die Addition dieser Werte erzeugen. Beispiel:

; -- ALLE Stufen verwenden --
; --    1 + 2 + 4 = 7      --
OPTIMIZE 7

Hinweis: Im Debug-Modus ist die Optimierung für FPU abgeschaltet.

Die Optimierung der Größe des ausführbaren Programmes kann man über das Menü Compiler->Create minimized Executable bewirken.

Zusammenfassung

Wir haben in diesem Teil des Tutorials gelernt,

  • was Kommentare sind und wie man sie verwendet
  • wie und wann man die Befehle Print und NPrint verwendet
  • was eine String-Variable ist
  • wie man mit dem Befehl Edit$ eine Benutzereingabe in einen String einliest
  • wie man Teilstrings zu einem neuen String zusammensetzt
  • wie man den Compiler dazu veranlasst, strengere Syntaxprüfung und Code-Optimierungen vorzunehmen
  • was der Amiga Version String ist und wie man ihn definiert

Im weiteren Verlauf des Tutorials werden wir grundsätzlich immer Variablen vor Gebrauch deklarieren und unseren lauffähigen Programmen einen Version-String mitgeben.

Ausblick

Im nächsten Teil werden wir uns etwas genauer mit Variablen, Konstanten und Datentypen befassen.


[Zurück zur Übersicht] | [zurück] | [vowärts]

BlitzBasic mit AmiBlitz3 - ein Tutorial für Amiga-Programmierer www.mbergmann-sh.de

BlitzBasic für Einsteiger – die Entwicklungsumgebung

AmiBlitz3 – Entwickler IDE für BlitzBasic auf dem Amiga

Herzlich willkommen bei meinem Tutorial zur Anwendungsentwicklung mit BlitzBasic auf dem Amiga!

Bevor wir richtig einsteigen können, müssen natürlich zunächst erst die Voraussetzungen zum Arbeiten mit BlitzBasic geschaffen werden. Grundsätzlich kannst du dieses Tutorial auch mit der alten BlitzBasic-Version v2.1 bearbeiten – aber warum solltest du dich quälen wollen? AmiBlitz3 ist eine moderne, feature-reiche IDE, gegen die der Editor aus AmiBlitz 2 einfach alt aussieht. Mit AmiBlitz3 hast du eine wesentlich leistungsfähigere Entwicklungsumgebung mit einem modernen Editor, Debugging-Features, einem Sourcecode-Browser, einem Bibliotheken-Browser, integrierten Hilfe-Funktionen und vielem mehr für lau zur Verfügung. Der neu überarbeitete Compiler erzeugt optimierten, schnellen Code für alle auf dem Amiga gebräuchlichen Motorola MC680x0 CPU und kann obendrein auch FPU-optimierten Code erzeugen. Dabei können Programme für jede klassische AmigaOS-Version erstellt werden.

AmiBlitz3 herunterladen und installieren

AmiBlitz3 wird derzeit aktiv von Sven Dröge entwickelt und ist auf GitHub gehostet:

Download:

  1. Option: https://github.com/AmiBlitz/AmiBlitz3 (der aktuelle Source Code auf GitHub)
  2. Option: https://github.com/AmiBlitz/AmiBlitz3/releases/download/v3.10.0/Amiblitz3100.lha (Programmarchiv)

Am einfachsten besorgst du dir das Archiv per Option 2 und entpackst es:

lha -a x Amiblitz3100.lha RAM:

list ram:AmiBlitz3.10/
Directory "ram:AmiBlitz3.10" on Samstag 15-Mär-25 
Tools Dir ----rwed Heute 15:00:50
Tools.info 6376 ----rwed 06-Mär-24 15:53:08
System Dir ----rwed Heute 15:00:50
System.info 6484 ----rwed 06-Mär-24 15:53:08
Sourcecodes Dir ----rwed Heute 15:00:50
Sourcecodes.info 5947 ----rwed 06-Mär-24 15:53:08
README.md.info 5880 ----rwed 06-Mär-24 15:53:08
README.md 2133 ----rwed 23-Mär-24 12:50:06
Locale Dir ----rwed Heute 15:00:49
Libs Dir ----rwed Heute 15:00:49
Docs Dir ----rwed Heute 15:00:49
Docs.info 5904 ----rwed 06-Mär-24 15:53:08
Debug Dir ----rwed Heute 15:00:49
Contributions Dir ----rwed Heute 15:00:48
Contributions.info 6296 ----rwed 06-Mär-24 15:53:06
Catalogs Dir ----rwed Heute 15:00:48
BlitzLibs Dir ----rwed Heute 15:00:48
AmiBlitz3.info 4832 ----rw-d 26-Feb-25 13:51:50
Amiblitz3 374456 ----rwed Gestern 10:30:44
9 files - 408K bytes - 10 directories - 442 blocks used

Kopiere das Verzeichnis AmiBlitz3.10 an einen beliebigen Platz auf deiner Festplatte. AmiBlitz3 benötigt keine zusätzlichen Einträge in s:user-startup – alle Abhängigkeiten sind über die ToolTypes des Programms geregelt. Du kannst den Editor also sofort starten.

Beim ersten Start dauert es ein Weilchen, bis die internen Indices des Programms generiert worden sind. Anschließend öffnet sich die IDE.

Der erste Kontakt mit der Benutzeroberfläche

AmiBlitz3 IDEBlitzBasic für Einsteiger www.mbergmann-sh.de

AmiBlitz3 IDE mit geladenem Quelltext (1280×960 Pixel)

Je nach verwendeter Monitorauflösung kann das Layout vom hier gezeigten Layout abweichen – AmiBlitz3 sucht sich automatisch ein passendes Layout für seine Fenster. Richtig Spaß macht die IDE auf einem Amiga mit Beschleuniger- und RGB-Grafikkarte bei einer Auflösung ab 1280×960 Pixeln, aber auch in niedrigeren Auflösungen lässt es sich sehr komfortabel arbeiten.

  1. Das Editor-Fenster ist der Bereich, in dem du deine Quelltexte erfasst. Der Editor verfügt über Zeilennummerierung und Syntax Highlighting für Schlüsselworte und Sprachkonstrukte. Alle Zeichensätze (und Vieles mehr) sind über das Menü
      Project->IDE Settings
    einstellbar.
  2. Der Instruction-Browser ist ein mächtiges Tool, mit dem du nach Bibliotheksbefehlen und ihrem Syntax suchen kannst. Auf Wunsch wird ein gefundener Befehl auch gleich an der aktuellen Cursor-Position in den Text eingefügt. Ein Doppelklick auf einen im Instruction-Browser gefundenen Befehl öffnet, falls vorhanden, die Zugehörige Beschreibung in deinem Viewer für AmigaGuide-Dateien.
  3. Der aus zwei Tabs bestehende Source-Browser ermöglicht u.a. die Anzeige von im Programm verwendeten eigenen Funktionen und Bibliotheksfunktionen, die man per Doppelklick anspringen kann.
  4. Der Definition-Browser ermöglicht die Überwachung von Konstanten, Variablen und Strukturen und deren Inhalten.
  • Wenn du den Cursor im Editor-Fenster über einem Schlüsselwort positionierst und danach die <Help>-Taste drückst, so wird dir in der Fensterleiste eine Kurzhilfe angezeigt.
  • Bei gleichem Szenario bewirkt ein Druck auf die F-Taste <F1> das Öffnen einer genaueren Beschreibung im AmigaGuide-Format (falls verfügbar) – ansonsten öffnet sich die globale Hilfedatei zu AmiBlitz3.
  • Bereits vorhandene Quelltexte lädst du über das Menü
      Source File->Open
    oder die Tastenkombination <Amiga> + <O> in den Editor.
  • Ein neues, leeres Editorfenster erzeugst du mittels des Menüs
      Source File->New->(weitere Optionen).
    Hier findest du dann Assistenten für bestimmte Anwendungstypen.
  • Einen in den Editor geladenen Quelltext schnell übersetzen und ausführen lassen kannst Du über das Menü
      Compiler->Compile and Run
    oder mit der Tastenkombination <Amiga> + <#>.
  • Bei der Ausführung eines Programms öffnet sich eine Shell. Wird das Programm beendet, so musst du in dieser Shell <ENTER> drücken, um zum Editor zurück zu gelangen.
  • Die mitgelieferten Beispiele findest du im Pfad <Festplatte>:AmiBlitz3/Sourcecodes.
  • Ein Klick auf das Iconify-Gadget im Editorfenster „versteckt“ die komplette AmiBlitz3 IDE. Um sie wieder zu öffnen, musst du auf der Amiga Workbench im Menü Hilfsmittel auf den Eintrag  AmiBlitz3 klicken.
  • Programme lassen sich aus der AmiBlitz3 IDE heraus entweder mit oder ohne Debugging-Informationen compilieren. Die entsprechende Option findest du im Menü
      Compiler->Create Debug Code
    Ist dieser Menüeintrag markiert, dann wird beim Start deines Programms auch der Debugger gestartet.
  • Die F-Taste <F1> öffnet das Online-Handbuch zu AmiBlitz3.

Weitere Optionen der AmiBlitz3 IDE klären wir im Verlauf des Tutorials dort, wo sie benötigt werden. Es schadet nichts, wenn du dir vorab das Handbuch schonmal durchgelesen hast (Taste <F1>).
Auf Facebook gibt es übrigens eine nette, englischsprachige Gruppe, die dir bei Fragen rund um BlitzBasic und AmiBlitz3 auch gern weiterhilft. 🙂

So, das war’s dann mit dem Schnelleinstieg in die AmiBlitz3 IDE. Im nächsten Beitrag beschäftigen wir uns dann mit dem Schreiben unseres ersten Programms, sowie einigen theoretischen Sprachgrundlagen zu BlitzBasic.

 


[Zurück zur Übersicht] | [zurück] | [vowärts]

AmigaNews – AmiBlitz v3.10 erschienen

 

 

Sven Dröge hat’s mal wieder möglich gemacht: Hochqualitatives BlitzBasic auf dem Amiga mit AmiBlitz v3.10
Eigentlich gab’s schon lange keinen Grund mehr, das alte BlitzBasic 2.1 mit seinem greislichen Editor zu verwenden, wo doch AmiBlitz3 ein durchdachtes modernes System aus Editor und Tools zur Verfügung stellt. Nun gibt’s dafür gar keinen Grund mehr (wenn man nicht auf einem sehr spartanischen Amiga entwickelt…).

AmiBlitz v3.10 wurde in vielen Punkten nochmals deutlich verbessert. Vieles ist schneller geworden, der Editor läuft stabil und zuverlässig. Das Paket lässt für BlitzBasic-Programmierer kaum noch Wünsche offen.

Download:

https://github.com/AmiBlitz/AmiBlitz3 (Source Code auf GitHub)
https://github.com/AmiBlitz/AmiBlitz3/releases/download/v3.10.0/Amiblitz3100.lha (Programmarchiv)