Da Assembler (wird von mir hin und wieder auch ASM abgekürzt) eine sog. Maschinennahesprache ist, sind zumindest grundlegende Einblicke in die Hardware unumgänglich!HinweisDie Infos dieser Seite sind, neben den ASM-Befehlen, die Basis für jede weitere Programmentwicklung! Dazu schauen wir uns mal grob an, wie der C64 aufgebaut ist und wie der Speicher unterteilt wird.
Das Innenleben des C64
Sehr vereinfacht kann man sagen, der C64 besteht nur aus einem Mikroprozessor (CPU), der durch einen Taktgeber angetrieben wird, etwas ROM & RAM und einer Ein-/Ausgabeeinheit (einfach mal Grafik, Sound, Ports usw. zusammengefasst). Alle Komponenten sind mit mehreren Leitungen verbunden (Bus genannt) um sich austauschen zu können.
Bevor wir das im Detail betrachten, könnt ihr dem folgenden Bild entnehmen, wie das ungefähr aussieht.
Fangen wir links beim Taktgeber an.
Wenn die CPU das Gehirn ist, dann ist der Taktgeber das Herz. Er gibt an, wie schnell die CPU Daten verarbeiten kann. Um diesen Takt zu bilden wird als Basis die Frequenz des sog. „color carriers“ (Farbträgersignal), der zugrundeliegenden Fernsehnorm, verwendet. Das ist auch der Grund, warum ein amerikanischer (besser gesagt NTSC) C64 schneller läuft als ein europäischer (PAL).
Falls euch die genaue Erklärung interessiert:
Die Frequenz des „color carriers“ beträgt bei einem PAL-System 4.43361875 MHz (bei NTSC 3.579545 MHz), die Frequenz wird dann mit 4 Multipilziert (da sämtliche Takte im C64 von diesem Ergebnis abgeleitet werden, spricht man auch von „master clock“ / Haupttakt) und anschließend bei PAL durch 18 (bei NTSC durch 14) geteilt. Somit kommt man auf einen Prozessortakt von etwas weniger als 1MHz (ja MHz!) bei PAL nämlich 4.43361875 MHz * 4 / 18 = 985248 Hz und auf etwas über 1MHz bei NTSC (3.579545 MHz * 4 / 14 = 1022727 Hz). Ein NTSC C64 ist also ca. 3,8% schneller als die PAL-Version.
Die CPU (unser Mikroprozessor) ist vom Typ 6510 (wie bereits an anderer Stelle erwähnt, eine Abwandlung des damals beliebten 6502). Die CPU führt unser Programm aus und verarbeitet unsere Daten. Sie kann über den 16-Bit breiten Adressbus die anderen Komponenten ansprechen und über den Datenbus Informationen lesen und / oder schreiben. Wer bei den Zahlensystemen aufgepasst hat erkennt, dass man mit den 16-Bit des Adressbusses 65536 verschiedene Zustände bilden kann. Da wir ja Profis sind nehmen wir für 1KB 1024 Bytes (statt 1000 Bytes wie es die Hersteller von Speichermedien machen, damit die Festplatte größer aussieht) so kommen wir auf die bekannten max. 64KB Speicher des C64, dazu unten mehr. Da der C64 wegen der 6510 CPU ein 8-Bit Rechner ist, beträgt die Breite des Datenbusses ebenfalls 8-Bit, größere Daten könnte der Prozessor am Stück nicht verarbeiten.
Schauen wir uns mal die drei Hauptkomponenten an, mit denen die CPU „kommuniziert“.
- ROM (Read Only Memorry)
Dies ist ein Speicher aus dem man nur lesen (read only) kann, daher zeigt in der Grafik der Pfeil nur vom ROM zum Datenbus. Außerdem ist der Speicher nicht flüchtig, d. h. auch wenn der Strom abgeschaltet wird, geht der Inhalt nicht verloren. Hier ist z. B. das Betriebssystem gespeichert, damit es nach dem Einschalten sofort zu Verfügung steht. - RAM (Random Access Memory)
Dies ist unser eigentlicher Hauptspeicher, der wird manchmal auch „Speicher mit wahlfreiem Zugriff“ (random access) genannt. Wir können Daten lesen und schreiben (Pfeil zum Datenbus zeigt in beide Richtungen), hier liegen unser Programm und unsere Daten. Allerdings verliert der Speicher bei Stromverlust seinen Inhalt. - Ein- / Ausgabe (kurz E/A)
Hiermit sind z. B. der VIC II (Video Interface Adapter / Grafik), SID (Sound Interface Device / Musik) oder auch die Joystick-Ports und die Tastatur gemeint. Also alles was dem Anwender eine Rückmeldung gibt bzw. eine entgegennimmt, daher zeigt auch hier der Pfeil zum Datenbus in beide Richtungen. Wir können damit also unsere Infos auf den Bildschirm bringen oder die zuletzt gedrückte Taste abfragen. Die E/A ist mit einem entsprechenden E/A-Bus verbunden, so kann z. B. auch der Drucker oder die Floppy angesprochen werden.
Die CPU im Detail
Nun schauen wir noch etwas tiefer in die Hardware, um genau zu sein, wir schauen in die 6510 CPU. Dieser Absatz ist meiner Meinung nach der wichtigste auf dieser Seite! Ihr braucht dieses Verständnis, um die folgenden Seiten überhaupt verstehen zu können!
Der wichtigste Baustein der CPU ist die ALU (Aritmetic Logical Unit). Diese ist für Rechen- und Logik-Operationen zuständig. Die ALU greift dabei auf den Akkumulator zurück und legt eventuelle Ergebnisse auch dort ab.
Der Akku ist eins von 6 Registern, die mit einer Ausnahme jeweils 8-Bit aufnehmen können. Der Akku wird von uns am häufigsten verwendete werden, wir benötigen ihn z. B. zum Rechnen oder für boolsche Operationen.
Neben dem Akku gibt es noch zwei ähnliche Register, das X- & Y-Indexregister. Diese werden häufig für besondere Adressierungsarten (indizierte Adressierung) oder für Schleifen benützt.
Der (Stapel)StackPointer (SP) zeigt auf den zuletzt auf dem Stack (Stapel) abgelegten Wert. Der Stack dient zum kurzfristigen zwischenspeichern von Werten. Ihr könnt ihn euch z. B. als einen Stapel Bücher vorstellen. Das zuletzt oben auf den Stapel gelegte Buch, wird auch immer als erstes wieder entfernt, dies wird LIFO = LastIn/FirstOut-Prinzip genannt. Er hat eine größe von 256 Bytes.
Der ProgramCounter (PC / Programmzähler) ist die eben erwähnte Ausnahme und ist 16-Bit breit. Damit lassen sich die kompletten 64 KByte des C64 adressieren. Er zeigt immer auf die nächste Anweisung, die ausgeführt werden soll. Wie ihr in der Grafik seht, habe ich den Adressbus in ein Low- & High Byte getrennt. Das liegt daran, dass die Adressen in ein hohes und ein niedriges Byte getrennt werden. LSB (Least Significant Byte) und MSB (Most Significant Byte) sind hier die Begiffe, die uns häufig begenen werden. Werden lsb und msb kleingeschrieben, so bezieht es sich auf Bits statt Bytes. Das LSB wird im Speicher zuerst abgelegt, das sehen wir uns später bei den Befehlen noch genauer an.
Das StatusRegister (SR) ist unsere Informationszentrale, hier können wir z. B. erkennen, ob das Ergebnis einer (Rechen)Operation negativ war. Von seinen 8-Bit werden aber nur sieben benutzt.
Bit Flag Wird auf 1 gesetzt, wenn --- ---- ------------------------------------------------------- 7 N das Ergebnis negativ ist 6 V es zu einem Überlauf kam 5 - ...(unbenutzt immer 1) 4 B ein Abbruch (Break) auftrat 3 D man im BCD-Format (Binary Coded Decimal) rechnen möchte 2 I Interrupts (Unterbrechung) gesperrt sind 1 Z das Ergebnis 0 ist 0 C es einen Übertrag gibt
Die Wichtigkeit dieses Registers kann man daran erkennen, dass es eigene Befehle zum Setzen, Löschen, Prüfen und sogar zum „Retten“ auf dem Stack gibt. Das sehen wir alles gleich bei den Assemblerbefehlen.
Das wären also die „wichtigsten“ Bestandteile unseres C64, schauen wir uns nun den Speicheraufbau an.
Speicheraufbau des C64
Den Speicher können wir uns zunächst als eine Straße mit 65536 Hausnummern (von 0 bis 65535) vorstellen. Jedes Haus steht dabei für ein Byte des Speichers. Es gibt hier allerdings nicht nur eingeschossige Häuser, sondern auch welche mit zwei oder gar drei Etagen. So wie wir eine Adresse benötigen, um ein bestimmtes Haus in einer Strasse zu finden, so benötigen wir auch die (Speicher)Adresse, um z. B. etwas ins RAM zu schreiben oder um von dort zu lesen. Da unser Computer nur eine Strasse hat, reicht uns als Adresse die Hausnummer.
Sehen wir uns den Aufbau einfach mal an:
Ganz oben in hellblau seht ihr den kompletten Adressraum des C64 (64 KBytes). Die gesamten 64 KByte des C64 werden in sog. Pages (Seiten) zu je 256 Byte unterteilt. Die Pages sind von 0 bis 255 durchnummeriert und beginnen mit der sog. „Zero Page“. Wir kommen somit also auf 256 Pages x 256 Bytes = 65536 Bytes = 64 KBytes. Der Speicher sieht zunächst schön glatt und einfach aus, aber er steht uns normalerweise nicht vollständig zur eigenen Verfügung. Die bunten Kästchen im unteren Teil der Grafik zeigen, was sich wo befindet, da ist dann schon mehr los.
Die Adressen werden im Laufe der Zeit sehr wichtig, weil wir festlegen müssen wo unser Programm und unsere Daten gespeichert werden oder wo wir z. B. den Bildschirmspeicher finden, um einen Text auszugeben.
Da wir in Assembler programmieren, werde ich ab jetzt nur noch die hexadezimale Schreibweise für die Adressen verwenden.
$0000 – $03FF: Das erste Kilobyte ist größtenteils für die CPU reserviert und beginnt, wie eben erwähnt, mit der Zero-Page ($0000 – $00FF). Hier lässt sich das Verhalten des C64 beeinflussen und lassen sich aktuelle Status abfragen. In Page-1 ($0100- $01FF) legt der Stack seine Daten ab. Page-2 & 3 enthalten größtenteils Werte für das Betriebssystem (z. B. aktuelle Zeichenfarbe oder den Kassettenpuffer).
Wir sollten also sehr vorsichtig sein, wenn wir im ersten KByte unsere Programme oder Daten ablegen wollen.
$0400 – $07FF: Hier liegt (sofern er nicht verschoben wurde) der Bildschirmspeicher. Den haben wir z. B. im BASIC- <=> Assemblervergleich benutzt. Der Bildschirm besteht bekanntlich aus 40 Zeichen x 25 Zeilen, also 1000 Bytes. Das KByte für den Bildschirmspeicher wird ab $07F8 durch acht Register für die Sprites vervollständigt, dort wird der Speicherbereich für die Spritedaten eingetragen (vgl. BASIC-Demo: Sprites).
$0800 – $9FFF: Dort befindet sich das BASIC-RAM, also der Speicher in dem unsere eingetippten BASIC-Programme und -Daten landen. Da BASIC normalerweise nicht auf den freien RAM-Bereich von $C000 – $CFFF zugreifen kann, wisst ihr nun auch, wie die Meldung 38911 BASIC BYTES FREE nach dem Einschalten des C64 zustande kommt. Den Bereich des BASIC-RAMs können wir durchaus für unsere Assembler-Programme benutzen, das macht z. B. das ASM-Programm aus dem BASIC- <=> Assemblervergleich. Es speichert ab $0801 den BASIC-Kopf (2018 SYS 2062) und das eigentliche ASM-Programm beginnt dann bei ($080e => 2062). Würden wir nach dem Laden des Programmes z. B. noch weitere BASIC-Zeilen eintippen, so würde unser Programm wieder überschrieben werden.
$A000 – $FFFF: Diesen Speicherbereich können wir ebenfalls nutzen, allerdings beginnen hier auch die Häuser mit zwei oder drei Etagen.
Die in diesen Bereich einblendbaren Komponenten sind:
- $A000 – $BFFF: Hier wird das BASIC ROM (nicht mit dem BASIC-RAM ab $0800 verwechseln) eingeblendet. Es enthält fast das komplette BASIC des C64, also alles was benötigt wird, um eure eingegebenen BASIC-Programme überhaupt laufen lassen zu können. Da das BASIC aber recht groß ist und mehr als 8 KBytes benötigt, finden wir den Rest ab $E000 im Kernal ROM.
- $C000 – $CFFF: Endlich ein freier Speicherbereich, den wir unter ASM einfach verwenden können, das BASIC kann hierauf nur mit PEEK & POKE zugreifen.
- $D000 – $DFFF: Die Ein- / Ausgabe teilt sich diesen Speicherbereich mit dem Zeichen ROM s. nächster Hauptpunkt. Wie die Grafik zeigt, teilen sich mehrere Ein- / Ausgaben diesen Speicher.
- $D000 – $D3FF: Die Register für den Grafikchip VIC II sind hier zu finden. Wir haben diese schon bei den Sprites verwendet, hier findet ihr eine Liste VIC-II-Register. Da es insg. nur 46 Register gibt, ist der Bereich von $D02F – $D3FF unbenutzt.
- $D400 – $D7FF: Der Soundchip SID hat hier sein Zuhause. Auch hier werden nur wenige Speicherstellen (nämlich die ersten 28) vom Standard C64 benutzt (Liste der SID-Register).
- $D800 – $DBFF: Um den Zeichen auf dem Bildschirm eine Vordergrundfarbe zuzuweisen, wird das hier beheimate Farb-RAM verwendet. Da wir ja wissen, dass der Bildschirm (BS) nur 1000 Zeichen (40 x 25) benötigt, erkennen wir direkt, dass 24 Bytes unbenutzt sind. Für die Vordergrundfarbe setzten wir das untere Nibble. Die Hintergrundfarbe lässt sich nicht für jedes einzelne Zeichen setzen. Man kann diese Farbe nur für je 64 Zeichen separat angeben.
- $DC00 – $DCFF: Der C64 besitzt zwei CIA-Chips (Complex Interface Adapter). Der erste wird als CIA-1 (wat ne Überraschung) bezeichnet. Seine Register sind hier zu finden. Der CIA-1 kümmert sich z. B. um die Tastatur, Joysticks, Datasette, Userport, IRQ-Steuerung (Interrupts) und Paddles.
- $DD00 – $DDFF: Die Aufgaben des CIA-2 sind z. B. die RS-232-Schnittstelle, der Userport, die NMI-Steuerung und die VIC-II Speicheradressierung.
- $DE00 – $DFFF: Dieser Bereich ist frei und für Erweiterungen gedacht.
- $D000 – $DFFF: Es ist kein Tippfehler, dieser Speicherbereich ist tatsächlich dreifach vergeben: RAM, E/A und das CHAR (Zeichen) ROM, hier sind die beiden Standard-Zeichensätze des C64 hinterlegt. Jeder Zeichensatz besteht aus 256 Zeichen, jedes Zeichen aus 8×8 Pixeln (Bildpunkten), also 8 Byte je Zeichen. Somit kommen wir auf die 4 KByte (2 x 256 x 8), die hier belegt sind.
- $E000 – $FFFF: Das Kernal ROM ist vergleichbar mit dem BIOS von PCs. Hier finden wir die Kernal-Routinen (Systemroutinen), die wir von Assembler direkt anspringen können und die uns das Leben leichter machen können. Außerdem ist hier alles zufinden, was der Rechner z. B. nach dem Einschalten oder nach einem RESET machen soll. Wie erwähnt, ist zunächst der Rest des BASIC-ROMs von $E000 – $E4D2 gespeichert, ab $E4D3 bis $FFFF kommen dann die Kernal-Routinen.
So nun wissen wir, wie der Speicher aussieht, aber was soll das mit der Doppelt- oder gar Dreifach-Belegung?
Hier kommen wir endlich auf den Hauptunterschied zwischen dem 6502 und unserem 6510. Diese Mehrfachbelegung, von Speicherbereichen beherrscht nur der 6510. Über das zweite Byte der Zero-Page (an der Adresse $01) lassen sich die einzelnen Speicherbereiche umschalten (bankswitching).
Auch das erste Byte (Adr. $00 / 6510 On-Chip I/O Data Direction Register) findet man in dieser Form nur beim 6510. Auf die Zero-Page werden wir später zurück kommen, sie spielt bei der Programmierung dieser Prozessoren ein besondere Rolle.
Da es so schön zum Thema passt, hier ein Leserbrief (zum Unterschied zwischen dem 6502/6510) aus der „Compute!“, einem alten US-Magazin:
Über die Zero-Page, an der Adresse $0001, lassen sich die einzelnen ROMs oder das RAM in den entsprechenden Speicherbereich einblenden.
Inhalt von $0001 Bit Aufgabe 0 1=BASIC ROM / 0=RAM 1 1=KERNAL-ROM / 0=RAM (BASIC verschwindet auch!) 2 1=E/A / 0=RAM (verschwindet auch sobald 0 & 1 null sind) 3 Datasette: Datenausgabe 4 Datasette: 0=Taste gedrückt / 1=KEINE Taste gedrückt 5 Datasette: 0=Motor an / 1=Motor aus 6 immer 0 (unbenutzt) 7 immer 0 (unbenutzt)
Ihr könnt euch also durch ein POKE 1, PEEK(1) AND 252 das gesamte RAM des C64 sichern, nur geht dann leider gar nichts mehr, ein RESET ist fällig, aber bis dahin gehören die 64 KByte euch 😉 .
Um mal wieder auf die Zahlensysteme zu verweisen (ja ich nerve, aber ich kann es nicht oft genug betonen: Die sind immens wichtig!): Wie kann uns der gesamte Speicher gehören, wenn wir doch nur die Bits 0 und 1 auf Null setzen und somit nur BASIC und KERNAL-ROM ausblenden? Dies liegt daran, dass das E/A-ROM auch automatisch ausgeblendet wird, sobald man die ersten beiden Bits auf 0 setzt. Nur der Vollständigkeit wegen, auch wenn Bit 1 offiziell nur das KERNAL-ROM ausblendet, wird automatisch ebenfalls das BASIC ROM deaktiviert.
Was nützt es uns nun, diese ROMs auszublenden, wenn man dann doch nichts mehr mit dem Rechner anfangen kann? Nun, wir müssen nur dafür sorgen, dass das entsprechende Programm auch ohne die ROMs auskommt oder wir können z. B. vor dem Abschalten das ROM ins darunterliegende RAM kopieren. Dies eröffnet uns dann zusätzlich die Möglichkeit die kopierten ROM-Inhalte (die liegen jetzt ja im RAM und sind somit nicht mehr „schreibgeschützt“) zu verändern, wir können aber auch nicht benötigte Teile überschreiben, um mehr Speicherplatz für unsere Programme zu haben.
Ich hoffe ihr bleibt weiter am Ball, denn als Nächstes legen wir endlich mit dem Programmieren los und schauen uns in Ruhe alle Assemblerbefehle (Mnemonics) an. Aber keine Angst, es wird keine Trockenübung!! Wir werden viele Beispiele im Emulator unter die Lupe nehmen.
WOW! eine Zeitreise in meine frühe Jugend! Ich habe damals auch mit Turbo Assembler die Nächte durchgehackt und meine ersten Spiele u.a. auch mit Basic programmiert. Das waren schöne Zeiten. Heute arbeite ich mit so abstrakten Dingen wie Python und vermisse doch schon sehr das low level.
vielen Dank für dieses tolle Tutorial, vielleicht finde ich mal wieder Zeit, das alte Wissen aufzufrischen.
Hallo,
nur mal so gefragt: Im Text steht, dass E/A auch deaktiviert wird, sobald die ersten beiden Bits von $01 (BASIC und Kernal) abgestellt sind und auch, dass das Abstellen vom Kernal auch BASIC deaktiviert. Bedeutet das, dass man den Kernal und das BASIC-ROM loswerden kann, ohne gleichzeitig auch E/A zu deaktivieren? Oder meintest du nur, dass auch BASIC nicht mehr klappt, wenn man das Kernal-ROM deaktiviert, da BASIC ja auch Teile des Kernal-ROMs nutzt? Wieso ist es eigentlich so, dass E/A sich abschaltet, wenn man BASIC und den Kernal abstellt?
Gruß
Julian
(das waren viele “abgestellt”s, da sieht man mal wieder, was für einen riesigen Wortschatz ich habe 😉 )
Hallo Julian,
das 2. Bit steuert eigentlich nur, ob E/A (1) oder Zeichen-ROM (0) sichtbar ist.
Sobald die unteren beiden Bits (0 & 1) auf 0 gesetzt werden, ist aber das RAM sichtbar.
Das mit dem BASIC ist evtl. missverständlich, liegt vielleicht daran, dass dies einer meiner ersten Beiträge 2012 war.
Sobald Bit 1 auf 0 gesetzt wird, verschwindet auch das BASIC-ROM.
Wie bereits im anderen Post erwähnt, sollte ich das hier mal überarbeiten.
Gruß,
Jörn
Ahhhh, jetzt macht’s Sinn. Eigentlich ja irgendwie ganz schlau, schließlich macht es wenig Sinn, BASIC ohne den Kernal zu nutzen, obwohl es vielleicht leichter gewesen wäre, einfach eines der unbenutzten Bits von $01 mit dem Char-Rom zu kuppeln aber … nun ja. Es geht ja und das hätte nur sehr wenige Möglichkeiten eröffnet.
Gruß
Julian
Hallo,
warum ist es eigentlich besser mit den Hexadezimalzahlen bzw sich diese einzuprägen zu arbeiten?
Ich habe in den 80er Jahren meine ersten Schritte (so wie wohl fast jeder) auf dem C64 mit Basic gemacht und dort dann natürlich auch Peer/Poke benutzte (bzw. benutzen müssen) um Register etc. direkt anzusprechen. Deshalb sind mir die Register, Speicherbereiche etc. in Dezimalzahlen geläufiger.
Beim Programmieren in AMS, das ich jetzt dank deines tollen Kurses wieder aufgenommen habe (ich arbeite per Emulator bzw. auch direkt am C64 mit Turbo Assembler) kann ich ja problemlos auch mit Adressen etc. in Dezimalzahlen arbeiten. Bringt das irgendwelche Nachteile oder ist das einfach Geschmacksache?
Hallo Anton,
wie du schon schreibst, ist es dem Assembler natürlich vollkommen egal, wie man die Adressen schreibt. Im Speicher landen immer die selben Nullen und Einsen.
Da Assembler eine systemnahe Programmiersprache ist, fühlen sich für mich dort Hex-Adressen einfach besser an, da sich diese nahezu direkt aus dem System ergeben.
Außerdem finde ich, dass die Verwendung von unterschiedlichen Zahlensystemen die Lesbarkeit eines Assemblerprogrammes verbessern kann.
Ich nutze unter Assembler Hex-Zahlen für Adressen, binäre für Register-Inhalte und Dezimalzahlen für den Rest (z. B. Anzahl Leben, Energie, Koordinaten usw.).
Aber wie von dir vermutet, ist die Schreibweise im Endeffekt geschmackssache. Wichtig ist eigentlich nur, dass man die gängigen Zahlensysteme beherrscht.
Gruß,
Jörn
Danke für die Antwort, Jörn.
Das Verwenden verschiedener Zahlensysteme zur besseren Lesbarkeit von Assembler-Programmen ist auf jeden Fall eine gute Idee, die ich aufgreifen werde.
Spannend, ich habe Programmieren auf dem Schneider CPC mit dem Z80 gelernt. Das Bank Switching war da besser gelöst. Man konnte nämlich beliebig auf beide Teile zugreifen, man musste nur eben dafür sorge tragen, daß der richtige Bereich entsprechend aktiviert wurde. So wurde z.B. auch das Bank Switiching für die Speichererweiterung auf 512k gehandhabt. Es wurden immer 16k bereiche ein und ausgepaged.
Irgendwie verstehe ich nicht, warum das nicht hier auch so gehen sollte. Byte 00 und 01 entsprechend setzen und auf Roms zugreifen … Byte 00/01 setzen und in RAM schreiben, bzw. davon lesen.
Kann man nicht einfach die Bank Switching logik im BASIC RAM ablegen und hat somit immer zugriff darauf und man kann dann das RAM was unter dem Kernel ROM liegt auch verwenden (ein und ausblenden)?
Hallo, mich würde mal interessieren, wie man per Hand – also mittels nasm – den netwide assembler – unter Linux, Diskimages erstellt und BASIC oder Assembler (sicherlich binär) erstellt.
Gibt es dazu Infomaterial?
ich bin mir nicht ganz sicher, was du genau machen willst. .. aber ich glaube, du suchst nach
einem cross-assembler. Sehr kann ich die Kombination von Kickassembler / Sublime / Vice Emulator empfehlen … dann kannst du unter Linux deinen code schreiben und direkt auf dem vice emulator testen ,…
Alles Liebe aus Zurich, Stephan
Im Speicheraufbau steht, wenn ich das richtig sehe, eine falsche Adresse für den Beginn der Spritesteuerung. Dort steht ab $07E8 beginnt der acht Byte breite Bereich. Es müsste aber wohl $07F8 sein.
Das hat mich erst etwas verwirrt, daher der Hinweis zur Korrektur.
Ist korrigiert, vielen Dank für den Hinweis und sorry für die Verwirrung.