,,Sprung zu beliebiger Adresse" - Kleine Frage dazu

Gast #3725038
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?
#3725059
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
#3725071
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.
Gast #3725095
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?
Gast #3725125
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?
Gast #3725139
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?
#3725161
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
#3725197
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
Gast #3725529
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?
Gast #3725609
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.
Gast #3725663
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
#3725667
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.
Gast #3725741
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
Gast #3726011
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
Gast #3726400
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
#3727641
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
#3727653
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).

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren