Hallo Besucher, der Thread wurde 4,5k mal aufgerufen und enthält 33 Antworten

letzter Beitrag von kinzi am

Laden eines Assembler-Programms aus Basic

  • Hallo zusammen,


    ich habe jetzt eine Weile das Forum durchsucht, um niemanden unnötig mit einer Anfängerfrage zu nerven, die schon zigmal gestellt wurde. Aber ich habe nichts gefunden was bei mir funktioniert.

    Nun frage ich also doch:

    Ich habe ein ganz einfaches Programm in Assembler geschrieben und gespeichert.

    Wenn ich das Programm mit Load"name",8,1 starte und anschließend den richtigen sys eingebe klappt alles.

    Das klappt auch: Das Programm über datas und pokes in einem basic-Programm zu nutzen.

    Nun will ich das assembler-Programm zu Beginn meines Basic-Programms vom Basic-Programm aus in den Speicher laden und später im Basic-Programm mit sys aufrufen.

    Das krieg ich irgendwie nicht hin...


    Kann mir jemand sagen, wie das geht?


    Viele Grüße

  • Was heißt denn, du kriegst das nicht hin? Was passiert und was passiert nicht?


    War es nicht so, dass ein Basic Programm nach einem Load neu gestartet wird? Daher musste man doch einen Trick anwenden. Ist aber 35 Jahre altes Wissen, das falsch sein kann. Probiere es mal so:



    10 if a=1 then goto 30

    20 a=1:load "Programm",8,1

    30 sys Startadresse

  • Nun will ich das assembler-Programm zu Beginn meines Basic-Programms vom Basic-Programm aus in den Speicher laden und später im Basic-Programm mit sys aufrufen.

    Das krieg ich irgendwie nicht hin...

    Code
    1. 10 IF A=0 THEN A=1:LOAD "NAME",8,1

    Der Punkt ist: Nach dem LOAD-Befehl startet das BASIC-Programm neu, wobei aber die Variablen erhalten bleiben. Du musst also dafür sorgen, dass dein Programm erkennt, dass dein Assembler-Programm mit "NAME" schon geladen wurde, ansonsten landest du in einer Endlosschleife.


    EDIT: Matula war schneller. ;)

  • Sollte eigentlich ohne Probleme machbar sein (WIKI).

    Poste mal bitte dein Assembler-Programm.

    Hast du am Ende ein RTS drin?

    An welche Adresse lädst du den Assenmblerteil?

    Vielen Dnak für deine rasche Antwort, aitsch.

    Ich glaube am Sys-Befehl liegt es nicht.

    Das Programm soll einfach ein Zeichen an die Curserposition schreiben und nutzt dafür eine Routine:

    lda #$01 (Zeichen)

    ldx #$00 (Farbe)

    jsr $ea13 (Zeichen A in Farbe X an Cursorposition ausgeben)

    rts


    Das Programm liegt bei $8000 und läuft wie gesagt.


    ich brauche nun aber den Befehl um es von Basic aus in den Speicher zu laden bzw. die Befehle.

  • Es geht so wie Matula und strik geschrieben haben.


    Load,8,1 schreibt es an die richtige Stelle im Speicher, danach kannst du‘s mit sys aufrufen.

  • Wenn du weiß, wohin das Assembler-Programm geladen wird, kannst du auch per PEEK die Adresse auslesen. Angenommen, dein Programm wird nach $C000 geladen und beginnt mit LDA #$00.

    Dann kann man mittels IF PEEK(49152)=169THEN RETURN, das Problem lösen. Der Vorteilist ist, das Programm wird nicht nachgeladen, wenn es schon im RAM steht.

  • Wenn du dein Programm mittels READ-DATA einließt hast du wahrscheinlich ein Fehler in den Datazeilen.

    Deine Datazeilen müssen mit 169 anfangen und mit einer 96 enden.


    Hier mal ein Beispiel:

    Code
    1. 10 FORI=0TO3:READA:POKE8192+I,A:NEXT
    2. 20 GETA$
    3. 30 IFA$=""THEN20
    4. 40 SYS8192
    5. 50 GOTO20
    6. 55 REM DEC $D020 & RTS
    7. 60 DATA206,32,208,96

    Drückst du eine Taste, wird das ASM-Programm ausgeführt und ändert die Rahmenfarbe.


    EDIT: Vielleicht hast du versehenlich die Startadresse mit reingepoked?!? Also: DATA 00,128,....

  • Wenn du weiß, wohin das Assembler-Programm geladen wird, kannst du auch per PEEK die Adresse auslesen. Angenommen, dein Programm wird nach $C000 geladen und beginnt mit LDA #$00.

    Dann kann man mittels IF PEEK(49152)=169THEN RETURN, das Problem lösen. Der Vorteilist ist, das Programm wird nicht nachgeladen, wenn es schon im RAM steht.

    Ganz schön riskant. Da sollte man eher Anfang und Ende checken, oder vielleicht sogar eine Prüfsumme auf die ganze Routine.

    Ist aber mit Kanonen auf Spatzen geschossen, das gute alte IFA=1-Idiom reicht ja aus.

  • Vielen Dank für die Tipps bis hier!!

    Das was Matula und strik geschrieben hat funktioniert leider noch nicht so, wie ich es möchte.

    Wenn ich den Dreizeiler an den Beginn meines Basic-Programms setze, funktioniert es.

    Ich möchte den sys-Befehl jedoch erst später in meinem Basic-Programm nutzen und lasse daher die Zeile 30 weg und haben den sys in einer späteren Programmzeile.

    Das funktioniert dann nicht mehr, d.h. statt des gewüschen Zeichens wird mir eine etwa 12 Zeichen lange Reihe mit einem anderen Zeichen ausgegeben.

    Eine Fehlermeldung bekomme ich nicht.

    Auch ist das Basic-Programm nicht so lang, dass es den Speicher für das Assembler-Programm überlagert.

    Vielleicht macht mein Programm irgendetwas anderes, was verhindert, dass es funktioniert.

  • Das funktioniert dann nicht mehr, d.h. statt des gewüschen Zeichens wird mir eine etwa 12 Zeichen lange Reihe mit einem anderen Zeichen ausgegeben.

    Eine Fehlermeldung bekomme ich nicht.

    Müsste aber eigentlich laufen. Vielleicht hast du einen Fehler in deinem Assembler Programm. Wenn du magst, poste das mal hier.

  • Bei diesem Miniprogramm lohnt es sich eigentlich gar nicht, das in einer extra Datei zu speichern. Das könnte man auch als DATA-Einzeiler laden. Ich sehe gerade, daß aitsch da gerade ein Beispiel für geschrieben hat.

    Die Zahlen, die da in die DATA-Zeile müssen, kannst du mit einer PRINT PEEK-Schleife ermitteln. Das sollten in deinem Beispiel 8 Bytes sein.

    JSR gefolgt von RTS kann man durch JMP ersetzen und man spart sogar noch ein paar Zyklen und ein Byte.

    Der Vorteilist ist, das Programm wird nicht nachgeladen, wenn es schon im RAM steht.

    Oder wenn da zufällig schon was anderes steht, was mit dem gleichen Byte anfängt. Keine gute Idee. Eine Variable, die am Programmanfang abgefragt wird, ist schon sinnvoll und üblich.

    Und $8000 ist tatsächlich keine gute Idee von BASIC aus, weil das mitten im BASIC-Speicher liegt. Für Assembler von BASIC aus eignet sich am besten $c000-$cfff.

  • Um es mit Yoda zu sagen: Einigermaßen doof ich bin...

    Ich zerschieße esmir selbst , da ich später nochmal eine kurze assembler-Geschichte an diese Speicherstelle poke...

    Oh mann,....

    Sorry und danke euch !! Bis zum nächsten Mal

    ... und außerdem, wenn du nach $8000 lädst, bist du da mitten im Variablenbereich und überschreibst irgendwann mit Stringinhalten usw. dein Programm. Entweder du nimmst $C000 für dein Programm oder POKEst das BASIC-Ende auf $7FFF runter.

  • Um es mit Yoda zu sagen: Einigermaßen doof ich bin...

    Ich zerschieße esmir selbst , da ich später nochmal eine kurze assembler-Geschichte an diese Speicherstelle poke...

    Oh mann,....

    Sorry und danke euch !! Bis zum nächsten Mal

    ... und außerdem, wenn du nach $8000 lädst, bist du da mitten im Variablenbereich und überschreibst irgendwann mit Stringinhalten usw. dein Programm. Entweder du nimmst $C000 für dein Programm oder POKEst das BASIC-Ende auf $7FFF runter.

    Danke für den Tipp! dann positioniere ich es besser dort.

  • Um es mit Yoda zu sagen: Einigermaßen doof ich bin...

    Ich zerschieße esmir selbst , da ich später nochmal eine kurze assembler-Geschichte an diese Speicherstelle poke...

    Oh mann,....

    Sorry und danke euch !! Bis zum nächsten Mal

    ... und außerdem, wenn du nach $8000 lädst, bist du da mitten im Variablenbereich und überschreibst irgendwann mit Stringinhalten usw. dein Programm. Entweder du nimmst $C000 für dein Programm oder POKEst das BASIC-Ende auf $7FFF runter.

    Ich merke gerade, dass ich durch den eigenen Zeichensatz und das befolgen der Ratschläge im Eintrag "Zeichen" in c64-Wiki den Speicher ab c000 mit dem VIC-Segment belegt habe. Ich muss mich noch mal genauer in die Speicherbelegung einlesen...

  • Ohne BASIC Programm restart geht das wie folgt:


    Code
    1. open channel,device,1,"filename":poke 780,0:sys 65493:close channel

    Ersetze "channel" z.B. durch 8 oder welchen Kanal du am liebsten nutzen willst und "device" mit der Laufwerksnummer von der du laden willst z.B. 8

  • Ich merke gerade, dass ich durch den eigenen Zeichensatz und das befolgen der Ratschläge im Eintrag "Zeichen" in c64-Wiki den Speicher ab c000 mit dem VIC-Segment belegt habe.

    In der Wiki-Beispiel-Konfiguration ist doch $c000-$c3ff noch frei. Wieso der Wiki-Artikel für den Zeichensatz $c800 vorschlägt, leuchtet mir nicht ein. Das ist ein sehr wertvoller Bereich für Maschinensprache, da er in jeder Konfiguration lesbar ist. Den Zeichensatz würde ich eher ab $e000 laden und evtl. nach $d000 verschieben, falls man im oberen Bereich noch etwas mehr Platz benötigt. Ein weiteres kB kann man bei $0400 bis $07ff nutzen, da dieser Bereich in der Konfiguration nicht mehr als Screen-RAM genutzt wird.

  • Wenn du weiß, wohin das Assembler-Programm geladen wird, kannst du auch per PEEK die Adresse auslesen. Angenommen, dein Programm wird nach $C000 geladen und beginnt mit LDA #$00.

    Dann kann man mittels IF PEEK(49152)=169THEN RETURN, das Problem lösen. Der Vorteilist ist, das Programm wird nicht nachgeladen, wenn es schon im RAM steht.

    Ganz schön riskant. Da sollte man eher Anfang und Ende checken, oder vielleicht sogar eine Prüfsumme auf die ganze Routine.

    Ist aber mit Kanonen auf Spatzen geschossen, das gute alte IFA=1-Idiom reicht ja aus.

    Ich verwende immer eine bestimmte Signatur, ein "Magic" aus 2 Bytes (die keine Code an sich darstellen), wo es schon recht unwahrscheinlich ist, dass zufällig diese Sequenz vorkommt.

    Mein "Funktionsmodule" haben dann den Aufbau in der Art

    Code
    1. *= $c000
    2. bit $FFFF
    3. *=*-2 ; back 2 byte (reset bit-argument)
    4. magic
    5. !scr "jk" ; magic

    Kaum mehr Aufwand als die Hochzählerei mit Variablen, trotzdem erspart man sich das ständige Laden beim Start.