Hallo Besucher, der Thread wurde 2,1k mal aufgerufen und enthält 8 Antworten

letzter Beitrag von Mike am

16bit * 8bit Multiplikation - Hilfe

  • Hi zusammen,


    ich bin weiter fleissig am lernen und coden und habe ein kleines Problem.


    Ich verwende folgenden Code aus der Codebase64: 16bit * 8bit


    In meinem Projekt kommt dann folgendes als Code dabei raus:


    Als Ergebnis würde ich nun #$0780 erwarten, also in fa #$07 und in fb #$80 - aber ich habe als Ergebnis im Speicher dann #$0680 stehen ?(


    Hab ich jetzt einen Fehler drin (den ich selbst nach Stunden des intensiven Anstarrens nicht entdecke) oder ist der Codeschnipsel schon fehlerhaft?




    Grüße,
    Schnippe

  • Damit die 16-Bit-Addition mit Carry-Übertrag funktioniert, muss $fa das Lowbyte und $fb das Highbyte sein (also little-endian, wie auf dem 6502 üblich).


    Außerdem solltest Du das STX am Ende durch STA ersetzen, sonst kann man nicht mit Null multiplizieren.

  • Was machst du auf der Zeropage in der Adresse $fa? Da sitzt das Highbyte (MSB) der Adresse des Ausgabebuffers der RS232-Schnittstelle.


    Üblicherweise nimmt man doch $fb bis $fe, zur Vermeidung von Seiteneffekten, die Stellen sind dafür gedacht.

    Die Belegungen kann man nur beachten, wenn man sie auch kennt. Früher (tm) habe ich auch $fa bis $ff für eigene Daten benutzt, aber ich hab keine Ahnung, woher die (falsche) Bereichsinformation ursprünglich stammt.
    Da die wenigsten Programme gleichzeitig mit RS232 eingesetzt werden, macht sich der Fehler normalerweise auch nie bemerkbar (bei $ff sieht das schon anders aus, das hat mindestens einmal Probleme gemacht).

  • Ich wollte einfach für das ganze Projekt (die Multiplikation ist hier nur ein kleiner Teil) einen möglichst zusammenhängenden Block an ZP-Adressen haben, deswegen habe ich einfach die ZP-Adressen mitgenommen welche für RS232 benutzt werden. Denn das kommt mir hier ganz sicher nicht in die Quere. :D


    Bezüglich der Geschwindigkeit habe ich noch keine Tabellenversion implementiert, ich wollte eigentlich so platzsparend wie möglich sein da es im Projekt (zumindest im Moment) nicht auf Geschwindigkeit ankommt. Aber danke für den Hinweis - wird sicher auch noch mal getestet.

  • Das, was Du da jetzt umgesetzt hast, ist die langsamere, dafür aber speichersparende Variante. Die Tabellen-Versionen gehen DEUTLICH schneller.

    Wenn die Multiplikation laufzeitmäßig zu einem "Hotspot" wird, sollte man aber schon überdenken, ob man nicht "versehentlich" eine Multiplikation verwendet, obwohl eigentlich eine Aufsummierung (im Anwendungscode!) in den Iterationen auch funktionieren würde. Sprich, in:


    1. FORT=1TO100:PRINT10*T:NEXT


    2. S=10:FORT=1TO100:PRINTS:S=S+10:NEXT


    ... ist die Multiplikation im ersten Fall erheblich "teurer" als die laufende Summation im zweiten Fall.


    ...


    Für eine Routine zum Zeichnen von Ellipsen brauchte ich auch mal eine 8 Bit x 24 Bit -> 32 Bit Multiplikation. Vier Zeropage-Adressen dienen als 32-Bit-Ergebnis/Akkumulator, der 24-Bit-Faktor steht immer bei höheren Adressen, die aber innerhalb einer Page mit dem Y-Register indexiert werden (das sind also die Arbeitsvariablen), der andere Faktor steht im Akku und es gibt eine Routine, um das 32-Bit-Ergebnis/Akkumulator in eine der Arbeitsvariablen (zurück) zu übertragen (wieder ebenfalls Y-indexiert):

    Die Ellipsen-Routine führt nur ein paar Multiplikationen am Anfang aus, der Rest der Routine arbeitet dann mit 32-Bit-Additionen, -Subtraktionen, -Absolutwertbildungen und -Vergleichen. :)



    P.S. $03..$06 sind ebenfalls frei. Sie werden zwar vom Interpreter mit Adressen zu Umwandlungsroutinen FAC <-> Integer belegt, aber nie benutzt. Und alle Programme, die mir so untergekommen sind, springen die Routinen auch direkt an. ;)