Mitch,

an der Stelle musste ich auch lange knobeln ! Du musst den Zeiger verdoppeln, weil die Anweisungen bei den ATmegas immer zwei Bytes (14 Bit) belegen. Ich arbeite viel mit Adressentabellen und habe mir dafür eine extra Assembler-Prozedur geschrieben:

Code:
/*------------------------------------
	PROCEDURE TBL_CALL

Die Prozedur TBL_CALL liest aus einer Adressentabelle, die 
im Programmspeicher abgelegt ist, ein 2-Byte-Adresse aus. 
Sie wird als Programmadresse angesprungen. Das aufrufende
Programm ist selbst dafür verantworlich, dass der maximale
Index nicht überschritten wird. Das aufrufende Programm
wird in der Zeile nach der Anweisung "rcall TBL_CALL "
fortgesetzt.


Eingangsvariablen
	zh:zl:  enhält den Zeiger auf die RAM-Adresse,
	     an der die Sprungtabelle beginnt
	r16: enthält den Index der Adresse, die 
	     angesprungen werden soll

Ausgangsvariablen
	keine

geänderte Register
	zh,zl

geänderte Ports
	keine

*/

TBL_CALL:
	push r17
	in r17,SREG
	push r17


	clr r17
	add zl,r16
	adc zh,r17
	add zl,zl
	adc zh,zh

	lpm r17,z+
	lpm zh,z
	mov zl,r17

	pop r17
	out SREG,r17
	pop r17

	ijmp	

	ret
Die Anwendung im Programm sieht so aus:

Code:
...
PROGRM_TABELLE:
.dw TU_DIES
.dw TU_DAS
.dw TU_JENES
...
...
ldi zl,low(PROGRM_TABELLE) ; Zeiger auf Tabelle nach zh:zl
ldi zh,high(PROGRM_TABELLE)
ldi r16,0x02                         ; Programmteil "TU_JENES" auswählen
rcall TBL_CALL
nop
...

TU_JENES:
nop
ret
...
Das Auslesen der Unterprogramm-Startadresse aus dem Flash geht mit der Anweisung "lpm". Da ich das ausgewählte Unterprogramm in TBL_CALL mit "ijmp" anspringe, bleibt die Rückkehradresse, die noch vom Aufruf von "rcall TBL_CALL" auf dem Systemstack liegt, unverändert. D.h. nach Abarbeiten von "TBL_CALL" und des Unterprogramms ("TU_JENES"), kehrt der Programmablauf zu der nächsten, auf "rcall TBL_CALL" folgenden Anweisung (nop) zurück.

Klappt's so?

mare_crisium