geschrieben am 05.08.2012 19:54:20
Zitat von kooooopa: Geht das nicht auch in dem wir das Powerup laden, schauen ob MArio einen Pilz hat, wenn ja zu Code Pilz springen und den Soundeffekt abspielen, wenn nein schauen ob Mario eine Blume hat, wenn ja....
Dann bräuchte ich doch garkeine Tabelle.
Ja, das stimmt. Trotzdem sind Tabellen vorzuziehen - sie sparen Platz, sind effizienter und machen den Code weitaus lesbarer. Was ist dir lieber, tausend Wenn-Dann-Befehle oder eine einzige Tabelle mit tausend Werten?
Zitat von kooooopa: Wenn LDY auch geht, gibt es dann einen Unterschied zwischen LDX und LDY?
Keinen großen, und keinen, um den du dir jetzt Gedanken machen musst. Es gibt nur einige Befehle, die nicht mit Y funktionieren - zum Beispiel würde LDA $000000,x funktionieren, LDA $000000,y gibt es aber nicht.
Okay, das mit dem Binärzahlen erkläre ich dir lieber ganz von vorne.
Du weißt, dass ein Byte aus 8 Bits besteht, oder? In Hexadezimal kann man zum Beispiel E6 sagen, das ist eine Zahl, die ein Byte lang ist. Sie besteht aus 8 Bits, und ein Bit ist eine Ziffer, die entweder 0 oder 1 sein kann. Wenn man die Bits einer Zahl ausschreibt, dann nennt man das Binärschreibweise. Die Zahl E6 wäre im Binärsystem 11100110. Dieselbe Zahl, nur verschiedene Schreibweisen. Du kannst sie auch im dir vertrauten Zehnersystem aufschreiben, das wäre 230, aber das tut hier nichts zur Sache.
Auch wenn man in ASM programmiert, sind die Werte, mit denen du arbeitest, meistens 1 Byte (8 bit) lang. Du kannst zum Beispiel schreiben:
, das lädt den Wert E6 in A. Du kannst aber auch die Binärschreibweise verwenden:
Das ist exakt dasselbe! Wenn du diese beiden Codes in die ROM einfügst, sind sie genau gleich. Die verschiedenen Schreibweisen sind nur für uns Menschen da, der Maschine ist das egal.
Hexadezimale Zahlen werden durch ein Dollarzeichen ($) angezeigt, Binärzahlen durch ein Prozentzeichen (%). Und merk dir: Welche Schreibweise du wählst, ist egal.( Normalerweise nimmt man aber die Hexadezimalschreibweise, die ist kürzer.)
Stell dir vor, der Wert in Adresse $15 wäre #$34 - das ist dasselbe wie 00110100.
Soviel dazu, jetzt zu den Controller-Adressen. $15 ist eine Adresse, deren Wert davon abhängt, welche Knöpfe man gerade drückt. Drückt man zum Beispiel den START-Knopf und sonst nichts, ist der Wert in Adresse $15 00010000, was dasselbe ist wie #$10.
Und woher weiß man jetzt, welcher Wert für welche Knöpfe steht? Vielleicht hilft dir das hier mehr weiter als die RAM-Map:
00000000 <-- dieses Bit ist 1, wenn A oder B gedrückt werden, und 0, wenn nicht
0
0000000 <-- dieses Bit ist 1, wenn X oder Y gedrückt werden, und 0, wenn nicht
00
000000 <-- dieses Bit ist 1, wenn SELECT gedrückt wird, und 0, wenn nicht
000
00000 <-- dieses Bit ist 1, wenn START gedrückt wird, und 0, wenn nicht
0000
0000 <-- dieses Bit ist 1, wenn der Pfeil nach oben gedrückt wird, und 0, wenn nicht
00000
000 <-- dieses Bit ist 1, wenn der Pfeil nach unten gedrückt wird, und 0, wenn nicht
000000
00 <-- dieses Bit ist 1, wenn der Pfeil nach links gedrückt wird, und 0, wenn nicht
0000000
0 <-- dieses Bit ist 1, wenn der Pfeil nach rechts gedrückt wird, und 0, wenn nicht
Verstehst du jetzt, warum der Wert 000
10000 ist, wenn START gedrückt wird?
Natürlich kann man auch mehrere Knöpfe gleichzeitig drücken, dann sind eben mehrere Bits 1. Wenn man zum Beispiel gleichzeitig SELECT, nach oben und nach links drückt, ist der Wert in Adresse $15 00101010. Und das ist dasselbe wie #$2A.
Wenn du jetzt überprüfen willst, ob man gleichzeitig SELECT, nach oben und nach links drückt, könntest du folgendes machen:
CodeLDA $15
CMP #$2A
BEQ KnoepfeGedrueckt
[...]
KnoepfeGedrueckt:
[...]
Oder, wenn dir die Binärschreibweise lieber ist:
CodeLDA $15
CMP #%00101010
BEQ KnoepfeGedrueckt
[...]
KnoepfeGedrueckt:
[...]
Wenn man SELECT alleine drückt, ist der Wert in $15 00100000, was dasselbe ist wie #$20. Wenn du überprüfen willst, ob man SELECT drückt, könntest du folgendes tun:
CodeLDA $15
CMP #$20
BEQ KnopfGedrueckt
[...]
KnopfGedrueckt:
[...]
Das würde auch oft funktionieren. Wenn man allerdings zur selben Zeit SELECT und einen anderen Knopf drückt (sagen wir mal SELECT und nach oben), dann würde das im obigen Beispiel nicht als "Knopf gedrückt" zählen. Der Grund: Wenn man SELECT und nach oben drückt, ist der Wert in $15 00101000, und das ist #$28. Der Code würde nicht zu "KnopfGedrueckt" springen, denn du überprüfst ja auf den Wert #$20, nicht #$28.
In den meisten Fällen nimmt man für Knopf-Abfragen
AND statt CMP und
vertauscht BEQ und BNE. Ein besserer Code würde also so aussehen:
CodeLDA $15
AND #$20
BNE KnopfGedrueckt
[...]
KnopfGedrueckt:
[...]
Dieser Code würde zu "KnopfGedrueckt" springen, wenn man SELECT drückt - egal, welche Knöpfe man sonst noch drückt.
Warum das funktioniert und was AND ist... das würde hier zu lange dauern. Ich hoffe, du hast es jetzt etwas besser verstanden.
Zitat von kooooopa: Ok, warum man TAX, etc. brauchen könnte leuchtet mir ein, aber wieso brauche ich PHA, etc. gibt es da irgendeine praktische Anwendung?
Natürlich, jede Menge sogar. Wenn du zum Beispiel Code von SMW veränderst, solltest du die Register vorher auf dem Stack speichern und am Ende wieder zurückholen, denn SMW verlässt sich darauf, dass in den Registern bestimmte Werte sind, mit denen es später weiterarbeiten will. Es gibt noch eine Menge mehr Anwendungsmöglichkeiten, aber mir will sonst gerade keine einfallen.