Forum: Mikrocontroller und Digitale Elektronik Sprungtabelle


von Christoph Wolthaus (Gast)


Lesenswert?

Hab folgendes Problem:

Abhängig von einem BYte soll ein entsprechendes Programm ausgeführt
werden:
Bisher mache ich das so:
byte --> r16

cpi r16,0x00
breq prg0jmp
cpi r16,0x01
breq prg1jmp
...

prg0jmp:
rjmp prog0
prg1jmp:
rjmp prog1
...
prog0:
 //code

prog1:
//code

Das muss aber viel viel einfacher gehen mit ijmp oder so etwas.
Hat da jemand ne elegante Lösung für mich?

von Christoph Kessler (Gast)


Lesenswert?

skip if bit set...
rjmp
rjmp

ist der Code so lang, dass der branch nicht reicht?

von Aleksej (Gast)


Lesenswert?

Ja, wenn du die absolute Adresse von deiner Sprungtabelle im Register Z
hast (
  ldi  ZL,low(prg0jmp*2)    ; low
  ldi  ZH,high(prg0jmp*2)    ; high
), dann geht es bisschen einfacher:

  add zl, r16
  brcc no_carry
  inc zh
no_carry:
  ijmp

von Christoph Wolthaus (Gast)


Lesenswert?

JA der ist zu lang. Und mit deinem Vorschlag kann ich zunächst auch nur
8 Programme ansteuern. ODER ? Dachte an sowas wie

(i)jmp label + r16 * (länge vom rjmp)

Label:
Rjmp prog0
Rjmp prog1
Rjmp prog2
Rjmp prog3
Rjmp prog4

nur ich würde ganz gerne einer multiplikation aus dem weg gehen.

von Aleksej (Gast)


Lesenswert?

Bemerkung:
mit zl sollst du erst LSL machen (mal 2)

von Aleksej (Gast)


Lesenswert?

falsch! lsl r16 - so soll es sein

von Hannes L. (hannes)


Lesenswert?

Oder so:

menujump:               ;Menüpunktaufruf
 ldi zl,low(menujmp)        ;Zeiger auf Sprungtabelle
 ldi zh,high(menujmp)
 add zl,mp                  ;Menüpunkt
 adc zh,null                ;dazu
 ijmp                       ;Menüpunkt aufrufen


menujmp:                ;Menü-Sprungtabelle
 rjmp mp_00
 rjmp mp_01
 rjmp mp_02
 ...

mp_00:                  ;Hauptmenü, Ebene Edit
 sbrc flags,v24rx           ;PC-Verbindung aktiv? nein...
 rcall usart_aus            ;ja, deaktivieren...
 mov ztl,ff                 ;Uhr auf
 mov zth,ff                 ;-1
 cbr flags,1<<aktiv         ;und aus
 rcall testmax              ;Anzahl Schüsse ermitteln
 rjmp editliste             ;Liste aufbauen und Menütexte anzeigen


Alles im Zusammenhang hier zu sehen:
http://www.hanneslux.de/avr/zuenduhr/ZndUhr01.asm

...

von Christoph Wolthaus (Gast)


Lesenswert?

DRei fragen an Aleksej:
a)
wofür die multiplikation mit zwei?
b)
reicht es den Wert von Z einfach mit meinem Inhalt von r16 zu erhöhen?
oder muss ich die länge eines rjmp-Befehl noch multiplizieren
c)
meine tabelle sähe dann so aus?:
prg0jmp:
rjmp prog0
rjmp prog1
rjmp prog2

von Christoph Wolthaus (Gast)


Lesenswert?

sorry ihr seit mir zu schnell!

von Hannes L. (hannes)


Lesenswert?

Die Multiplikation mit 2 ist für byteweisen Zugriff bei LPM
erforderlich, bei IJMP aber nicht, da hier der Zugriff wordweise
erfolgt.

...

von Hannes L. (hannes)


Lesenswert?

> sorry ihr seit mir zu schnell!

Wir sind auch Mehrere, du nur Einer...

Wir teilen uns quasi die Arbeit...

;-)

...

von Christoph Kessler (Gast)


Lesenswert?

Baumartig verzweigen:
cpi $80
brge...
cpi $40
brge...
cpi $20
das ist jedenfalls schneller als 255 Vergleiche nacheinander, nach 8
Vergleichen hat man 256 Sprungziele erreicht

von Remo (Gast)


Lesenswert?

Das geht auch einfacher mit IJmp oder ICall.
Aufpassen: diese Befehle können manche AVR Controller nicht, also
besser vorher im Datenblatt nachschlagen.

Im Prinzip funktioniert das so (habs die Syntax nicht ausprobiert):

; Sprungtabelle in Z-Pointer laden
   LDI ZL, low(Sprungtabelle)
   LDI ZH, high(Sprungtabelle)
;hier musste nochmals nachschlagen das Prinzip sollte klar sein, der
Assembler soll das low byte der Adresse der Sprungtabelle in ZL laden
dito für ZH, die Syntax sieht bestimmt ein bischen anders aus.

; Nachdem jeder Eintrag in der Sprungtabelle 2 byte gross ist musst du
den Index-Wert in R16 noch mit 2 multiplizieren das enspricht einem
linksshift.
   LSL R16
;Nun index auf Z draufaddieren (auf überlauf des lowbyte achten!)
; daher vorher ein Register mit 0 laden
   SUB R0,R0      ; R0 wird mit 0 geladen
   ADD ZL, R16    ; R16 wird auf ZL addiert und C ggfs. gesetzt
   ADC ZH, R0     ; ZH = ZH + 0 + C, ggfs carry draufaddieren. zum
Registersparen geht das auch ohne R0 mit Abfrage des Carrybits und
einem eventuellen INC des ZH.

; Nun der eingentliche Sprung
   Ijmp
; Hier nun die Sprungtabelle
Srungtabelle:
   rjmp prog0
   rjmp prog1
   rjmp prog2
   ....

ciao
Remo

von Christoph Wolthaus (Gast)


Lesenswert?

HEY HANNES!!
Genau das isses! Alles Befürchtugen sind dahin, das funzt! Danke an
Euch alle!

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.