Hello, Guest the thread was called412 times and contains 5 replays

last post from skoe at the

CA65, wie Speicherbereiche festlegen?

  • Ich versuche gerade aus der CA65-Dokumentation schlau zu werden. Ich habe nirgends finden können, wie ich Speicherbereiche festlege, wo der Code hin soll. Soetwas wie

    Code
    1. .org $1f03
    2. nop
    3. .org $3b80
    4. nop

    funktioniert nicht. Wird beides direkt lückenlos im Speicher abgelegt.
    Zum einen will ich sicherstellen, daß bestimmte Routinen aus Geschwindigkeitsgründen keine seitenübergreifenden Schleifen bilden oder über Seiten weg indizieren. Zum Anderen will ich bestimmte Bereiche frei halten, weil ich dort die Grafik etc. hinladen werde.
    Wie macht man das?

  • Hast Du mal die Option ".FEATURE org_per_seg" ausprobiert? Laut Doku ist .org normalerweise global. Ich würde meinen, dass es dann nur eine Startadresse gibt. Hier der Auszug aus der Doku:


    10.69 .ORG


    Start a section of absolute code. The command is followed by a constant expression that gives the new PC counter location for which the code is assembled. Use .RELOC to switch back to relocatable code.


    By default, absolute/relocatable mode is global (valid even when switching segments). Using .FEATURE org_per_seg it can be made segment local.


    Please note that you do not need .ORG in most cases. Placing code at a specific address is the job of the linker, not the assembler, so there is usually no reason to assemble code to a specific address.


    Example:


    .org $7FF ; Emit code starting at $7FF

    Menschen wurden geschaffen um geliebt zu werden. Dinge wurden erschaffen um benutzt zu werden.

    Der Grund, warum die Welt sich im Chaos befindet, ist weil stattdessen Dinge geliebt und Menschen benutzt werden.

  • Nachdem auch das Definieren von Segmenten mir nicht weiter geholfen hat, habe ich das Problem mit nur einem .org gelöst:

    Code
    1. .org $1f03
    2. nop
    3. .repeat $3b80-*
    4. .byte $00
    5. .endrep
    6. nop

    Gibt es eine Möglichkeit, daß der Assembler automatisch einen Bereich mit Code füllt, und dann in einem anderen Bereich weiter macht? Oder muß ich meine einzelnen Routinen von Hand so anordnen, daß sie optimal sitzen?

  • Quote


    In most cases ...


    Wenn man Floppy Programme erstellt, müssen die in einem bestimmten Buffer laufen. Da kommt man nicht herum ...


    falsch. das wäre ein paradebeispiel für einen fall in dem man .org NICHT braucht


    Quote


    Nachdem auch das Definieren von Segmenten mir nicht weiter geholfen hat, habe ich das Problem mit nur einem .org gelöst:


    huuuarg hilfe /o\


    solche konstruktionen deuten drauf hin das das prinzip nach dem ca65 und der linker funktionieren nicht verstanden wurden =P


    sowohl ersteres als auch zweites lassen sich einfach per kleinem linkerconfigfile erschlagen. dazu mal die docs vom ld65 lesen :)


    Quote

    Gibt es eine Möglichkeit, daß der Assembler automatisch einen Bereich mit Code füllt, und dann in einem anderen Bereich weiter macht? Oder muß ich meine einzelnen Routinen von Hand so anordnen, daß sie optimal sitzen?


    in der regel sollte der pseudoop ".align" das tun

  • Yep, ein Linkerscript ist genau, was Du brauchst.


    Funktionsprinzip:
    Wenn Du eine C-Datein oder Eine Assembler-Datei kompilierst/assemblierst, ist dem Compiler/Assembler "in most cases" egal, wo der Code später hinkommt. Wenn er eine absolute Adresse braucht (z.B. JSR bla), die er nicht auflösen kann, merkt er sich einfach das Symbol ("bla") als sog. "unresolved external". Das Zwischenergebnis ist eine Objekt-Datei (*.o)


    Dann kommt der Linker ins Spiel. Der macht das, was der Name sagt: Er verbindet die Objektdateien und ggfs. Bibliotheken und Startup-Code (s.u.). Dabei versucht er, alle fehlenden Adressen aufzulösen.


    Also muss der Linker wissen, wo was hinkommt. Und das sagt man ihm mit dem Linkerscript. Der ld65 hat pro Maschine (z.B. c64) ein eingebautes. Oft braucht man aber ein eigenes.


    Da steht sinngemäß drin: code soll nach $8000 (= text segment), daten nach $c000 (= data segment) und uniitialisierte daten nach $2000 (= bss segment). Der Startup-Code, der evtl. dazugelinkt wird, sorgt für das Verschieben an die richtige Stelle. Aber auch das muss nicht sein.


    So ganz grob erklärt... den Rest musst Du Dir selbst anlesen.


    P.S. sauhunds Tip mit dem align solltest Du dann anwenden, wenn Du z.B. verhindern möchtest, dass ein BNE über eine Seitengrenze springt. Aber nicht, um 8 kByte zu überbrücken...