Guten Tag miteinander, momentan Arbeite ich Stück für Stück die AVR ASM Tutorials durch, stoße jedoch immer wider auf Frage auf die ich keine Antwort finde. Meistens sind es Kleinigkeiten wie hier z.B. Es geht um folgenden Artikel: http://www.mikrocontroller.net/articles/AVR-Tutorial:_Stack Genauer um den Letzten Abschnitt (,,Sprung zu beliebiger Adresse"). In der ersten Zeile steht: ,, Kleinere AVR besitzen keinen Befehl, um direkt zu einer Adresse zu springen, die in einem Registerpaar gespeichert ist." Hier habe ich nun eine Frage zum Begriff Registerpaar. Es scheinen wohl zwei Register gemeint zu sein. ZH und ZL z.B. Aber woher weiß ich, dass die Adresse 16Bit lang ist, so dass die Adresse in zwei Registern gespeichert werden speichern muss? Verstehe ich es richtig, dass ich 8Bit lange Adressen ganz normal mit rcall aufrufen kann? Hier die selbe Frage: Woher weiß ich, dass die Adresse 8Bit lang ist?
>Woher weiß ich, dass die >Adresse 8Bit lang ist? Na sicherlich aus dem Datenblatt, bzw zugehöriger Programmingreferenz.
Die (absolute) Adresse ist immer 16 Bit lang. Bei rcall steht keine absolute Adresse (16 Bit) sondern eine relative Adresse (daher 'r'call). Und das bedeutet: "gehe zu einer Adresse in der Nähe von deiner aktuellen Adresse" Die 'Nähe' ist in dem Fall eine 8-Bit-2er-Komplement-Zahl und hat den Bereich -128 ... +127. Gruß Dietrich
Hagrid schrieb: > ,, Kleinere AVR besitzen keinen Befehl, um direkt zu einer Adresse zu > springen, die in einem Registerpaar gespeichert ist." Vorsicht Falle. Es gibt m.W keine AVRs mit indirektem Sprung über ein 8-Bit Register. Selbst bei Zwergen mit nur 256 Worten ROM ist der IJMP über ein Registerpaar definiert. Es könnte sein, dass sich dieser Passus auf steinalte Typen wie den AT90S1200 bezieht, der überhaupt keinen indirekten Sprungbefehl mit programmierbarer Zieladresse kennt. Egal mit welcher Breite. > Verstehe ich es richtig, dass ich 8Bit lange Adressen ganz normal mit > rcall aufrufen kann? Hier die selbe Frage: Woher weiß ich, dass die > Adresse 8Bit lang ist? RCALL adressiert relativ zum aktuellen PC und kann einen Bereich von 2K Worten um den aktuellen PC erreichen. AVRs bis 8KB/4KW besitzen daher keinen CALL Befehl, weil unnötig. Mit 8 Bit hat das nichts zu tun. Ob auf AVRs mit mehr als 8KB ROM das Ziel mit RCALL erreichbar ist ergibt sich aus der Adressdifferenz. Beachte dass die Befehlsadresse wortweise gerechnet wird, nicht byteweise.
:
Bearbeitet durch User
Es ist sinnvoll, parallel zum Tutorial die Befehlssatzbeschreibung 'AVR Instruction Set' zu lesen; das sollte solche "Kleinigkeiten" beantworten.
Dietrich L. schrieb: > Die (absolute) Adresse ist immer 16 Bit lang. Nein. Sie kann auch kürzer oder länger sein. Exakt 16Bit lang ist sie nur bei AVRs mit exakt 128kByte Flash. > Bei rcall steht keine absolute Adresse (16 Bit) sondern eine relative > Adresse (daher 'r'call). Ja. Und zwar eine relative _Wort_adresse mit 12Bit(signed). > Und das bedeutet: "gehe zu einer Adresse in der > Nähe von deiner aktuellen Adresse" Die 'Nähe' ist in dem Fall eine > 8-Bit-2er-Komplement-Zahl und hat den Bereich -128 ... +127. rcall kann entsprechend der verfügbaren 12Bit für die Sprungdistanz und der Word-Adressen natürlich +-4kBytes erreichen. Sag' mal, kannst du mit deinem Halbwissen mal was anderes machen, als Einsteiger zu desinformieren? Z.B. die gesparte Zeit nutzen, um Halbwissen zu Vollwissen zu machen?
an c-hater Vollkommen richtig, nur - es geht, wenn ich den Link richtig interpretiere, doch um ijmp bzw. icall.
Danke euch allen, also was es mit RCALL auf sich hat habe ich nun begriffen. Ich denke ich muss nicht fürchten, dass ich ein Programm schreibe was größer als 4kByte groß ist. Wenn doch, sollte ich das im Hinterkopf behalten. Mein größtes Programm war bislang ein halbes kByte groß. Wenn das Programm größer als 4kByte groß ist könnte man doch die Unterprogramme welche aufeinander zugreifen "näher zusammenbringen" um dann wider einen zugriff per RCALL zu ermöglichen richtig?
Was nun, icall oder rcall? Im letzteren Fall braucht der Hinterkopf nicht bemüht zu werden, der Assembler wird eine Bereichsüberschreitung melden. Ist das Programm größer als 8 (!) kiB groß, wird der Controller auch über die entsprechenden Befehle verfügen, ein "näher zusammenbringen" spart zwar etwas Code und Zeit, verschlechtert aber i.a. die Lesbarkeit. an c-hater Verstehen Sie den letzten Satz auf der verlinkten Seite?
Hagrid schrieb: > momentan Arbeite ich Stück für Stück die AVR ASM Tutorials durch, stoße > jedoch immer wider auf Frage auf die ich keine Antwort finde. > ,, Kleinere AVR besitzen keinen Befehl, um direkt zu einer Adresse zu > springen, die in einem Registerpaar gespeichert ist." Konkret geht es um den IJMP Opcode. Und den gibt es anscheinend auf allen AVRs außer dem AT90S1200. > Hier habe ich nun eine Frage zum Begriff Registerpaar. > Es scheinen wohl zwei Register gemeint zu sein. ZH und ZL z.B. Ja. Ein Paar sind zwei Stück. Erstaunlich. Und im Fall von IJMP sind es nicht nur beispielsweise ZL und ZH, sondern sogar genau ZL und ZH, bzw. als Paar einfach Z. > Aber > woher weiß ich, dass die Adresse 16Bit lang ist, so dass die Adresse in > zwei Registern gespeichert werden speichern muss? Schau halt mal wie groß der Programmspeicher ist. Um die 8KB = 2K Worte eines ATmega8 zu adressieren, wieviele Bits braucht man da? Reicht ein Register dafür aus? > Verstehe ich es richtig, dass ich 8Bit lange Adressen ganz normal mit > rcall aufrufen kann? Es gibt gar keinen AVR µC, bei dem 8 Bit lange Adressen reichen würden (der dürfte dann nur 0.5KB Flash haben). Absolute Sprungbefehle (egal ob indirekt oder nicht) müssen immer den gesamten Adreßraum der CPU erreichen könne, sonst sind sie nutzlos. Zusätzlich scheinst du das noch mit relativen Sprungbefehlen zu vermischen. Die sind nochmal anders, dahingehend daß sie keine absolute Adresse enthalten, sondern eine Adresse relativ zur aktuellen Adresse. Einen solchen Opcode zusätzlich einzuführen ist natürlich nur dann sinnvoll, wenn die relative Adresse kürzer ist als eine absolute (sonst könnte man ja gleich absolut springen). Folgerichtig können relative Sprungbefehle nur einen Teil des Adreßraums erreichen. Und das ist nur deswegen keine Einschränkung, weil man diese verkürzten Sprungbefehle als Optimierung verwendet (der Maschinencode ist kürzer). Falls die Distanz zu weit sein sollte, kann man ja allemal noch einen absoluten Sprung nehmen. Allerdings übernimmt der Assembler für dich das Ausrechnen der Sprung- distanz. Der Assemblercode enthält ein absolutes Sprungziel und der Assembler rechnet einerseits aus, wie weit der Sprung tatsächlich ist und kann andererseits auch durchaus mal einen Fehler zurückgeben, daß die Distanz zu weit ist. Bspw. können die "kleinen" AVR maximal +/- 4KB mit einem RCALL springen. Der Flash ist aber bis 128KB groß. XL
> Der Flash ist aber bis 128KB groß.
Er kann auch größer sein, dafür gibt es dann die extended-Befehle.
Axel Schwenke schrieb: > Es gibt gar keinen AVR µC, bei dem 8 Bit lange Adressen reichen würden > (der dürfte dann nur 0.5KB Flash haben). Doch, gibt es: ATtiny4/5. Die sich allerdings in der Herstellung wohl kaum vom ATtiny10 mit 1KB Flash unterscheiden dürften.
Hagrid schrieb: > Unterprogramme welche aufeinander zugreifen "näher zusammenbringen" um > dann wider einen zugriff per RCALL zu ermöglichen Stimmt! Sind relative Sprünge zu weit, meldet der Assembler einen Fehler. Eine kurze, nur einmalig für einen spez. Zweck benötigte Subroutine kann man auch mitten im Hauptprogramm in Nähe des RCAll implementieren und im normalen Programmablauf mit RJMP über diese Routine hinwegspringen. Bsp.: RCALL Menu - RJMP Weiter - Menu...RET - Weiter
:
Bearbeitet durch User
> Bsp.: RCALL Menu - RJMP Weiter - Menu...RET - Weiter
Gibt es außer einer evtl. besseren Lesbarkeit einen weiteren Grund für
eine solche Konstruktion?
Für viele Leser ist bessere Lesbarkeit bei diesem Konstrukt wohl eher nicht gegeben. Aber der TO hat ja gefragt, was möglich wäre.
der alte Hanns schrieb: > Was nun, icall oder rcall? Im letzteren Fall braucht der Hinterkopf > nicht bemüht zu werden, der Assembler wird eine Bereichsüberschreitung > melden. Manchmal sogar fälschlicherweise, wenn man nichts dagegen tut. Siehe Option "wrap relative jumps" in den Optionen eines Assemblerprojektes. > an c-hater > > Verstehen Sie den letzten Satz auf der verlinkten Seite? Welchen meinst du genau? Der letzte Satz auf der Seite ist: > Ggf ist auch SPH zu berücksichtigen --> 2byte Stack-Pointer Was soll es daran nicht zu verstehen geben?
Ich meinte eigentlich die ganze Klammer am Schluss, aber richtig, es ist der zweitletzte Satz: > (Der in dieser Abhandlung angegebene Befehl MOV ZLow, SPL muss für einen > ATmega8 IN ZL, SPL heißen, da hier SPL und SPH ein I/O-Register sind.
Noch deutlicher: ich habe nie mit dem ATmega8 gearbeitet, aber ein Konstrukt MOV ZLow,SPL kommt mir seltsam vor, und kann es auch sonst in dieser "Abhandlung" nirgends finden.
Hi >Noch deutlicher: ich habe nie mit dem ATmega8 gearbeitet, aber ein >Konstrukt MOV ZLow,SPL kommt mir seltsam vor, und kann es auch sonst in >dieser "Abhandlung" nirgends finden. Das ist auch nicht nur seltsam, sondern schlichtweg Unsinn. Bei AVRs dient 'mov' zum Kopieren zwischen zwei Registern im Bereich r0..r31. SPL/SPH liegt aber immer im IO-Bereich, auf den mit 'mov' gar nicht zugegriffen werden kann. Die Einschränkung beim ATMega8 kommt eher daher, das der Autor nur diesen AVR gekannt hat. MfG Spess
Gab es überhaupt jemals einen AVR, der MOV *,SPL kennt? Oder ist das nur eine Besonderheit eines Assemblers, der MOV abhängig vom Operanden unterschiedlich codiert? Das Tutorial beschreibt eine Methode, indirekt über PUSH/RET zu springen. Welcher AVR hat zwar PUSH, nicht aber IJMP? Ich habe auf die Schnelle keinen gefunden.
:
Bearbeitet durch User
Hi >Gab es überhaupt jemals einen AVR, der MOV *,SPL kennt? Nein. Die Dokumente 'Weitere Informationen (von Lothar Müller):' sind ein Mischmasch aus AVR- und 8051-Assembler. MfG Spess
Hi
Auf diese frage kann ich antworten...
>Welcher AVR hat zwar PUSH, nicht aber IJMP?
Atmega8 A
bei dem ging's nicht, oder der Assembler hat es nicht zugelassen.
Im Übrigen, tolle Diskussion...
Gruß oldmax
oldmax schrieb: >>Welcher AVR hat zwar PUSH, nicht aber IJMP? > Atmega8 A Mein Datasheet vom ATmega8, mit und ohne A, enthält IJMP.
Hi Richtig... aber probier es mal aus. Und soweit ich mich erinnern kann, steht da auch was betreffendes im Datenblatt. Möglicherweise in einer Fußnote. Gruß oldmax
Hi >Und soweit ich mich erinnern kann, >steht da auch was betreffendes im Datenblatt. Möglicherweise in einer >Fußnote. Da steht nichts drin. ICALL taucht sogar bei der Stackbehandlung auf. Das hatte bestimmt eine andere Ursache. MfG Spess
oldmax schrieb: > Richtig... aber probier es mal aus. GCC 4.7.2 erzeugt und assembliert seelenruhig IJMP. > Und soweit ich mich erinnern kann, > steht da auch was betreffendes im Datenblatt. Möglicherweise in einer > Fußnote. Ich finde nichts (bzw. der Document Reader findet IJMP nur an exakt einer Stelle).
Hi Also, das ist mir fast peinlich.... aber ich weiß, das ich mit IJMP eine Sprungtabelle abarbeiten woolte und der Assembler gemeckert hat. Der Atmega8, den ich verwende ( hab ihn jetzt grad nicht zur Hand, sonst könnt ich genaueres sagen) war ausgeklammert. Aber vielleicht war es tatsächlich ein Fehler meinerseits. Das käme mir aber sehr gelegen und es wäre einer der seltenen Fälle, wo ich über meine Fehler erfreut wär. Gruß oldmax
Hi Nochmal kurz zu ICALL und IJMP. Manchmal stell ich mich aber auch etwas dusselig an
1 | ICALL Z |
ist natürlich falsch. Einfach nur
1 | ICALL |
und gut. Trotzdem, in der Hilfe von AVR Studio wird darauf hingewiesen; >This instruction is not available in all devices. >Refer to the device specific instruction set summary. Darauf bin ich dann auch prompt eingestiegen..... Gruß oldmax
oldmax schrieb: >This instruction is not available in all devices. Das stimmt ja auch. Im AT90S1200 gibts ihn nicht. PUSH aber auch nicht.
Hi >Im AT90S1200 gibts ihn nicht. PUSH aber auch nicht. Ebenso ATTiny11/12/15. Alles AVRs ohne RAM. MfG Spess
>Absolute Sprungbefehle (egal ob >indirekt oder nicht) müssen immer den gesamten Adreßraum der CPU >erreichen könne, sonst sind sie nutzlos. Na dann gugg mal bei PIC.
MCUA schrieb: >>Absolute Sprungbefehle (egal ob >>indirekt oder nicht) müssen immer den gesamten Adreßraum der CPU >>erreichen könne, sonst sind sie nutzlos. > Na dann gugg mal bei PIC. Die kleinen PIC bis einschließlich PIC18 sind nutzlos. Der einzige Grund sich die anzusehen besteht darin, daß man danach weiß wie man eine CPU Architektur nicht baut. Oder man ist Masochist. XL
Axel Schwenke schrieb: > Oder man ist Masochist. Oder es ist dem Anwender schietegal was der Compiler an umständlichem Code erzeugt, so lange der ins ROM passt und schnell genug ist. Der wahre Masochist ist der Autor des Compilers. Architekturen, die Probleme haben, in einem einzelnen Befehl direkt im gesamten Adressraum rumspringen zu können, waren und sind nicht wirklich selten. Dazu gehören naturgemäss die 32-Bitter mit maximal 32 Bits umfassenden festem Befehlsformat, sowie die 64-Bitter. Aber auch 8-Bitter jenseits PIC waren dabei, wie SC/MP, der in direkter Form nur mit 8-Bit Displacement springen konnte. Das war selbst für damalige Verhältnisse (70er) etwas krass (aber billig).
:
Bearbeitet durch User
>Die kleinen PIC bis einschließlich PIC18 sind nutzlos. NaNa. So extrem schlimm ists auch nicht. Bei PIC18 hat der PC immerhin 21 Bits, die (20) auch in CALL rein passen. Der hat das Problem nicht.
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.