CALL / RCALL / ICALL / EICALL - Call to a Subroutine

CALL Adresse
Adresse: Wert des Programm Counters (PC)

Mit diesem Befehl kann der Adresspointer auf einen neuen Wert gesetzt werden. Dadurch springt die Programmausführung an diese neue Adresse. Zusätzlich wird die Adresse hinter dem Call Befehl auf den Stack gespeichert, so dass eine Rückkehr an diese Stelle mit Hilfe des RET-Befehls möglich ist.
Die Anzahl der Bytes auf dem Stack hängt von der Speichergröße des Prozessors ab. Bis zu 64kWords (=128kByte) Programmspeicher werden 2 Byte Rücksprungadresse auf den Stack geschoben. Darüber werden 3 Byte auf den Stack geschoben. Der Stackpointer passt sich entsprechend an.
Die verschiedenen CALL-Befehle stehen auf verschiedenen Prozessortypen in Abhängigkeit des vorhandenen Adressraums zur Verfügung.

CALL: Spungbefehl innerhalb eines 4MWords (=8MByte) Adressraums.

RCALL: Spungbefehl innerhalb eines 4kWords (=8kByte) Adressraums (±2kWords). Dieser Befehl hat zwar eine eingeschränkte Sprungweite, ist jedoch platzsparender und schneller als der CALL-Befehl.

ICALL: Indirekter Spungbefehl auf die Adresse die im Z-Pointer (PC(15:0)) geladen ist. Dieser Befehl kann nur eine 16-Bit Adresse (innerhalb des unteren Adressbereichs) ansprechen. Es sind 64kWords (=128kByte) ansprechbar, da Adressen immer wortweise adressiert werden.

EICALL: Erweiterter indirekter Spungbefehl innerhalb eines 4MWords (8MByte) Adressraums. Zu dem Z-Pointer wird das EIND-Register für die oberen Adressbits (PC(21:16)) hinzugenommen. Der Befehl ist nur auf Prozessoren mit mehr als 64kWords Adressraum vorhanden.

Achtung: Ein CALL wird normalerweise durch einen Return-Befehl (RET) beendet. Passiert dies nicht, droht ein Stacküberlauf.


Beispiel:

call Label ;Sprung auf die Adresse, die im Code mit 'Label:' gekennzeichnet ist

rcall Label ;Sprung auf die Adresse, die im Code mit 'Label:' gekennzeichnet ist. Funktioniert nur, wenn das Label innerhalb von ±2k-Adressen vor oder hinter dem Sprungbefehl ist.

ldi ZH, high(Label<<1)
ldi ZL, low(Label<<1)
icall ;Sprung auf die Adresse, die im Z-Pointer ist

ldi r0, page(Label<<1) ;Hier werden die Bytes 21-16 einer Adresse geladen
out eind, r0 ;Speichern im EIND-Register
ldi ZH, high(Label<<1) ;Laden von high und low-Byte der Adresse
ldi ZL, low(Label<<1)
eicall ;Sprung auf die Adresse, die im Z-Pointer und im EIND-Register ist

Statusregister: Keine Beeinflussung
Speicherplatz:
CALL: 4 Byte
RCALL: 2 Byte
ICALL: 2 Byte
EICALL: 2 Byte

Taktzyklen:
CALL: 4 (64kWords PC) 5 (4MWords PC)
RCALL: 3 (64kWords PC) 4 (4MWords PC)
ICALL: 3 (64kWords PC) 4 (4MWords PC)
EICALL: 4 (4MWords PC)