Hallo, ich arbeite mich zur Zeit als blutiger Programmieranfänger durch das AVR-Assembler-Tutorial. Soweit habe ich eigentlich alles gut verstanden und auch schon erste kleine eigene Programme zur Led-Ansteuerung ausgetüftelt. Allerdings hänge ich jetzt schon seit gestern Abend an folgender Stelle: Zitat: Der Befehl lpm dient zum Laden einzelner Bytes aus dem Programmspeicher. Das ist vor allem für Tabellen mit konstanten Werten sehr nützlich (7-Segmentdekoder, Zeichensätze, Kennlinien, Parameter Texte, etc.) Doch wie kommt man nun in dem wortweise adressierten Programmspeicher an einzelne Bytes? Ganz einfach. Der AVR "mogelt" hier und erwartet im Z-Register eine Byte-Adresse. Von dieser Adresse bilden die Bits 15..1 die Wortadresse, welche zur Adressierung des Programmspeichers verwendet wird. Bit 0 entscheidet dann, ob das hoch- oder niederwertige Byte in das Zielregister kopiert werden soll (0=niederwertiges Byte; 1=höherwertiges Byte). Darum muss bei Verwendung des Befehls lpm die Anfangsadresse immer mit zwei multipliziert werden. Zitat Ende. Wieso man die eigentliche Programmspeicheradresse mit 2 multiplizieren muss verstehe ich (alle Bits werden 1 nach links geshiftet, sodass die eigentlich Programmspeicheradresse (die ja eh nur 12 Bit lang ist) auf den Bits 15-1 liegt). Was mir allerdings unklar ist, ist wie jetzt bestimmt wird, welches Byte denn jetzt geladen werden soll. Denn das unterste Bit ist nach einer Multiplikation mit 2 doch immer 0 oder nicht? Oder ist es so, dass man generell erst das low Byte lädt, dann den Z-Pointer mit lpm r16,Z+ auf das high Byte setzt und anschliesend das lädt? Verstehe ich es richtig, dass der Z-Pointer nur im Zusammenhang mit dem lpm Befehlt Byte-Weise positioniert wird und ansonsten immer auf eine komplette 16bit Programmspeicheradresse zeigt die dann in ZL und ZH aufgeteilt ist und z.b. mit ijmp angesprungen werden kann? Vielen Dank! Gruß, Timo
Timo schrieb: > den Bits 15-1 liegt). Was mir allerdings unklar ist, ist wie jetzt > bestimmt wird, welches Byte denn jetzt geladen werden soll. Denn das > unterste Bit ist nach einer Multiplikation mit 2 doch immer 0 oder > nicht? 2 Dinge * wenn du mittels eines Labels irgendetwas im Programmspeicher unterbringst, dann sorgt der Assembler schon dafür, dass es auf die gerade Adresse zu liegen kommt. d.h. in dem Fall brauchst du einfach nur die Adresse (in Form des Labels) beim Laden des Z-Pointers mal 2 nehmen und alles passt. * zweitens. Auch der Z-Pointer ist im Grunde nur eni Register (eigentlich Registerpärchen) wie jedes andere. Alle Befehle, die auf Register anwendbar sind, funktionieren selbstverständlich auch für das Registerpärchen R30/R31 (welche ja den Z-Pointer darstellen). Insbesondere kann man selbstverständlich nach dem Laden noch 1 dazuzählen oder man kann das selbstverständlich auch direkt beim Laden des Z-Pointers schon angeben. Der Assembler kann ja rechnen. Er hat ja auch die Adresse (die durch das Label gegeben ist) mal 2 rechnen können. Da kann er dann auch ruhig noch 1 dazuzählen. > > Oder ist es so, dass man generell erst das low Byte lädt, dann den > Z-Pointer mit lpm r16,Z+ auf das high Byte setzt und anschliesend das > lädt? Das macht jetzt aber was anderes., mittels lpm r16, Z+ lpm r17 lädst du ja 2 hintereinanderliegende Bytes aus dem Flash. > Verstehe ich es richtig, dass der Z-Pointer nur im Zusammenhang mit dem > lpm Befehlt Byte-Weise positioniert wird und ansonsten immer auf eine > komplette 16bit Programmspeicheradresse zeigt die dann in ZL und ZH > aufgeteilt ist Der Z-Pointer ist immer in ZH und ZL aufgeteilt (volgo R30/R31)
>Was mir allerdings unklar ist, ist wie jetzt bestimmt wird, welches Byte >denn jetzt geladen werden soll. Denn das unterste Bit ist nach einer >Multiplikation mit 2 doch immer 0 oder nicht? Was hindert Dich daran unmittelbar nach der Multiplikation noch eine weitere Operation anzufügen, die das zu ladende Byte bestimmt? Stimmt. Nichts. >Oder ist es so, dass man generell erst das low Byte lädt, dann den >Z-Pointer mit lpm r16,Z+ auf das high Byte setzt und anschliesend das >lädt? Nein. Mit lpm r16,Z+ wird sowohl ein Byte geladen und Z erhöht. Es wäre sinnlos, generell erst das low Byte laden. Es mag z.B. sein, das man nur das Byte an der ungeraden Adresse braucht. Wozu dann noch das an der geraden Adresse laden? >Verstehe ich es richtig, dass der Z-Pointer nur im Zusammenhang mit dem >lpm Befehl Byte-Weise positioniert ... Nicht nur. Aber beim lpm Befehl schon. > ... und ansonsten immer auf eine komplette 16bit Programmspeicheradresse zeigt die dann in ZL und ZH aufgeteilt ist und z.b. mit ijmp angesprungen werden kann? Nein. Nicht "ansonsten". Was Du beschreibst ist die Interpretation des Wertes in Z im Falle des ijmp. Es gibt andere Interpretationen. In der Befehlsbeschreibung stehen die weiteren.
Zu spät. Man soll halt nicht während des Antwortens noch Tee kochen. :-{
Vielen Dank erst mal ihr Beiden!! :) Das bringt mich weiter. Karl Heinz Buchegger schrieb: > Das macht jetzt aber was anderes., mittels > > lpm r16, Z+ > lpm r17 > > lädst du ja 2 hintereinanderliegende Bytes aus dem Flash. Kali schrieb: > Nein. Mit lpm r16,Z+ wird sowohl ein Byte geladen und Z erhöht. Stimmt... da hab ich wohl einmal zu viel geladen Kali schrieb: > Nein. Nicht "ansonsten". Was Du beschreibst ist die Interpretation des > Wertes in Z im Falle des ijmp. Es gibt andere Interpretationen. In der > Befehlsbeschreibung stehen die weiteren. Ah natürlich.. ich verstehe. Der Z-Pointer enthält einfach eine Adresse des Programmspeichers. Die Befehle können damit dann natürlich machen was sie wollen :) (lpm sieht einfach die obersten 15 Bits als Programmspeicheradresse von der geladen werden soll an) Kali schrieb: > Was hindert Dich daran unmittelbar nach der Multiplikation noch eine > weitere Operation anzufügen, die das zu ladende Byte bestimmt? > Stimmt. Nichts. Stimmt.. jetzt wo du es sagst. Frage mich, wieso ich mich damit jetzt so schwer getan habe. Ist doch eigentlich alles nur logisch :) Warscheinlich muss sich mein Hirn erst mal an die neue Denkweise mit den ganzen Registern und Speicheradressen gewöhnen, ist doch recht viel neuer Stoff den es zu verarbeiten gilt.
Timo schrieb: > Ah natürlich.. ich verstehe. Der Z-Pointer enthält einfach eine Adresse > des Programmspeichers. Die Befehle können damit dann natürlich machen > was sie wollen :) (lpm sieht einfach die obersten 15 Bits als > Programmspeicheradresse von der geladen werden soll an) Du magst jetzt vielleicht lächeln, aber das, genau das, ist eine ganz wichtige Erkentniss in so gut wie allen Programmiersprachen, ganz speziell aber in Assembler. Die Kombination von Befehlen macht das Rennen. Die Befehle selbst sind eigentlich ganz einfach.
Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.