Hello, Guest the thread was called326 times and contains 9 replays

last post from zrs1 at the

Wie reserviert man Speicher ausserhalb des Programms?

  • Hallo!


    Habe eine Frage:


    Wenn ich mit derzeitigem (beschraenktem) Kenntnisstand in Assembler (ich nutze ca65) ein Byte Speicher brauche, das ich aber nicht vordefiniert brauche, sondern einfach nur als Platzhalter fuer irgendwelche Berechnungen, dann mach ich das so:

    Code
    1. meinbyte:
    2. .byte $00

    Wenn ich das richtig verstehe, endet dieses Byte ja in der PRG Datei, und das ist ja Verschwendung, oder? Weil auf der Diskette brauch ich das Byte ja nicht, sondern nur irgendwo im Arbeitsspeicher. Allerdings muss der Assembler ja wissen wo dieses Byte sein soll, so dass er dann im Programm an den entsprechenden Stellen die Adresse davon einsetzen kann. Und mich interessiert es auch nicht weiter, wo er dieses Byte anlegt, vielleicht am besten einfach direkt nach dem Ende des PRG, wo auch immer das halt jeweils endet.


    Wie kann ich das im Assembler ausdruecken?


    Vielen Dank schon mal im Voraus!

  • wenn du etwas direkt hinter deinem programm speichern möchtest, könntest du folgendes probieren:


    Code
    1. ldy #$01
    2. sta ($2d),y    speicher akku am programmende ($2d/$2e) +1

    habs jetzt nicht ausprobiert, aber es sollte klappen. willst du mehrere werte speichern musst du entsprechend den wert im y-reg erhöhen.

  • Ich weiß jetzt nicht, wie es in Deinem Assembler geschrieben wird.

    Es könnte so oder ähnlich aussehen:

    Code
    1. *=$c000         ; Startadresse
    2.     rts            ; Irgendein Quatsch als Beispielcode
    3. frei1=*            ; erste leere Adresse hinter dem Code kann jetzt als frei1 angesprochen werden.
    4. frei2=frei1+1      ; D.h. für frei1 ist nur 1 Byte reserviert, denn frei2 ist direkt 1 Byte dahinter.
    5. frei3=frei2+100 ; von frei2 bis frei3 sind es 100 Bytes. So kannst Du Lda frei2,y für y 0-99 verwenden.

    Aber wie gehabt in Assembler: Nix verhindert, dass Du frei1+5 für irgendwas benutzt und Spaghetticode machst.

  • Korrekte Vorgehensweise bei ca65:


    • definiere ein Segment vom Typ "bss". Wenn du es BSS nennst, kannst du im Source einfach .bss schreiben statt .segment "BSS".
    • in diesem Segment verwendest du dann .res zum reservieren von Speicher.

    Kann ganz simpel z.B. so aussehen:


    Linker-Config:

    Code
    1. MEMORY {
    2. MAIN: start = $c000, size = $1000;
    3. }
    4. SEGMENTS {
    5. CODE: load = MAIN;
    6. DATA: load = MAIN;
    7. BSS: load = MAIN, type = bss;
    8. }


    Assembler-Source:

    Code
    1. .bss
    2. buffer: .res $10 ; 16-byte buffer
    3. .data
    4. foobar: .byte "foobar", $0 ; a string
    5. .code
    6. lda #<foobar;
    7. [...]


    Der Linker platziert alle drei Segmente in der Reihenfolge der Config in die angegebenen Speicherbereiche. BSS wird also ganz hinten platziert, und da es vom Typ "bss" ist landet es nicht im Ausgabefile.


    Vorsicht: In C ist auch bss initialisiert. Aber nur, weil die C-Runtime entsprechenden Code hat, der BSS-Segmente erstmal mit Nullen vollschreibt. Wenn du BSS in Assembler benutzt, ist nichts initialisiert, solange du das nicht selbst machst.


    edit: Es ist natürlich richtig, dass du in Assembler einfach "überall hin" schreiben kannst, und dir im Code dafür labels "hartcoden" kannst. Davon würde ich aber abraten. Gerade mit ca65 sollte man die Vorteile nutzen, die einem der Linker mit Segmenten bietet, und alle RAM-Bereiche und Segmente in der Linker-Config definieren. Das gibt dir z.B. die Möglichkeit, ohne jede Änderung am Source deine komplette Memory-Map umzubauen -- du musst nur die Linker-Config editieren :)

  • Korrekte Vorgehensweise bei ca65:

    Vielen Dank ZRS1, genau auf sowas hatte ich gehofft, und gesucht. Die Doku vom ca65 finde ich ziemlich duerftig, da muss man schon vorher wissen wie alles geht. Was ein Glueck gibt es dieses Forum!


    Und ja, das mit dem Linker und den Segmenten macht total Sinn, werde das genau so einrichten.

  • Nur der Vollständigkeit halber: Es hindert einen keiner daran, .res auch in "normalen" Segmenten zu nutzen, bzw tatsächlich Dinge mit .byte etc (oder gar opcodes) in ein BSS-Segment zu schreiben. .res sorgt beim assemblieren für die angegebene Zahl Null-Bytes. Beim Linken wird der Linker dann BSS-Segmente einfach ignorieren, wenn sie am Ende eines Speicherbereichs liegen. Die Verwendung von .res in BSS-Segmenten ist also eigentlich nur Konvention, aber eine sinnvolle für lesbaren Code :)