In diesem Kapitel ist es besonders wichtig, nur Codes auszuführen, die mit Grün markiert sind! Experimente mit dem Hauptspeicher können echte Schäden verursachen. Wenn du dir nicht sicher bist, wende dich an die Community, damit sie deine Codes prüft, bevor du etwas ausprobierst.Axe bietet die Möglichkeit, Variablen direkt in den RAM zu speichern. Das hat den Vorteil dass dir die Variablennamen nicht ausgehen (A-Z reichen oft nicht). Das geht folgendermaßen:
In Axe wird mit
{X
} der inhalt des Bytes X zurückgegeben.
X bezieht sich dabei auf die Hauptspeicheradresse, also die Adresse im RAM.
Hier ein Beispiel - Dies überschreibt den Inhalt des ersten Bytes (Adresse 0) mit X, speichert also X an der ersten Position im RAM:
X->{0}
(Na gut, eigentlich die erste Position im Flash-speicher, da dieser bei $0000 beginnt und der RAM erst bei $8000 (Hexadezimale Angaben - also 32.768 in Dezimal).)
Eine 1 Byte lange Zahl kann nur 2^8 Werte haben, also eine zahl zwischen 0 und 255.
Das ist natürlich viel zu wenig, also verwendet Axe standartmäßig 2 Byte pro Variable.
Damit kommt man auf 2^16 Werte, also einen Zahlenbereich von 0 bis 65.535
Das heißt dieser Code wird uns ein Problem bereiten:
300->{0}
Ein kurze Erklärung:
Die Zahl 300 ist binär:
0000-0001-0010-1100, also 256+32+8+4
Sie besteht also aus 2 Bytes:
0000-0001 und
0010-1100. Versucht man nun die 300 wie oben abzuspeichern, kann nur das erste Byte tatsächlich abgespeichert werden. Das heißt aus der 300 wird
0000-0001, also die Zahl 1.
Um dieses Problem zu umgehen, wird {0}
^r verwendet.
(Du findest das
r unter
2nd -> APPS)
Durch das Anhängen des
r signalisierst du dem Compiler, dass hier nicht nur das eine Byte {0} angesprochen werden soll, sondern zwei Bytes auf einmal:
300->{0}^r
Das erste Byte (die Adresse 0) bekommt hier
0000-0001 zugewiesen und das zweite Byte (die Adresse 1) bekommt
0010-1100.
Um eine 1Byte lange Zahl zu speichern (0-255) reicht also ein Byte, für den Rest müssen 2 Bytes verwendet werden:
5->{0}
42->{1}
83->{2}
9001->{3}^r
500->{5}^r
Hierbei ist zu beachten dass {4} bereits durch
9001->{3}^r mitverwendet wird.
Wenn ihr nicht allzuviel Wert auf Speicherplatz legt aber auf nummer sicher gehen wollt, verwendet also einfach nur gerade Hauptspeicheradressen und arbeitet immer mit Bytepaaren.
5->{0}^r
42->{2}^r
83->{4}^r
9001->{6}^r
500->{8}^r
Genauso wie sich einzelne Bytes im Hauptspeicher einfach setzen lassen, kann man sie natürlich auch wieder abrufen:
555->{16}^r
{16}^r+7->A[code]
Nun ist es natürlich keine gute Idee, irgendwelche Adressen im RAM (oder Flash) einfach zu überschreiben. Du riskierst damit ernsthafte Schäden an deinem Taschenrechner!
Aber natürlich bietet Axe dir eine sichere Möglichkeit diese Technik einzusetzen: [b]L1[/b]
Anders als in Basic ist [b]L1[/b] in Axe keine Liste, sondern eine einfache Adresse im Hauptspeicher. Du denkst die L1 am besten als konstante variable mit irgendeiner komischen Zahl als wert. Das hört sich jetzt komisch an, ist aber eigentlich ganz einfach:
[b]L1[/b] markiert eine Position im Hauptspeicher, an der unbenutzter Speicher zur Verfügung steht, wodurch du also auch nichts kaputt machen kannst :)
Wenn du jetzt das erste Bytepaar von L1 ansteuern willst, machst du das so:
[code]9000->{L1}^r
{L1}^r+1->A
Natürlich stellt L1 dir auch ordentlich Platz zur verfügung: Du kannst die nächsten 256 Bytes, die nach L1 kommen, problemlos verwenden.
Übrigens: Zwar ist L1 nur eine einzelne Position, aber man spricht trotzdem davon, Variablen
IN L1 abzuspeichern wenn sie in diesem Bereich gespeichert werden. Der einachkeit halber übernehmen wir das auch.
Das heißt wenn du mehr Speicherplatz für Variablen brauchst, stehen dir
{L1+0}^r bis {L1+256}^r zur freien Verfügung.
Theoretisch kannst du das selbe übrigens auch mit L2, L3, L4, L5 und L6 machen, davon wird aber abgeraten da diese zumindest teilweise schon von Axe verwendet werden:
Wenn du z.B: Interrupts in deinem Programm verwendest, werden diese in L2 gespeichert. Und L6 entspricht dem Bildschirm, d.h. Veränderst du etwas in L6 ist das als würdest du etwas auf dem Bildschirm anzeigen lassen.
Es ist also besser, nur L1 zu verwenden bis du genau weißt was du tust. Und wenn dir doch der Platz in L1 ausgeht, dann frage besser einen Profi bevor du es einfach ausprobierst.Codebeispiele zum ausprobieren
Diese Codes kannst du selbst ausprobieren:
.ADRESS1
9000->{L1}^r
{L1}^r+1->A
Output(1,1,A>Dec)
Sleep(5000)
.ADRESS2
1->{L1+0}^r
2->{L1+2}
3->{L1+3}^r
{L1+0}^r+{L1+2}+{L1+3}^r->X
Output(1,1,A>Dec)
Sleep(5000)
Zusätzlich besteht noch die Möglichkeit, einzelne
Nibbel anzusteuern (ein Nibbel ist eine 4Bit-Einheit, so wie ein Byte eine 8Bit-Einheit ist. Und jep, die heißen wirklich so!) Das machst du so:
Mit
nib{ (du findest den Befehl unter
[Math] -> NUM -> 3) wählst du eine 4Bit-Einheit aus. Wie auch Bytes werden die Nibbel mit Adressen angesteuert. ABER: Die Adressen der Nibbel sind auf 4 statt auf 8 Bit ausgelegt. Das heißt die Adresse "4" bezieht sich NICHT auf das 4. Byte sondern auf das 4. Nibbel, sprich das 2. Byte. Das heißt du musst die gewünschte Adress im Hauptspeicher zuerst Verdoppeln (zB das hundertste Nibbel liegt im 50sten Byte, daher die Verdoppelung damit die Adressen sich auch hier auf Bytes beziehen).
Nehmen wir einmal an das erste Byte in L1 wäre
1010-1111 und wir rufen
nib{L1*2} auf, dann wird uns
1010 zurückgegeben.
Rufen wir
nib{L1*2+1} auf, dann wird uns
1111 zurückgegeben.
Um das vierte Byte in L1 aufzurufen schreiben wir also
nib{L1+3*2} und
nib{L1+3*2+1} auf. (Beachte dass das +3 ebenfalls verdoppelt werden muss da es sich um Byte-Angaben handelt)
Es besteht aber auch die Möglichkeit, zwei Nibbels (also ein Byte) auf einmal abzufragen. Hier dazu ien Beispiel:
nib{L1+4*2}->A
nib{L1+4*2+1}->B
nib{L1+4*2}^r->C
nib{L1+4*2+1}^r->D
nib{L1+4*2}^r^r->E
nib{L1+4*2+1}^r^r->F
Nehmen wir an, dass L1+4 und L1+5 diesen Inhalt haben:
1010-1111 0000-0110, dann bewirkt der Code folgendes:
A = 1010 Hier wird einfach das erste Nibbel aus dem Byte L1+4 abgefragt
B = 1111 Hier wird das zweite Nibbel aus dem selben Byte abgefragt
C = 1111-1010 Hier werden 2 Nibbel abgefragt, beginnend mit dem ersten Nibbel im Byte L1+4. Die Reihenfolge der Nibbel wird dabei standardmäßig vertauscht.
D = 0000-1111 Auch hier werden 2 Nibbel abgefragt, das zweite Nibbel in L1+4 und das nächste, also das erste Nibbel in L1+5. Auch hier die vertauschte Reihenfolge.
E = 1010-1111 Hier werden wieder beide Nibbel aus L1+4 abgefragt - aber die Nibbels explizit getauscht. Das heißt ihre Reihenfolge stimmt wieder.
F = 1111-0000 Hier werden wieder das zweite Nibbel aus L1+4 und das erste aus L1+5 angefragt - in richtiger Reihenfolge.
Wichtig: Beim Arbeiten mit Nibbeln darfst du NIEMALS vergessen, die Adresse zu verdoppeln da du ansonsten einen anderen Bereich im Speicher ansprichst und eventuell Schäden an deinem Taschenrechner entstehen!*HIER NOCH WEITERSCHREIBEN*