Forum: Mikrocontroller und Digitale Elektronik rjmp jmp ---> bei IJMP ATmega1284 ASSEMBLER


von Bernhard S. (bernhard)


Lesenswert?

Geschätztes Forum,

folgenden Effekt kann ich mir nicht erklären,
so funktioniert es:


  ldi ZL, LOW (SPRUNGMARKE)
  ldi ZH, HIGH(SPRUNGMARKE)
  add ZL,R16
  adc ZH,NULL
  IJMP                ; SPRUNG (Zeiger nach Z)
SPRUNGMARKE:
  rjmp ROUTINE_A
  rjmp ROUTINE_B
  rjmp ROUTINE_C
  rjmp ROUTINE_D
  rjmp ROUTINE_E


Aber so, nur komische Effekte, aber keine Fehlermeldung im 
AVR-Studio4:


  ldi ZL, LOW (SPRUNGMARKE)
  ldi ZH, HIGH(SPRUNGMARKE)
  add ZL,R16
  adc ZH,NULL
  IJMP                ; SPRUNG (Zeiger nach Z)
SPRUNGMARKE:
  jmp ROUTINE_A
  jmp ROUTINE_B
  jmp ROUTINE_C
  jmp ROUTINE_D
  jmp ROUTINE_E


Danke

Bernhard


Nachtrag: betrifft den ATmega1284P

von Peter II (Gast)


Lesenswert?

die Reichweite von rjmp begrenzt. Es kommt vermutlich darauf an, wo denn 
ROUTINE_A im Speicher liegt. ist sie Relativ weit weg, oder relativ am 
Anfang?

von der alte Hanns (Gast)


Lesenswert?

jmp belegt zwei Worte, das add/adc R16 muss also zweimal erfolgen.

von Bernhard S. (bernhard)


Lesenswert?

Ich danke Euch !

>jmp belegt zwei Worte

So funktioniert es:

  ldi ZL, LOW (SPRUNGMARKE)
  ldi ZH, HIGH(SPRUNGMARKE)

  LSL R16              ; mal 2 (nur bei R16=0...127)

  add ZL,R16
  adc ZH,NULL
  IJMP                ; SPRUNG (Zeiger nach Z)
SPRUNGMARKE:
   ...



Bernhard

von c-hater (Gast)


Lesenswert?

Bernhard S. schrieb:

> So funktioniert es:
>
>   ldi ZL, LOW (SPRUNGMARKE)
>   ldi ZH, HIGH(SPRUNGMARKE)
>
>   LSL R16              ; mal 2 (nur bei R16=0...127)
>
>   add ZL,R16
>   adc ZH,NULL
>   IJMP                ; SPRUNG (Zeiger nach Z)
> SPRUNGMARKE:

Und so funktioniert es auch dann, wenn in R16 Werte zwischen 128 und 255 
stehen:

  ldi ZL, LOW (SPRUNGMARKE)
  ldi ZH, HIGH(SPRUNGMARKE)

  lsl R16
  adc ZH,NULL
  add ZL,R16
  adc ZH,NULL
  ijmp

SPRUNGMARKE:
  jmp ROUTINE_A
  ...

Kostet allerdings auch einen Takt mehr als deine Variante.

Oder, noch besser, dauert nämlich genauso nur einen Takt mehr, spart 
aber dafür auch noch die Hälfte des Flashspace für die Sprungtabelle:

  ldi ZL, LOW (SPRUNGMARKE<<1)
  ldi ZH, HIGH(SPRUNGMARKE<<1)

  lpm R16,Z+
  lpm ZH,Z
  mov ZL,R16
  ijmp

SPRUNGMARKE:
  .DW ROUTINE_A
  ...

von der alte Hanns (Gast)


Lesenswert?

Für den allgemeinen Einsatz fehlt da aber RAMPZ.

von der alte Hanns (Gast)


Lesenswert?

Ich vergaß: sowie elpm.
Und dann dauert es erstens länger und wird zweitens nicht so ganz 
einfach.

von der alte Hanns (Gast)


Lesenswert?

Okay, bei der Ausführungszeit lagen wir beide falsch, es fällt ja das 
jmp weg.
Trotzdem würde ich die erste Lösung mit zweifachem Addieren vorziehen.

von c-hater (Gast)


Lesenswert?

der alte Hanns schrieb:

> Trotzdem würde ich die erste Lösung mit zweifachem Addieren vorziehen.

Ich auch. Die zweite war namlich schlicht und einfach völliger Blödsinn. 
Da fehlt der entscheidende Schritt, der Sprungverteiler. Deswegen war 
das wohl auch so überraschend schnell...

Aber für Routine_A hätte es immerhin tatsächlich funktioniert. ;o)

Einfach vergessen diesen Quatsch. OMG, heute ist wohl echt nicht mein 
Tag.

von der alte Hanns (Gast)


Lesenswert?

Zwar verstehe ich nicht ganz, was Sie jetzt meinen, aber egal, mein Tag 
war's heute nämlich auch nicht.
Ich steig wieder aufs Turmdach rauf.

von der alte Hanns (Gast)


Lesenswert?

Ah - jetzt - ja: die adds fehlen.
Bleibt also nur die Platzersparnis, und die ist bei Assembler auf einem 
1284 wohl eher nachrangig.
(Wie schon erwähnt, dauert's bei mir heute besonders lange)

Schönen Abend noch.

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.