Zu 1. ist schon alles gesagt...
Zu 2.: ret und reti sind nicht völlig verschieden. Der einzige
Unterschied ist, dass reti das I-Bit im SREG setzt und dementsprechend
die Interrupt-Bearbeitung wieder freigibt. Das ist wichtig beim
Rücksprung aus einem Interrupt Handler. Man kann sagen: Rücksprung aus
einem "normalen" Unterprogramm, das mit call, rcall oder icall
aufgerufen wurde, immer mit ret, Rücksprung aus Interrupt Handler mit
reti.
rcall ist ein relativer Unterprogrammaufruf, der aufgrund der
verfügbaren Adressbreite max. 8 KiB Programmspeicher (4 Ki-Worte)
adressieren kann, aber weniger Speicher (1 Programmwort) benötigt, als
der normale call (2 Worte). Deshalb gibt es auf den AVRs bis einschl. 8
KiB Flash auch nur den rcall-Befehl, weil sich mit dem der komplette
Speicher ansprechen lässt. Bei den AVRs ab 16 KiB Flash brauchts dann
den call. Gleiches gilt für jmp und rjmp (und wegen der größeren Breite
von jmp gegenüber rjmp sind auch bei den AVRs ab 16 KiB die
Interrupt-Vektoren doppelt so breit, eben damit auch ein jmp reinpasst;
beliebter Anfänger- bzw. Umsteiger-Fehler!). icall ist ein indirekter
call, der die Sprungmarke nicht im Befehl selbst eingebaut hat, sondern
diese aus einem Pointer-Register bezieht.