PET 2-Pass Assembler v4.7 mit PROGRAM-LOADER - (BASIC4)

  • Anbei die neue Version des Assembler für den PET (BASIC 4).

    Der Assembler ist als ROM für $9 oder alternativ $A (BIN Files).


    Zum testen im RAM habe ich eine Version für die Adresse 25000 assembliert (nur Assembler, ohne Program Loader).

    Einfach mit DLOAD laden, NEW eingeben, und mit SYS25000 aktivieren.




    Was ist neu?

    • Fehlerbereinigung - alle gemeldeten Fehler sind gefixed
    • eine kleine Doku als Textfile im ZIP
    • Assembler Befehle starten mit "." statt mit '
    • Die Zahlenumwandlung wird mit ".," gestartet
    • neuer Befehl: "Binary Save" - das assemblierte Programm kann nun auf Diskette gespeichert werden
    • die ROM Versionen haben den PROGRAM-LOADER mit dabei, der mit .p gestartet wird
    • die ROM Versionen haben die BSOS Kennung voran gestellt, deswegen aktiviert sich das ROM mit BSOS automatisch



    Eine BASIC 2 Version für den CBM 3032 als Beta Version siehe hier:

    Welchen Assembler könnt Ihr empfehlen?

  • Manual:


    2 Pass Assembler v4.7 für PET (BASIC-4)

    =======================================



    Der Assembler ist für das Zusatz ROM (wahlweise $9000 oder $A000).

    Man kann den Assembler auch wahlweise an die dezimale Adresse 25000 laden zum testen.



    1. Eingabe des Assembler Source Code:

    ------------------------------------


    Der Sourcecode wird einfach wie ein BASIC Programm eingegeben.

    Man braucht dazu nur einen ganz normalen PET ohne Erweiterung.

    Der Sourcecode kann ganz normal DSAVE gespeichert und mit DLOAD geladen werden.


    Es ist ganz genau wie bei einem gewöhnlichen BASIC Programm.


    Nur kann man den Source Code natürlich NICHT mit dem Befehl RUN starten.

    Der BASIC Interpreter kann mit dem Assembler Sourcecode nichts anfangen.



    2. Befehls Erweiterung:

    ----------------------


    2.1 Neue Befehle:

    ----------------


    Die Assembler Befehlserweiterung wird mit SYS 25000 (bzw. 36868 und 40964) aktiviert.

    Wenn man BSOS als Betriebssystem hat, dann wird die Assembler Befehlserweiterung automatisch aktiviert.



    Danach gehen folgende Kommandos:


    .a ... (assemble) kompiliert den Assembler Sourcecode


    ., ... Zahlen Umrechnung und Ausgabe der Label Adressen (nach .a)


    .k ... (kill) schaltet die Befehlserweiterung aus


    .p ... (program-loader) startet den Program-Loader mit SD2PET Unterstützung (CD Kommando)


    .s ... (binary save) speichert das assemblierte Maschinen-Programm auf die Diskette (oder Tape)




    2.2 Formel Auswertung:

    ---------------------


    Die Formel Auswertung ist eine zentrale Funktion des BASIC Interpreter im PET.

    Er ermöglicht die Berechnung umfangreicher mathematischer Ausdrücke.


    Die Assembler Befehlserweiterung bietet zusätzliche Funktionen für die Formel Auswertung.

    So sind nun neben den dezimalen Konstanten auch hexadezimale und binäre Konstanten erlaubt.

    Den hexadezimalen Zahlen ist ein $ Zeichen vorangestellt und können 2 oder vierstellig sein.

    Die binären Konstanten beginnen mit einem % Zeichen und können 4,8,12 oder 16 stellig sein.

    Die neuen Konstanten können überall in einer mathematischen Formel vorkommen.


    Es gibt die zwei neue Operatoren < (Low Byte) und > (High Byte).

    Hinter den Operatoren < und > kann ein beliebiger mathematischer Ausdruck folgen.


    Die neue Formelauswertung funktioniert im Direktmodus und auch in BASIC Programme.


    So sind jetzt zb. folgende Dinge möglich:


    PRINT 12 + $2341 * %0110

    B = $E834 + 2

    A = <(B + $2001 * 3)



    3. Aufbau des Assembler Source Code:

    -----------------------------------


    3.1 Zieladresse und Ablageadresse:

    ---------------------------------


    Vor dem ersten Assembler Befehl muss die Zieladresse angegeben werden mit: *=adresse

    Alternativ kann man den Code auch an einer anderen Adresse speicher: &=ablageadresse


    Die Zieladresse ist jene Adresse, auf der das Programnm später laufen soll.

    Die Ablageadresse ist jene Adresse, an der das Programm vom Assembler gespeichert wird.

    Wenn man keine Ablageadresse definiert, dann nimmt der Assembler die Zieladresse an.


    Zb. man möchte ein Programm für den $A ROM Bereich assemblieren.

    Aber da ist kein RAM deshalb kann man den Code dahin nicht speichern.

    Also hilft man sich mit einer Ablageadresse im RAM, zb. auf 20000:


    10 *=$A000:&=20000

    20 ldx ...


    Nach dem Assembliervorgang speichert man das Programm ab und brennt es auf EPROM:


    .s"tool-$a"



    3.2 Kommentare:

    --------------


    Sourcecode sollte immer kommentare enthalte, damit man sich später wieder zurecht findet.


    Kommentare beginnen mit einem Stricjpunkt: ";"


    10 ; --- ich bin ein Kommentar -------

    20 lda #32 ;lade ein Blank " " in den AC



    Kommentare werden vom Assembler ignoriert und kosten keinen Platz im assemblierten Code.



    3.3 Assembler Code:

    ------------------


    Der Assemblercode besteht aus einem Befehl (6502 Memnonic / OPC) und optional weiteren Operanden.

    Befehle können einen oder mehrere Adressierungsarten haben.

    Mehr dazu in einem einschlägigen 6502 Assembler Buch.


    Die Syntax ist die gängige Notation.

    Nach dem Memnonic muss ein Blank kommen (Ausnahme: Befehle ohne Operand)


    Die Befehle ASL, ROR, LSR und ROL stehen allein wenn sie sich auf das A Register beziehen.


    Zeropage Befehle werden automatisch erkannt und verwendet, wenn der Operand ein Bytewert ist (0 bis 255).

    Deshalb müssen ZP Labels definiert sein, bevor sie verwendet werden.


    Beispiele:


    10 lda #1

    20 stx 23

    30 lda $8000

    40 lda $70,x

    50 pha

    60 sta ($77),y

    70 jmp ($0345)

    80 asl



    Wie in BASIC können auch mehrere Befehle in einer Zeile hintereinander geschrieben werden:


    10 ldx #4:cmp 2000,x:dex:bne



    Um den Code von den Labels abzuheben, kann er optional mit einem oder mehreren : eingerückt werden.


    10 label

    20 :ldx #23



    3.4 Label und Variable:

    ----------------------


    Im Gegensatz zu BASIC Variable können Labels und Assembler Variable beliebig lang sein.

    Die Labels stehen für die "aktuelle" Adresse im Assembler Code.

    Damit kann man beliebige Punkte imn Code ansprechen, ohne die Adresse kennen zu müssen.


    10 :ldx #3

    20 loop

    30 :sta buffer,x

    40 :dex

    50 :bpl loop

    60 :rts

    70 :

    80 buffer

    90 .0,0,0



    Assembler Variable werden wie BASIC Variable definiert.

    Mit dem = Zeichen wird den Variablen ein Wert zugewiesen.


    10 hp =17

    20 screen=$8000

    30 rom =$9000



    3.5 Datenfelder:

    ---------------


    Neben 6502 Befehle können im Sourcecode auch Datenfelder vorkommen.


    Datenfelder beginnen mit einem ".".

    Nach dem Punkt können beliebig viele Werte folgen, getrennt durch einen Beistrich.

    Die Werte können Byte- (8 Bit) oder Word (16 Bit) Werte sein.



    100 .23,2345,$22,%10000001, "hello",0




    3.6 Ausdrücke:

    -------------


    Der Assembler kann Berechnungen durchführen.

    Jeder Operand im Sourcecode und jede Datenstruktur wird vom Assembler berechnet.


    Es ist alles möglich, was auch im BASIC funktioniert.

    Klammern, Funktionen, Konstanten, natürlich Addition/Subtraktion/Multiplikation ...


    Durch die veränderte Formelauswertung können alle Erweiterungen beliebig kombiniert werden.

    Dazu zählen binäre und hexadezimale Konstanten, Low- und Highbyte und Assembler Labels.



    Zahlen im Quellcode können wie folgt angewendet werden:


    dezimal: 12345

    hex2: $12 oder hex4: $2045

    binär: %10011100 (4, 8, 12, oder 16 stellig)

    ASCII: "A"

    ASCII: 'P'



    Der Befehl ".," ermöglicht das spielerische Erlernen der Funktionalität.

    Unmittelbar nach einem erfolgreichen Assemblier Vorgang kann ".," auch Assembler Labels auswerten.


    Beispiele:


    .,200

    .,$20

    .,%11001001

    .,"a"

    .,loop


    oder komplex:

    .,loop+1

    .,$ea44 + 23

    .,>$3412

    .,<loop

    .,>loop

  • Als $9 ROM wird der Assembler aktiviert mit SYS 36868


    Mit BSOS ist der Assembler automatisch nach jedem Reset aktiviert.




    Der PROGRAM-LOADER wird mit .p gestartet:




    Der Assembler Vorgang wird mit .a gestartet.


    Wenn erfolgreich, dann kann das Programm als Binärcode direkt gespeichert werden mit: .s"name"




    Alternativ kann mit dem .s Befehl jeder beliebige Speicherbereich auf Disk gespeichert werden:




    Man sieht im Screenshot dass beide Dateien erstellt wurden.

  • Also ich habe mir eben mal ein Eprom gebrannt und den Assembler in meinen 8032 eingesetzt an Adresse $A000. Der Assembler wird mit sys 40960 und nicht mit sys 40964 gestartet. Dann habe ich ein kleines Testprogramm geschrieben.


    10 *=$0401 Startadresse RAM

    20 lda #$01 Schreibe den Wert 1 in den Akku

    30 sta $8100 Speichere Akku-Inhalt an Speicherstelle $8100,dh, wirf mir ein a auf den Bildschirm

    40 rts Return from subroutine...also Ende


    Danach starte ich den Assembler mit sys 40960 und dann mit ".a". Dann bekomme ich immer eine Fehlermeldung.


    undefined statement error in 141.


    Was mache ich falsch ?



    Dann noch eine Frage. Wenn ich ein kleines "Hallo Welt" Programm schreibe, würde ich es aus Gewöhnung so machen:


    *=$0401 ; Startadresse 401h

    lda #$00 ; lösche akku

    tax ; lösche x Register bzw kopiere 0 von Akku

    tay ; lösche y Register bzw kopiere 0 von Akku

    loop: lda message,x ; lade byte+x aus message

    sta $8000,x ; speichere an Screen+x

    inx ; inkrementiere x

    cpx $0c ; vergleiche x mit 0ch, also 12d

    bne loop ; branch wenn nicht 12d, springe zu loop zurück, ansonsten weiter

    rts

    ;

    message="hallo welt !"



    Wie kann ich branch Befehle mit Zeilennummern umsetzen ? Einfach zB "BNE <Zeilennummer>" eingeben ?

    Und, wie mache ich das mit define bytes ? Kann ich da auch mit Labels arbeiten, und die dementsprechenden bytes werden beim assemblieren direkt hinter den Code gesetzt ?



    Jedenfalls tolles Projekt ! Es macht mir riesen Spaß, mal ein wenig am 8032 zu arbeiten bzw. zu lernen ! Ein Hoch auf Grünbildschirme !


    Vielen Dank !


    Gruß Jan

  • Hallo Jan


    Ich schau es mir abends nach Dienst an.


    Hab keinen 8032, aber auf meinem 8296 läuft es tadellos.


    Starten tut man es nicht mit SYS 40960 sondern mit SYS 40964.

    Das liegt daran, weil die ersten 4 Bytes die BSOS Kennung im ROM ist.


    Vielleicht liegt es daran?


    ==============


    Dein Testprogramm ist vollkommen in Ordnung.

    Allerdings ist es nicht klug, die Startadresse auf $0401 zu legen.

    Dein Sourcecode liegt genau an der Adresse. ;)


    10 *=$2000

    20 lda #$01

    30 sta $8100

    40 rts

    sys $2000


    so funktioniert es ...


    =============


    Dein "Hello Word" Programm müsste dann so aussehen:


    Labels haben keinen : nach dem Namen, wobei vermutlich würde der einfach ignoriert werden


    Datenfelder beginnen einfach mit einem ".", das ist dann so wie DB oder .Byte bei anderen Assembler.

    Kann ich aber auch noch anpassen, damit es einheitlich ist.



    Es kann aber sein, dass "Hello Word" nicht wie gewünscht arbeitet.

    Beim 8032 ist PETSCII nicht gleich Bildschirmcode, zumindest nicht vollständig gleich.


    Der String nach "message" ist PETSCII.

    Das sollte man über die Kernal Routine BSOUT ausgeben (FFD2).


    Code
    60 lda message,x   ; lade byte+x aus message
    70 jsr bsout       ; zeichen ausgeben
    
    
    10000 bsout=$ffd2
  • Allerdings ist es nicht klug, die Startadresse auf $0401 zu legen.

    Dein Sourcecode liegt genau an der Adresse. ;)

    Was passiert bei

    10 *=$0401


    Auf $0401 liegt dein Sourcecode als BASIC Text.



    mit .a fängt der Assembler an, den BASIC Text zu lesen und Assembler Code ab $0401 abzulegen.

    Und damit zerstört er den Sourcecode

    Es ist wie wenn man POKE 1025,xx, POKE 1026, yy … macht.


    Deswegen bitte etwas oberhalb des Sourcecode.

    Ich verwende gerne dezimale Adressen ganz weit oben (20000 oder 25000).


    ======


    Anmerkung:


    Wenn der Code später wirklich auf $0401 liegen soll, dann geht das so:


    10 *=$0401:&=20000



    Der Assembler assembliert den Sourcecode FÜR die Adresse $0401.

    Aber er legt den Binärcode in den Speicher ab Adresse 20000 (damit kein Konflikt ist mit dem Sourcecode).

  • Ok, vielen Dank für die Info !


    Mit sys40964 startet der Assembler hier nicht. Nach Eingabe von zb .a schreibt das Basic Syntax Error.

    Wenn ich mit sys40960 starte und dann .a eingebe, startet der Assembler wie er soll.


    Ah, das mit der Basicstartadresse 401 leuchtet mir auch ein. Stimmt, da steht ja dann der Source.. :)


    Gruss Jan

  • Also, im VICE als Model 8032 funktioniert es tadellos:




    wie erwartet erscheint in der Zeile 4 ein "a" nach dem SYS 20000


    es ist ein "a" weil der Bildschim Code 1 (lda #$01) ein "a" darstellt.

  • Ja, ich finde es fantastisch das die alten Dinger noch funktionieren. Ich habe mir gerade heute erst ein 8032-32B gekauft und hole mir den am Wochenende ab. Meine Frau schüttelt nur noch mit Kopf :) Ich habe parallel ein C64 und C128 und versuche mich da am Thema Assembler und habe auch schon einige Catridges selber gebaut/gebrannt.


    Zum Thema "Ein eigenen Assembler" programmieren möchte ich gerne auf Dein KnowHow zugreifen, wenn es für Dich OK ist. Ich habe da einige Fragen um zu verstehen :)


    Beste Grüße

    Marco

    Ich suche: Atari 800, MPF-IP

  • Ich würde auch soooooo gerne Assembler können... kleine lustige Spiele für die CBMs basteln.

    Basic ist da einfach witzlos langsam- und Assembler unglaublich schwer zu kapieren für mich.


    Glückwunsch übrigens zum 8032! ;)


  • Ja der FAF (Frauen Akzeptanz Faktor) ist bei Retro Computer ziemlich bei Null, kenne ich. :D




    Denselben Assembler gibt es auch für den C64.

    Da habe ich auch noch ganz andere Sachen implementiert.

    • Durchscrollen des Source Code mit den F Tasten
    • LIST einer ganzen Seite ausgehend von einer gewünschten Zeilennummer
    • Löschen vom Cursor rechts bis Zeilenende
    • FIND Funktion für Strings und Befehle im Sourcecode
    • DEL - löschen von Zeile bis Zeile
    • UNNEW ...
    • ... und noch viele viele Dinge ...

    Das ganze heisst EX-ASS (extended Assembler).


    Muss ich mal raus suchen bei den alten Disketten.



    Ja wenn du Fragen hast, jederzeit gerne

  • Ich würde auch soooooo gerne Assembler können... kleine lustige Spiele für die CBMs basteln.

    Basic ist da einfach witzlos langsam- und Assembler unglaublich schwer zu kapieren für mich.


    Glückwunsch übrigens zum 8032! ;)

    Danke für die Glückwünsche. Er sah auf den Bildern schon ein wenig lädiert aus :) Mal sehen was sich daraus machen lässt.


    Vielleicht machen wir hier mal ein Assembler Kurs (für Anfänger). Ggf. auch auf einem Treffen!


    Beste Grüße

    Marco

    Ich suche: Atari 800, MPF-IP

    Einmal editiert, zuletzt von discmix ()

  • und Assembler unglaublich schwer zu kapieren für mich

    Alles halb so wild.

    Man muss sich nur erst an diese Denkweise gewöhnen.


    Wir können ja einen kleinen Assembler Kurs für Anfänger machen.

  • Juhu Jungs!


    Assemblerkurs: GERNE!

    Wenn nur dieser Corona-Mist endlich mal entspannter wäre... ich bin ein Mensch, der sich tendenziell lieber persönlich trifft.

    Vielleicht ergibt sich das mal auf einem Retro-Computer-Treffen? Würde mich wirklich freuen, auch wenns komplett sinnbefreit ist, auf einem knapp 40 Jahre alten Schinken Assembler programmieren zu können. :D


    Viele Grüsse,
    Matthias

  • Ja, ein Treffen auf ein Bierchen (oder zwei oder drei) wäre wirklich schön.

    Leider wohnen wir halt alle sehr weit voneinander entfernt.


    Sinn?

    Bei unserem Hobby darf man sich nie die Sinn Frage stellen.


    Es zählt was Spaß macht!

    Wenn es Spaß macht ist es gut.

    Wenn nicht, sollte man was anderes tun.



    Assembler ist simpel.

    Das hat man schnell raus.


    Was aber hinzu kommt, man muss die Hardware sehr gut kennen.

    Auf Bit und Byte.

    Nur dann macht das Sinn.

    Stelle dir ein BASIC vor, das mit POKE und PEEK auskommen muss.


    Natürlich kann man auf Betriebssystem Routinen zugreifen.

    Aber dann muss man halt da Wissen aufbauen.

    Einsprungadressen, APIs, Speicheraufbau ...

  • Assemblerkurs: GERNE!

    Trockene Theorie mag niemand.

    Oder doch?


    Ansonsten würde ich vorschlagen, man denkt sich einfache Übungen aus und versucht diese gemeinsam zu implementieren.

    So wie mein Beispiel oben das den Bildschirm mit Zeichen füllt.

  • Mir schwebt so etwas wie ein kleiner Editor vor:

    • Laden von Daten und Kommunikation mit Datenquelle
    • Speichern von Daten und Kommunikation mit Datenquelle
    • Laden und Einfügen von Daten an Einfügemarke (also da wo der Cursor sich befindet)
    • Freies Bewegen des Cursors
    • Anzeige wo der Cursor sich befindet: Zeile:x Spalte:y
    • Prüfen der Eingabe einer Zeile auf ...

    Das möchte ich gerne lernen, ich bin bereit die Kiste Bier zu spendieren :)

    Oder noch besser: Den Assembler von Diddl analysieren, verstehen und erweitern (wenn möglich bspw. Macros)


    Und ja, das eigentliche Assemblern ist nicht schwer, man muss sich nur sehr konsequent an die Regeln halten. Wichtiger ist es das Kernel und die Einsprungadressen zu kennen. Hier muss ich noch sehr viel lernen.


    Beste Grüße

    Marco

    Ich suche: Atari 800, MPF-IP

  • Hi Diddl,


    ich habe nun dein Assembler auf einem 3032 ausprobiert. Welches ist die aktuellste Version und wo bekomme ich diese. Wenn ich sys25000 ausführe und den Punkt eingebe, erscheint . , A K S (kein P). Es ist abweichend von den Screenshots. Kannst Du mir ein Link auf eine aktuelle Version (für Basic 2) geben?


    Beste Grüße

    Marco

    Ich suche: Atari 800, MPF-IP

    Einmal editiert, zuletzt von discmix ()

  • Es gibt zur Zeit keine aktuellere.

    Beider Versionen sind 4.7, egal ob BASIC2 oder BASIC4.


    Das .P gibt es nur in der ROM Version.

    Es startet den Program Loader.


    Der Programm Loader ist nicht von mir.

    Und er hat auch nichts mit dem Assembler zu tun.


    Aber weil ich den Loader praktisch finde so als Tool, habe ich das ROM damit befüllt, weil hinter dem Assembler noch freier Platz war.

    Mit .P startet man das Tool im ROM, weil man sich sonst die Einsprungadresse merken müsste.


    ====


    Beider Versionen sind 4.7, egal ob BASIC2 oder BASIC4.


    Bei BASIC2 laufen die Dinge aber ein bisschen anders als unter BASIC4:


    Bei BASIC4 hat man Vektoren im RAM für Formelauswertung und Statement Ausführung.

    Ich ändere die Vektoren auf den Assem 4.7 und erweitere so das BASIC.


    Bei BASIC2 hat man keine Vektoren und es ist etwas schwieriger das BASIC zu erweitern.

    Ich verwende dazu eine modifizierte CHRGET Routine.

    Das BASIC ruft für jedes Zeichen das interpretiert wird eine Routine auf: CHRGET()

    Die CHRGET Routine steht im RAM (in der Zeropage).

    Der Assem 4.7 ändert den Code der CHRGET und kann so gucken was das BASIC gerade macht.

    Wenn es etwas Assem spezifisches ist, dann übernimmt mein Code das Ruder ...

    Es ist ein hässlicher Hack, aber es ging damals nicht anders ...

  • Alles klar, Danke dafür.


    Noch eine Verständnisfrage zu Zieladresse und Ablageadresse.


    Ich habe wie folgt eingetragen: *=$033a, &=$4e20

    Nun kompiliere ich und speichere mit .s $4e20,$4e30,"test"

    Wenn ich jetzt mit load"test",8 lade sollte der Code doch an 033a "liegen", oder?


    Beste Grüße

    Marco

    Ich suche: Atari 800, MPF-IP

  • Noch mal ich :)

    Ich habe jetzt mal die letzten Stunden mit dem Assembler "gespielt". Wenn ich Zieladresse und Ablageadresse hinterlege (bspw. *=$033a, &=$4e20) und das Ganze speichere (egal ob .s "test" oder .s $4e20,$4e30,"test") und danach lade mit load"test",8 oder load"Test",8,1 legt er das Programm immer in den Ablagespeicher. Ich hätte erwartet, das es ab der Zieladresse einlädt. Was habe ich falsch verstanden?


    Danke und Beste Grüße

    Marco

    Ich suche: Atari 800, MPF-IP

  • Puh, wenn ich schon die ganzen $-Dinger sehe, bin ich noch mehr verwirrt, als vorher. Assembler ist echt was für außerordentlich intelligente Menschen- oder aber, ich bin nicht die hellste Kerze auf der Torte. Kann auch gut sein. :)

  • Es wird immer das geladen von wo man gespeichert hat.

    Der SAVE Befehl speichert die Start Adresse in die Datei.


    Das * sagt dem Assembler nur die virtuelle Adresse.


    *=$0330

    LOOP

    JMP LOOP



    Kodiert


    4C 30 03


    JMP ... 4C

    Lobyte ... 30

    Hibyte ... 03

  • Puh, wenn ich schon die ganzen $-Dinger sehe, bin ich noch mehr verwirrt, als vorher. Assembler ist echt was für außerordentlich intelligente Menschen- oder aber, ich bin nicht die hellste Kerze auf der Torte. Kann auch gut sein. :)

    Ach alles halb so wild.


    Man muss sich halt gewöhnen an die Syntax

  • Ich würd soooo gerne kleine Spielchen programmieren... bzw. einfach generell schneller unterwegs sein, als mit Basic.

    Na, da ergibt sich bestimmt mal ein kleiner interaktiver Kursblock. :)

  • Ich würd soooo gerne kleine Spielchen programmieren... bzw. einfach generell schneller unterwegs sein, als mit Basic.

    Na, da ergibt sich bestimmt mal ein kleiner interaktiver Kursblock. :)


    Prinzipiell nicht das große Problem.

    Allerdings befürchte ich, dass dieser Brocken für den Anfang zu groß ist.


    Vielleicht einfach für den Anfang ein paar Assembler Basics ...


    Was für ein Spiel schwebt dir den vor?