Hello, Guest the thread was called1.9k times and contains 40 replays

last post from JeeK at the

Hilfsroutinen in Assembler / Maschinensprache

  • Hallo zusammen,


    da ich über die Suche nichts gefunden habe: gibt es vielleicht eine Stelle, wo man Hilfsroutinen in Assembler findet, die man in eigene Basic-Programme einbinden kann?


    Hintergrund: Leider übersteigt das Programmieren in 6502-Assembler meine Fähigkeiten, bzw. ich würde viel zu lange brauchen, um mich da reinzuarbeiten. Daher suche ich immer wieder mal Codebeispiele, die ich weiterverwenden kann.


    Im konkreten Fall brauche ich eine Routine, die auf dem C64 im Textbildschirm ein Rechteck einfärbt, und die man z.B. mit sys adr,x,y,width,depth,col aufrufen kann. Es muss nur ins Farbram geschrieben werden. So etwas in der Art gibt es bestimmt schon, aber gefunden habe ich bisher nichts.

  • Da hilft nur eins: Ran an den Speck! :)


    Die Routinen CHKCOM ($aefd) und GETBYT ($b79e) benutzt du, um deine Parameter zu übergeben.


    Die Zeilennummer nimmst du mal 40, rechnest die Spaltennummer dazu, das alles noch zu $D800 addieren, und dann hast du deine Startadresse zum Poken.


    Dann nimmst du eine äußere Schleife für die Zeilen, und eine innere Schleife für die Zeichen in jeder Zeile. Bingo!


    ... oder vielleicht hat ja jemand noch eine einfachere Idee.


    P.S. Ohne Maschinensprache ist der C64 nur halb so schön! :) Und ich bin selber noch beim Lernen und habe noch viel zu tun, aber ich denke, es lohnt sich.

  • Die Zeilennummer nimmst du mal 40

    ..und dafür muss man nicht einmal multiplizieren können: Bei Multiplikation mit einer Konstanten (und die Zeilenlänge beim C64 kann man als sehr konstant ansehen) stellt man diese Konstante als Summe ihrer Bits dar und ersetzt die Multiplikation durch Shifts und Additionen. Beispiel: in 40 sind nur zwei Bits gesetzt, d.h. 40 = 8 + 32 = 2^3 + 2^5.

    Man shiftet also die Zeilennummer drei mal nach links und hat damit das 8-fache. Das speichert man kurz irgendwo hin.

    Man shiftet weitere zwei mal nach links. Damit hat man fünfmal geshiftet und somit das 32-fache. Dazu addiert man das 8-fache von gerade eben und schon hat man das 40-fache.


    ...und wenn das zu kompliziert oder zu langsam ist, nimmt man einfach eine Lookup-Tabelle. :D

  • ..und dafür muss man nicht einmal multiplizieren können: Bei Multiplikation mit einer Konstanten (und die Zeilenlänge beim C64 kann man als sehr konstant ansehen) stellt man diese Konstante als Summe ihrer Bits dar und ersetzt die Multiplikation durch Shifts und Additionen. Beispiel: in 40 sind nur zwei Bits gesetzt, d.h. 40 = 8 + 32 = 2^3 + 2^5.

    Man shiftet also die Zeilennummer drei mal nach links und hat damit das 8-fache. Das speichert man kurz irgendwo hin.

    Man shiftet weitere zwei mal nach links. Damit hat man fünfmal geshiftet und somit das 32-fache. Dazu addiert man das 8-fache von gerade eben und schon hat man das 40-fache.

    Dazu vielleicht noch ein passendes Stück Code:

  • ...und wenn das zu kompliziert oder zu langsam ist, nimmt man einfach eine Lookup-Tabelle.

    ... die im KERNAL sogar schon vorhanden ist (ok, nur für die Low-Bytes, die High-Bytes sind dort im RAM).

    Übrigens auch die Routine, um von x/y-Koordinaten auf die Adresse im Video-RAM zu kommen. Allerdings kann man es natürlich auch noch schneller machen als dort.

  • Danke, das ist eine gute Idee!

    Da hilft nur eins: Ran an den Speck!

    Danke für die Hinweise, aber das Können oder Wollen ist nicht das Problem. Im Prinzip wüsste ich schon, wie man das machen müsste. Auch das Programmieren einer Multiplikation über Shift und Addieren ist mir geläufig. Aber das Programmieren in Assembler ist für mich ganz einfach eine Frage von Aufwand und Nutzen. Bis ich weiß, welche Befehle es in Assembler gibt, und wie man die benutzt, da vergeht sehr viel Zeit. Und die habe ich gerade nicht. Wenn ich ab heute wüsste, dass ich die nächsten Jahre ganz viel Assembler programmiern würde, dann würde es sich lohnen, sich damit weiter zu vertiefen.


    Trotzdem Danke für Deinen Code, immer wieder faszinierend zu sehen, wie das manche aus dem Ärmel schütteln. :-)

  • Aber das Programmieren in Assembler ist für mich ganz einfach eine Frage von Aufwand und Nutzen. Bis ich weiß, welche Befehle es in Assembler gibt, und wie man die benutzt, da vergeht sehr viel Zeit. Und die habe ich gerade nicht.

    Schade! Aber eines sollte man nicht vergessen: Das Suchen nach Fertiglösungen, die gerade zufällig genau zu dem passen, was man haben will, kann ebenfalls sehr zeitraubend sein. Und wirklich lernen tut man nichts dabei.


    Habe jetzt aber mal eine kleine Routine für dein farbiges Rechteck geschrieben. Das klappt so, ist aber möglicherweise nicht optimal geschrieben. Verbesserungsvorschläge sind ggf. willkommen.


    P.S. Code wurde mit dem C64 Studio erstellt.


    P.P.S. Leider geht durch das Pasten meine Formatierung flöten.


  • Schade! Aber eines sollte man nicht vergessen: Das Suchen nach Fertiglösungen, die gerade zufällig genau zu dem passen, was man haben will, kann ebenfalls sehr zeitraubend sein. Und wirklich lernen tut man nichts dabei.

    Das ist mir klar, ich bin keine 15 mehr. Selbst wenn Du die Ziffern umdrehst, kommt das nicht mehr hin. ;-) Der Zeit- und Nutzenfaktor spielt die große Rolle (s.o.).

    Habe jetzt aber mal eine kleine Routine für dein farbiges Rechteck geschrieben.

    Vielen Dank! Ich werde es testen, aber es wird etwas dauern, bis ich es testen kann. Da ich das C64Studio ebenfalls nutze, habe ich jetzt mal ein gutes Beispiel, um damit weiter einzusteigen. Dann lerne ich doch noch etwas.

  • ...und wenn das zu kompliziert oder zu langsam ist, nimmt man einfach eine Lookup-Tabelle. :D

    Man kann die existierenden Tabellen bei $ecf0 (fürs Low Byte) und bei $d9 (fürs High Byte) nehmen, und das Highbyte für das Color Ram modifizieren, wenn man Wert auf kleinen Code legt.

  • Nein, wenn schon umbenennen, dann in Höhe.


    Die Routine funktioniert jedenfalls, und ob die Farbe jetzt neu geladen wird, im y-Register oder mit Push/Pull gespeichert wird, ist hier eher unerheblich.


    Ich kann nur sagen: wenn ich das in Assembler probiert hätte, wäre es viel komplizierter geworden. Die Multiplikation *40 hätte ich wohl gleich mit 2 Bytes realisiert, braucht man hier aber nicht. Die Doppelschleife mit den x- und y-Registern hätte ich so elegant nicht hinbekommen.


    Wenn man noch optimieren möchte, könnte man im Init-Teil in Zeile 47 das Initialisieren von pokead weglassen (die Zeile 48 ist dagegen notwendig), denn der Wert wird in Zeile 58 mit sta pokead sowieso überschrieben.

  • Vorschlag für ab Z. 65: wenn man eh schon im Carry den Überlauf hat und das Color-RAM-Highbyte dazuaddiert, kann man das "verschmelzen"


    lda pokead+1

    adc #>colram

    sta pokead+1


    Das bcc, inc, clc davor fällt weg.


    Weiters würde ich empfehlen - wie auch im TODO angemerkt - die Parameter zu prüfen, weil das in BASIC zu viel Zeit kostet, sowas abzufragen. Darauf verlassen, dass da immer die richtigen Werte kommen, würde ich mich nicht....

    Dabei entweder ein Clipping machen oder mit Fehlermeldung abbrechen.

    Also x nur von 0 bis 39

    y von 0 bis 24

    länge 0 bis 40

    höhe 0 bis 25

    x+länge <= 40

    y+höhe <= 25

  • Guter Punkt! Ich hatte gleich das Gefühl, dass diese ganze Passage etwas umständlich war, jetzt weiß ich auch, warum!


    Allerdings habe ich das gesamte Programm noch einmal umgekrempelt (siehe nächster Beitrag)...


    Bereichsprüfung wäre sicher sinnvoll, aber das ist Arbeit und macht keinen Spaß! :)

  • So, diese Look-up-Tabellen sind ja etwas ganz Wundervolles. Danke an Claus für den Tipp! :thumbsup: Ich musste das gleich mal in eine neue Version einbauen.


    Ich bin jetzt davon ausgegangen, dass die unteren drei Bits in der $d9-Tabelle immer zwischen 100 und 111 liegen. Die oberen 7 Bits lösche ich, dann zähle ich $d4 dazu, sodass als Hibyte etwas im Bereich $d8 bis $db herauskommt.


    Wie kommt die Tabelle ab $d9 eigentlich zustande? Wo liegt die ROM-Routine, von der die Tabelle erzeugt wird? Einfach aus dem ROM kopiert wird sie wahrscheinlich nicht, oder? Falls doch, könnte man ja gleich die ROM-Tabelle selbst nehmen.


    Außerdem habe ich noch den Vorschlag von Lysosom beherzigt ("lda color" statt pha/pla), sodass wir jetzt ein richtiges Community-Projekt haben. :)


    Der Code ist von 120 auf 105 Bytes geschmolzen. Möglicherweise geht da ja noch mehr bzw. weniger.


  • Die Routine (noch die alte Version) ist jetzt in meiner Binäruhr für das Wic64 aktiv.

    Cool! Wenn ich mal ein Wic64 habe, gucke ich mir das an.


    Übrigens, in der neuen Version habe ich Länge und Breite in der Parameterübergabe vertauscht und außerdem in "xdim" und "ydim" umbenannt, um den diesbezüglichen Diskussionsstrang zu beenden. :)