Forum: Mikrocontroller und Digitale Elektronik ,,Sprung zu beliebiger Adresse" - Kleine Frage dazu


von Hagrid (Gast)


Lesenswert?

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?

von Jens G. (jensig)


Lesenswert?

>Woher weiß ich, dass die
>Adresse 8Bit lang ist?

Na sicherlich aus dem Datenblatt, bzw zugehöriger Programmingreferenz.

von Dietrich L. (dietrichl)


Lesenswert?

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

von (prx) A. K. (prx)


Lesenswert?

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
von der alte Hanns (Gast)


Lesenswert?

Es ist sinnvoll, parallel zum Tutorial die Befehlssatzbeschreibung 'AVR 
Instruction Set' zu lesen; das sollte solche "Kleinigkeiten" 
beantworten.

von c-hater (Gast)


Lesenswert?

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?

von der alte Hanns (Gast)


Lesenswert?

an c-hater

Vollkommen richtig, nur - es geht, wenn ich den Link richtig 
interpretiere, doch um ijmp bzw. icall.

von Hagrid (Gast)


Lesenswert?

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?

von der alte Hanns (Gast)


Lesenswert?

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?

von Axel S. (a-za-z0-9)


Lesenswert?

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

von der alte Hanns (Gast)


Lesenswert?

> Der Flash ist aber bis 128KB groß.

Er kann auch größer sein, dafür gibt es dann die extended-Befehle.

von (prx) A. K. (prx)


Lesenswert?

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.

von Rainer V. (rudi994)


Lesenswert?

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
von der alte Hanns (Gast)


Lesenswert?

> Bsp.: RCALL Menu - RJMP Weiter - Menu...RET - Weiter

Gibt es außer einer evtl. besseren Lesbarkeit einen weiteren Grund für 
eine solche Konstruktion?

von Rainer V. (rudi994)


Lesenswert?

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.

von c-hater (Gast)


Lesenswert?

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?

von der alte Hanns (Gast)


Lesenswert?

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.

von der alte Hanns (Gast)


Lesenswert?

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.

von spess53 (Gast)


Lesenswert?

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

von (prx) A. K. (prx)


Lesenswert?

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
von spess53 (Gast)


Lesenswert?

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

von oldmax (Gast)


Lesenswert?

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

von (prx) A. K. (prx)


Lesenswert?

oldmax schrieb:
>>Welcher AVR hat zwar PUSH, nicht aber IJMP?
> Atmega8 A

Mein Datasheet vom ATmega8, mit und ohne A, enthält IJMP.

von oldmax (Gast)


Lesenswert?

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

von spess53 (Gast)


Lesenswert?

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

von (prx) A. K. (prx)


Lesenswert?

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).

von oldmax (Gast)


Lesenswert?

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

von oldmax (Gast)


Lesenswert?

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

von (prx) A. K. (prx)


Lesenswert?

oldmax schrieb:
>This instruction is not available in all devices.

Das stimmt ja auch. Im AT90S1200 gibts ihn nicht. PUSH aber auch nicht.

von spess53 (Gast)


Lesenswert?

Hi

>Im AT90S1200 gibts ihn nicht. PUSH aber auch nicht.

Ebenso ATTiny11/12/15. Alles AVRs ohne RAM.

MfG Spess

von MCUA (Gast)


Lesenswert?

>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.

von Axel S. (a-za-z0-9)


Lesenswert?

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

von (prx) A. K. (prx)


Lesenswert?

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
von MCUA (Gast)


Lesenswert?

>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
Noch kein Account? Hier anmelden.