Hello, Guest the thread was called1.8k times and contains 23 replays

last post from ghengiz at the

Verwirrter Einsteiger sucht Hilfe...

  • Hallo Freunde des C64,


    vor kurzem habe ich nach vielen Jahren abstinenz dank des Emulators VICE meine Liebe zum C64 wieder entdeckt. Seitdem habe ich mich auch intensiv mit Basic beschäftigt und stoße schon deutlich an seine Grenzen. Ich möhte nun aber weiter gehen und Assembler lernen. Mangels Original-Brotkasten und der Bequemlichkeit halber aber im Emu.
    Ich habe mir zwar TurboAss schonmal angesehen, komme aber gar nicht klar damit. nach Compilieren und ausführen sollte man doch mit der RESTORE Taste wieder in den Editor kommen. Aber hier passiert leider nichts. Könnte wohl an VICE liegen.


    Viel lieber wäre mir aber, den Code auf dem PC zu schreiben und das Ergebnis im VICE ausführen zu lassen (Crosscoding). Daher habe ich mir Relaunch64 besorgt, VICE als Emu angegeben und ACME als Compiler reingehängt. Da ich ja noch kein Assembler kann, habe ich das mit Codeschnippseln hier aus dem Forum versucht, welche im TurboAss auch funktioniert haben
    Beispiel:
    *=4096
    lda #1
    sta 53280
    rts


    Nun komme ich zu meinem PRoblem: ACME compiliert das nicht richtig und es wird nichts ausgeführt. Verwende ich andere Compiler wie C64ASM oder DASM, kommen andere Fehlermeldungen.
    Ich muss also davon ausgehen, dass Assembler nicht gleich ASsembler ist und es verschiedene Dialekte/Syntaxen gibt.


    Was genau macht denn nun aber Sinn zu lernen? Gibt es einen Compiler, der mir das in Relaunch64 geschriebene in TurbuAss umsetzt so dass ich dem kleinen Tutorial aus dem Beitrag "Basic Scrolling" mitmachen kann? Gibt es den ultimativen Assembler? Was macht Sinn ziu lernen, was nicht?
    Und wo gibt es den ultimativen "Ich lerne Assembler in 10 Minuten bis zur Perfektion Online Kurs"? ;-)


    Ich hoffe ihr versteht worauf ich hinaus will: Ich brauche einfach ein bisschen Starthilfe um eine möglichst gute Startposition zu haben. Ich habe zwar schon viel hier im Forum gelesen. Als Neueinsteiger ist es halt nicht immer so einfach, die jeweils richtige Information zu bekommen. Bitte entschuldigt also, falls ich Antwort durch eine gezielte Suche hätte finden können.


    Ich würde mich sehr freuen, wenn mir jemand helfen könnte.


    Besten Dank!
    Gruß
    Wolfgang

  • Die Schreibweisen in den verschiednene Assemblern für Makros, Label usw. sind immer ein bisschen anders. Ich denke, man bleibt bei dem, den man gewöhnt ist, solange man in anderen Assemblern nichts total tolles findet, das man schon die ganze Zeit vermisst hat, soviel zum optimalen Assembler.
    Im Beispiel oben fehlt ein
    !to "pcdateiname.prg"
    So assembliert er zwar das Programm, nur wird das Ergebnis nirgends hingeschrieben.

  • Danke für die schnelle Antwort!


    Du hast recht: Das !to "name.prg" hab ich nicht geschrieben, verwende es aber.
    Lasse ich das nun compilieren, lädt vice, der C64 bootet ordentlich, es erscheint LOAD"name",8,1
    READY.
    RUN


    und dann wird der Bildschirm gelöscht und READY kommt. Nichts weiter.
    Mittlerweile habe ich auch einige Codeschnippsel noch probiert. Immer das selbe Spiel. Im TurboAss laufen die aber korrekt. Nur wie gesagt, reagiert der ASM nicht auf die RESTORE Taste.
    Also scheint es an der Interpretation von ACME zu liegen. Grundsätzlich funktionieren tut er aber wohl schon: Lade ich mir von popelganda.de die DEMO-Files runter, werden die korrekt compiliert und ausgeführt!


    ICh muss mich wohl vor dem eigentlichen Lernen erst noch intensiv mit den Eigenheiten von ACME beschäftigen.

  • du musst das Proghram im EMu noch starten. RUN hilft da leider wenig, da das Programm ab Adresse 4096 steht (wegen dem *=4096, das "Sternchen gleich" gibt die Startadresse an, also wohin der Assembler den Code im Speicher assembliert). Also du musst auf jeden Falöl SYS4096 eingeben um das Program auch zu starten.
    Die Rahmenfarbe sollte sich ändern und READY wieder erscheinen.


    EDIT: Das mit der Restore-Taste: Das ist von TurboAss Version zu Version unterschiedlich implementiert; bei manchen gehts bei anderen nicht. Vom TASS gibt es zig Versionen. Ansonsten solltest du die meisten Versionen mit SYS36864 (oder in einigen Fällen SYS32768) wieder betreten können.

  • JAWOLL! Das hat geholfen! Beides. Vielen Dank! Jetzt kann ich endlich loslegen :)
    Bei jedem Test mit sys36864 wieder zurückzukehren ist mir jedoch ein wenig zu umständlich.... ich werde mich wohl auf Relaunch64 und ACME einschießen.


    Also Danke schön nochmal!

  • hier hast du mein "ACME-template" mit dem ich immer anfange:



    damit kannst du's mit RUN starten und der code liegt ab $1000/4096.


    gruss,
    tecM0

  • danke auch Dir!


    Kannst Du mir sagen, ob es igendwo eine vernünftige Anleitung für ACME gibt, die einem Einstieger hilft da durchzublicken? Am besten wäre natürlich ein Anfänger-Assembler-Kurs auf ACME Basis :D
    Die mitgelieferten Docus richten sich leider mehr an den Assembler-Umsteiger als an den Einsteiger mit BAsicerfahrung. Dem Einstieg von Biguser im Thread Basic-Scrolling folgend, bin ich bei counter byte 0 hängen geblieben. Ich hab über ne Stunde gebraucht bis ich heruasgefunden habe, dass das bei ACME counter !byte 0 heißen muß. was dieses byte 0 bedeutet, ist mir hingegen noch immer nicht klar :baby:


    Du siehst, ich bin blutiger Laie. Aber ambitioniert: Ich will das lernen ;-)


    Gruß
    Wolfgang

  • label !byte 0


    assembliert an die stelle im speicher einfach eine "null" hin. initalisiert
    also einen zähler den du dann mit


    lda label abfragen und z.b. mit
    inc label hochzählen kannst.


    einem assemblerKurs auf ACME-basis kenne ich auch nicht, aber wozu auch?
    nur die opcodes sind von assembler zu assembler anders ... also statt .byte
    einfach !byte nehmen usw.


    sieh zu! das wird schon! ;)



    T.

  • ok, dann sollte das in den Griff zu kriegen sein. Soooo viele Opcodes werden das ja wohl nicht sein (und wehe es demotiviert mich jetzt einer ;-) )


    Nochmal nachgehakt: Wo ist der Unerschied zwischen counter=0 und counter !byte 0?



    Eine Frage noch (eigentlich gehört das alles ja ins crosscoding-forum, sorry fürs falschposten)
    Wenn ich in Assembler etwas schreibe und im Emu starte, kann ich ich es ja mit sys... aufrufen. Das funktioniert auch schon ganz gut.
    Will ich allerdings das mit Basic kombinieren, klappts plötzlich nicht mehr. Nach Starten des Emu wird durch list ein
    10 SYS 4096
    aufgeführt. Egal was ich noch schreibe, und sei es nur ein 20 REM, nach ausführen des Programms wird nur der Bildschirm gelöscht und READY. kommt. Das Asm Prog wird gar nicht erst ausgeführt. Lösche ich die Zeile 20 wieder, gehts wieder ganz normal. ziemlich seltsam...


    Liegt das an einer Einstellung in VICE oder funktioniert sowas im EMU gar nicht?

  • ...hüstel.... kannst Du mir das bitte nochmal ausdeutschen? Ist mir ja peinlich, mich so blöd anzustellen, aber bei dem eben geschreibenen ist bei mir wohl ein Pointer nicht richtig gesetzt =)


    heißt das nun, dass ich einen Pointer (was auch immer das sein mag) setzen muß oder dass diese Kombination grundsätzlich nicht funktioniert?


    dank Dir! :)

  • AAaso... ;)


    Pointer sind Speicherzellen, die auf bestimmte Adressen im RAM "zeigen". Z.B. gibt es einen Pointer für das Ende des BASIC-Programms. Er "zeigt" auf die Stelle im Speicher, an der das gerade geladene BASIC-Programm endet. Wenn Du ein BASIC-Programm schreibst und so Zeile für Zeile eintippst, wird laufend der Pointer erhöht, da Dein Programm mit der Zeit ja immer länger wird.
    Solche Pointer gibt es auch für viele Dinge, wie Beginn und Ende des BASIC-Programms, des Variablen-Bereichs, und und und.


    Wenn Du jetzt ein Programm in den Speicher lädst, was eine BASIC- und einen Maschinenspracheteil enthält, zeigen einige Pointer auf die falschen Stellen im Speicher. Solange Du das Programm nur mit RUN ausführen willst, ist das auch nicht weiter tragisch. Aber sobald Du anfängst, neue BASIC-Zeilen einzugeben, werden die Pointer so verschoben, dass das Programm nicht mehr mit RUN ausgeführt werden kann. Der SYS müsste aber trotzdem noch gehen.


    Willst Du BASIC- und Maschinenprogramm gleichzeitig im Speicher haben, solltest Du beide Programme einzeln für sich in den Speicher laden. Zurerst LOAD"BASIC-PRG",8 und dann LOAD "MASCHINEN-PRG",8,1.
    Den zweiten LOAD kannst Du auch im BASIC-Programm angeben.


    Übrigens ist 4096 ($1000) eine ungünstige Stelle für Maschinenprogramme, wenn auch noch mit BASIC gearbeitet werden soll, da so für das BASIC-Proggie nur 500 Bytes zur Verfügung stehen.


    CU
    Kratznagel

  • UH!!
    Wenn Du ein Basic-Programm in den Speicher lädst, egal, ob nur Basic-Zeilen oder Basic mit Assembler kombiniert, dann hat es auch eine Endadresse, nämlich die, die das File hat, nicht die, die es haben könnte, wenn man sich nur die Basic-Zeilen betrachtet. Das Programm mit dem Sys4096 müsste etwa 2K groß sein, und auch nach dem Laden weiß der Computer noch, daß das Programm kurz hinter 4096 aufhört. Die genaue Adresse+1 findest Du in 45/46.
    Wenn Du nun eine Basic-Zeile einfügst, die z.B: 10 Bytes braucht, dann sucht der Computer die passende Speicherstelle raus und verschiebt alles von dort bis zum Programmende nach hinten, damit die neue Zeile eingefügt werden kann. Damit wandert auch das Maschinenprogramm nach hinten, und darum das Ready nach dem Sys.
    Man könnte nun den Ende-Pointer 45/46 korrigieren und auf das Ende der Basic-Zeilen richten, aber das Ass-Programm an der Stelle abzulegen bleibt in Kombination mit Basic kitzlig...


    counter=0 : Du definierst eine Variable und die hat den Wert 0. Du kannst dann später Lda#counter, Sta counter usw machen, und der Assembler setzt an den Stellen 0 ein.


    counter !byte 0 belegt eine Speicherstelle mit 0. Welche genau gibst Du gar nicht an, das erledigt der Assembler für dich. Steht z.B: ein *=4096 davor, dann wird das Nullbyte an der Adresse 4096 landen. Wenn Du die Adresse in deinem Programm ansprechen willst, kannst Du counter verwenden. Lda counter würde hier durch Lda 4096 ersetzt.

  • alles klar, wieder was gelernt! Vielen Dank euch allen! Das Forum hier ist klasse und hat sich als sehr informativ und hilfsbereit erwiesen. So macht lernen Spaß!


    Wenn ich das ganze richtig verstehe, ist das also so, dass die Variablen (oder nennt man counter !byte 0 (um beim Beispiel zu bleiben) gar nicht Variable?) immer/meist am Ende des Programms definiert werden, aber als erstes abgearbeitet werden. Daher werden sie der Reihe nach am Anfang des zuerst definierten Speicherbereichs (in diesem Falle 4096) abgelegt. mit counter !byte0 : counter2 !byte0 sind also 4096 und 4097 schonmal besetzt und das eigentliche Programm startet bei 4098.
    Stimmt das soweit?


    Bischen kompliziert (anders formuliert: ungewohnt) ist das ganze schon ;-) Aber wenn man peeken und poken gewohnt ist, erscheint einem schon vieles auf Anhieb logisch :)


    Welches ist denn ein günstiger Speicherbeginn wenn man BAsic und Asm mischen will? Wobei ich ja eigentlich aufs Basic verzichten möchte und alles assemblen will. Gerade anfangs könnte es aber hilfreich sein, sich mit dem vertrauten BAsic zu behelfen, und wenns nur zum debuggen ist...

  • Quote

    (oder nennt man counter !byte 0 (um beim Beispiel zu bleiben) gar nicht Variable?)


    Man nennt's eigentlich immer Label. Label ist aber eher sowas wie ein Namensschildchen, das man an eine Adresse heftet. COUNTER !by 0 kann man ohne weitere Diskussion Label nennen. COUNTER=0: Lda#counter würde ich eher Variable nennen, nennt man aber trotzdem Label, auch wenn die Zahl, die sich dann dahinter verbirgt, nicht für eine Speicherstelle steht.



    Quote

    Wenn ich das ganze richtig verstehe, ist das also so, dass die Variablen immer/meist am Ende des Programms definiert werden, aber als erstes abgearbeitet werden.


    Nö, der Assembler klappert den Quelltext halt ab und übersetzt, was ihm dabei vor die Linse kommt. Ein Label und ein !by gehören überhaupt nciht zusammen, hinter Labeln können genausogut Assemblerbefehle stehen, und vor einem !by muß kein Labele stehen. Trifft der Assembler auf ein !by 0, dann fügt er halt an der aktuellen Position ein Nullbyte ein, trifft er auf eine Labeldefinition, dann merkt er sich unter dem Namen halt die aktuelle Position. Die Reihenfolge wird so sein, wie Du's in den Quelltext geschrieben hast.

    Code
    1. *=$c000
    2. loop sta 1024,y
    3. dey
    4. bne loop
    5. !by $60


    Quote

    Welches ist denn ein günstiger Speicherbeginn wenn man BAsic und Asm mischen will? Wobei ich ja eigentlich aufs Basic verzichten möchte und alles assemblen will. Gerade anfangs könnte es aber hilfreich sein, sich mit dem vertrauten BAsic zu behelfen, und wenns nur zum debuggen ist...


    $c000-$d000 ist frei und kommt dem Basic nicht in die Quere, auf die Basic-Zeile am Anfang sollte man dann allerdings verzichten. Die Basic-Zeile ist aber je nach Zweck dann doch bequemer. Irgendwas im Direktmodus kannst Du da auch weiterhin machen, nur das Einfügen von weiteren Zeilen kommt nicht so gut.

  • Hallo zusammen,


    ich habe mich nun ein paar Tage mit Asm beschäftigt. Leicht ist was anderes :P


    So ganz hab ich das mit den Labels/Variablen noch nicht gefressen und möchte da nochmal nachhaken. Folgendes Beispiel:


    -------------------------------
    *=$1000


    .klein = 0
    .gross =0


    lda #42
    ldx #10
    loop sta 1024,x
    jsr wait
    dex
    bne loop
    rts



    wait
    inc .klein
    bne wait
    inc .gross
    bne wait
    rts
    ------------------------------
    Dieses kleine Programm soll 10 Sternchen von rechts nach links oben auf den Bildschirm zaubern. In dieser Variante erzeugt es jedoch nur ein Sternchen und hängt dann in einer Endlosschleife.
    Ändere ich zeile 2 in .gross=2, funktioniert es seltsamerweise. Bei 0 und 1 nicht. Warum?


    Ersetze ich die ersten beiden Zeilen durch
    .klein !byte 0
    .gross !byte 0
    dann wird der Bildschirm gelöscht und Ready erscheint. Schneide ich die beiden Zeilen aus und hänge sie hinten an, funktionierts. Auch hier: Warum?


    Dies sind so Kleinigkeiten, die einem den Einstieg ziemlich schwer machen ;-)


    Bedeutet .klein=0 nun, dass die Variable .klein den Wert 0 hat oder dass sie den Inhalt der Sepeicherzelle 0 annimmt? Warum ergibt .klein=#0 einen Syntax-Error? Ist diese 0 somit hex? Dann wärs aber doch .klein =$0. Oder doch Speicherzelle 0? Wiederspricht der Aussage von hoogo. Sehr verwirrend das ist für einen jungen Padawan... :)


    Wie kann man mit x und y als einzige Variablen auskommen? Kann ich x in einer aufgerufenen Subroutine nochmals verwenden und darauf vertrauen, dass x beim RTS den ursprünglichen Wert wieder vom Stack bekommt? Oder muß ich immer vor dem JSRen die Inhalte von A,X/Y und anderen Dingen wie C/Z/N-Flags manuell auf den Stack schieben? Kann man (bzw. soll/muß( man überhaupt per Hand am Stack herum pfuschen?


    Wieder mal viele Fragen. Aber ich denke, sie werden langsam etwas konkreter und ich bin aus dem Absolut-Noob-Stadium schon heraus :D
    Ein großes Rätsel ist mir noch der Speicheraufbau. Ich habe einige Listen mit der speicheraufteilung des C64. Irgendwie alles noch böhmische Dörfer für mich. Wo darf ich, wo soll ich, wo muß ich was tun? Was kann ich tun um... Diese ganzen Kniffe die einem das programmieren erst ermöglichen, fehlen mir einfach noch.



    Ach ja, noch was: ich bin ja nicht gezwungen, in Relaunch64 die Adressnummern mit anzugeben. Wenn ich das nicht tue, habe ich folglich aber auch keine Adressen auf die ich branchen kann und muß somit immer mit LAbels arbeiten. Was macht eurer Meinung nach mehr sinn? Mit Adressen zu programmieren und somit auch den ganzen NAchteilen (branchen ins unbekannte) oder ohne und dafür dauern Labels definieren?


    Gott, wenn ich so schreibe, fallen mir noch tausend andere Sachen ein. Aber eins nach dem anderen. Ich hab euch eben genug zugetextet ;-)


    Ich würde mich freuen, wenn ihr mir noch ein bisschen helft bis es klick bei mir macht und der Knoten platzt. Momentan schwirren tausende Einzel-Infos in meinem Kopf herum. Das muß ich alles jetzt erst irgendwie sortieren, zusammensetzen und daraus was sinnvolles machen :)


    eins ist aber sicher: ASM macht höllisch Spaß. Nur mit hex hab ichs noch nicht, auch wenn ich die Vorteile verstanden habe und weiß, wie man sie umwandelt. *g*


    Beste Grüße
    Wolfgang

  • Quote

    Original von Flat23
    Bedeutet .klein=0 nun, dass die Variable .klein den Wert 0 hat oder dass sie den Inhalt der Sepeicherzelle 0 annimmt?


    Es bedeutet vielmehr, dass Du der Speicherzelle 0 den Namen "klein" zuweist. Und in er nächsten Zeile weist Du genau der gleichen Zelle auch noch den Namen "gross" zu. D.h. Deine Wait-Schleife verändert die ganze Zeit nur die Speicherzelle 0 und kommt deshalb nie aus der zweiten BNE-Abfrage raus. ;)


    Richtig ist
    .klein !byte 0
    .gross !byte 0
    und zwar hinten im Programm. Damit weist Du zwei aufeinanderfolgenden Zellen die Namen und Werte zu.


    Klar kannst Du diese Variablen auch am Anfang (hier $1000) stehen haben. Dann musst Du allerdings beachten, dass der eigentliche Programmcode erst zwei Bytes später anfängt (also ab $1002) und der SYS zum Starten sich dann natürlich auf diese Adresse beziehen muss. Ansonsten versucht der Prozessor den Inhalt ab $1000 auszuführen (der ja mit $00 beginnt), was natürlich daneben geht. ;)


    CU
    Kratznagel

  • ok, also mal ganz von vorn:
    Dein ASM Programm steht Anweisung für Anweisung hintereinander im Speicher, ab der Adresse, die du mit "*=xxxx" angibst.
    Jede Zeile im Assembler-Quelltext beinhaltet folgendes:


    LABEL OPCODE KOMMENTAR


    alles optional, d.h. eine Zeile kann auch nur aus LABEL oder nur aus KOMMENTAR oder allen denkbaren Kombinationen bestehen. Oder natürlich nur aus einem Opcode (Opcodes sind alle Mnemonics, z.B. LDA, STA, RTS usw.) Zum Opcode gehört natürlich immer null, ein oder zwei Operanden


    Ein LABEL tut nun folgendes. Es ist nur für den Assembler existent. Dieser merkt sich unter dem Label-Namen die aktuelle Adresse, also bei

    Code
    1. *=$1000
    2. LOOP LDA #$01


    dann hat LABEL den Wert $1000
    oder bei

    Code
    1. *=$1000
    2. lda #1
    3. loop ldx #2
    4. ...


    nun hat der Zähler bereits den Wert $1002 (LDA #1 benötigt zwei Bytes, eines für den LDA-Opcode und eines für den Operand (#1)) wenn das Label angelegt wird, LOOP hat also den Wert $1002. Du brauchst dich aber um die eigentlichen Werte der Labels überhaupt nicht kümmern, das macht ja alles der Assembler für dich. Für dich sielt das (zumeist) keine Rolle, welchen Wert ein Label hat.


    Achtung! Es geht aber auch so:


    Code
    1. LABEL = 1234


    Durch das Gleichheitszeichen wird direkt der Wert der folgt (1234) alsd Label-Wert genommen, der Programmzähler (aktuelle Adresse) bleibt unberührt und wrd nicht beachtet.
    Das hast du ja gemacht mit

    Code
    1. .klein = 0


    .klein erhielt dann den Wert 0.


    Das # wird nur für die UNMITTELBARE Adressierung (bei LDA) verwendet, es hat also nichts mit Hex oder Dezimal zu tun.

    Code
    1. LDA #1


    Lade Akku mit dem (unmittelbaren) Wert 1
    im Gegensatz zu

    Code
    1. LDA 1


    Lade Akku mit dem Inhalt der Speicherstelle 1.
    Gib dir aber auch folgendes:

    Code
    1. label = 12
    2. lda #label


    label wird mit 12 definiert (interessiert nur den Assembler, dein Programm "weiss" davon nichts)
    und macht aus dem lda #label einfach ein lda #12.


    Code
    1. label = 12
    2. lda label


    wiederum lädt den Akku mit dem Inhalt der Adresse 12. Warum ist jetzt hoffentlich klar, oder?


    Nun zum Thema "!byte"
    Damit weist du ACME an, an der aktuellen Stelle einfach ein Byte mit dem angegebenen Wert zu assemblieren.
    Damit kann man zum Beispiel Speicherzellen reservieren, die allerdings natürlich nicht zum Programm selber gehören dürfden, deshalb macht man solche "Variablen" meist an den Schluss des Programms, der nie vom Programm ausgeführt wird (also hiter das letzte RTS)


    Gibst du solch einer Speicherstelle noch ein Label kannst du bequem darauf zugreifen, wie du schon bemekt hast.


    Code
    1. lda wert
    2. ...
    3. rts
    4. wert !byte 17


    beachte, dass hier die absolute Adressierung verwendet werden muss (ohne das #), da
    du ja den Inhalt der Speicherstelle auslesen willst.


    Bei !byte handelt es sich um einen sogenannten PSEUDO-OPCODE, diese sind eben Assemblerspezifisch und gehen auch wiederum nur den Assembler was an. (Beim TurboAssembler z.B. heisst das dann ".byte", diese PSeudo-Opcodes sind also nur kleine Gadgets die die Assemblerprogrammierer dir zur Verfügung stellen; mit Masschinensprache haben die eigentlich so gesehen nichts zu tun. Lies in der ACME-Doku nach, welche Pseudo-Opcodes es alles gibt und was sie bewirken)
    Dein Program "weiss" nichts von diesen Geschichten, es findet eben nur später an dieser Stelle den angegebenen Wert vor.


    Ach und nochmal zu Hex/Dez usw.:
    Dezimalzahlen kannst du ganz normal angeben z.B. 123, Hex Zahlen werden mit $ vorangestellt, also z.B. $12fa und Binärzahlen mit einem %, z.B.: %10101110
    Das # hat damit NICHTS zu tun:

    Code
    1. lda #12 ;lädt den Wert 12
    2. lda #$3a ;... den Wert $3a
    3. lda #%0101011 ;...den Wert %0101011
    4. lda 12 ;lädt den Inhalt der Speicherstelle 12
    5. lda $3a ,lädt den Inhalt der Speicherstelle $3a
    6. lda %0101011 ;...


    Die Register werden bei JSR und RTS NICHT gesichert, d.h. du musst tatsächlich dafür Sorge tragen, dass diese von deiner Subroutine nicht geändert werden, wenn du den Inhalt später noch brauchst.


    Dazu gibt es verschiedene Möglichkeiten, die banalste ist:


    also einfach alle Register der Reihe nach auf den Stack schieben und nach dem Unterprogramm wieder iun umgekehrter Reihenfolge vom Stack holen.
    Eine andere Möglichkeit wäre, die Inhlate einfach zwischenzuspeichern, irgendwo, also z.B.



    Normalerweise achtest du aber evtl. einfach darauf, welche Register überhaupt vom Unterprogramm verwendet werden, bzw. achtest darauf, dass das Unterprogramm möglichst wenig Register "verbraucht".


    Den Stack solltest du vorerst nur "legal" mit PHA und PLA "bearbeiten", bevor du genau weisst was du tust, und eben immer beachten dass jedes JSR und RTS ebenfalls den Stack benutzt, somit wäre so was tödlich:


    Code
    1. pha
    2. jsr sub
    3. ...
    4. sub pla
    5. ...
    6. rts


    Du kannst also nicht (ohne weiteres) in einer Unterroutine auf ausserhalb dieser Routine gepushte Stack-Werte zugreifen!


    Ok, was war noch...?!
    Was du mit den Adressen meinst versteh ich nicht so ganz. Du kannst über den Assembler alle Adressen als Labels benutzen und solltest dies auch tun.
    Auch die Branch-Befehle akzeptieren Labels, der Assembler berechnet automatisch den richtigen Offset für den Branch:


    Code
    1. bne weiter
    2. ...
    3. weiter rts


    geht problemlos.


    Zum Thema Speicheraufteilung: google mal nach "mapping the c64" das ist eine sehr gute Memory Map.
    Ganz grob:


    Standard-Mem:
    $0000-$0100 Zeropage, hier stehen mehr oder weniger wichtige "Variablen" von BASIC und KERNAL, du solltest wissen was du tust, wenn du hier Werte änderst, da darauf auich teilweise im Interrupt zugegriffen wird, den du so einfach (noch) nicht abschalten kannst (damit würdest du auch die Tastaturabfrage usw. abschalten). Adressen, die du sorglos benutzen kannst sind hier $f8- $fe
    $0100-$01ff STACK
    $0200-$03ff verschiedene BASIC und KERNAL-Krams, Vektoren usw. für dich im Moment eher uninterssant (noch...;))
    $0400-$07ff Bildschirmspeicher (+Spritepointer), kann verschoben werden bei Bedarf.
    $0800-$09ff BASIC-RAM. Hier steht ein evtl. vorhandenes BASIC-PRogramm (der Quelltext) im Speicher. Benutzt du kein BASIC-Programm (Direktmodus geht trotzdem) kannst du hier alles benutzen
    $a000-$bfff BASIC-ROM (kann man abschalten, wenn man aufs BASIC verzichten kann)
    $c000-$cfff "geschützter" Bereich, BASIC und KERNAL benuzten diesen Bereich überhaupt nicht, ist also ideal für die Anfänge, da kannst du nichts falsch machen!!!
    $d000-$dfff I/O-Bereich, CHAR-ROM und FarbRAM
    $e000-$ffff KERNAL ROM. Auch dieses kann man abschalten, dazu sollte man aber wiederum genau wissen was man tut, da man dann wirklich alles selber machen muss (vom Interrupt, Keyboardabfrage usw. angefangen)


    Ok, hoffe so manches klären zu können. Kann dir gut nachfühlen, da es mir ganz ähnlich ging als ich angefangen habe.... aber nur Mut, das wird schon; versuch dich mal an kleinen Beispiellistings die man so im Netz findet zum Anfangen...
    Kannst auch mal auf meine hp schauen, da findest du bisschen was und ausserdem vielleicht nützliche Links...


    Viel Spaß!

  • Was vielleicht noch anzumerken wäre: Akuu/x/y nennen sich Register und sind quasi 3 Byte Speicher im Prozessor, mit denen er jederzeit arbeiten kann. Parameterübergabe an Unterprogramme, wie Du sie von anderen Sprachen kennst, gibt es so nicht. Das üblichste ist, daß man in den Registern die nötigen Parameter übergibt und auch in den Registern die Ergebnisse zurückgibt. Sind zwar nur 3 Bytes, kommt man aber oft genug mit aus. Und wo man nicht damit auskommt definiert man sich halt ein paar Speicherstellen und belabelt die. Entweder in der Form merker=$fa oder merker !by 0 oder ähnlich. Die sollte man dann so behandeln, als ob sie zum Unterprogramm gehören, man aber von aussen was reinschreiben oder auslesen kann.


    Unüblich sind Übergaben über desn Stack oder die Parameter sonstwo abzulegen und dem Unterprogramm zu sagen, wo die zu finden sind.