jal
lyszt.net behandelt jal und andere RISC-V-Befehle ausführlicher.
Kodierungsformat
Beschreibung
jal ruft eine Funktion auf. Eine Funktion ist ein benannter Block von Anweisungen, der von mehreren Stellen aus ausgeführt werden kann und dann zurückkehrt, sodass die Logik einmal geschrieben und überall verwendet wird. Ein Funktionsaufruf erfordert zwei Dinge. Das Programm springt dorthin, wo sich die Funktion befindet, und es merkt sich, woher es kam, um danach zurückzukehren. jal macht beides, und sein Name bedeutet jump and link.
Der Sprung geht zu einem Label, das die Funktion markiert. Der Link-Teil geschieht vor dem Sprung. jal speichert die Adresse der nächsten Anweisung, also der direkt nach dem Aufruf, in einem Register. Die Funktion verwendet diese gespeicherte Adresse, um zurückzukehren.
Konventionell geht die gespeicherte Adresse in ein Register namens ra, für return address. Die folgende Zeile springt zur Funktion square und hinterlässt in ra die Rücksprungadresse.
jal ra, square
Wenn die Funktion endet, kehrt sie zurück, indem sie zur Adresse in ra springt, was die Anweisung ret tut. Die übliche Kurzform für denselben Aufruf ist unten gezeigt.
call square
Das RISC-V-Handbuch sagt, dass der Sprungversatz in Vielfachen von 2 Bytes gezählt, vorzeichenerweitert und zur Adresse der Sprunganweisung addiert wird. Das ergibt einen Bereich von plus oder minus 1 MiB, wobei ein MiB 1.048.576 Bytes ist. jal speichert die Adresse der folgenden Anweisung, also pc plus 4, in rd. Die standardmäßige Software-Aufrufkonvention verwendet x1 als Rücksprungadressregister und x5 als alternatives Link-Register. Die unbedingten Sprunganweisungen verwenden pc-relative Adressierung, was positionsunabhängigen Code unterstützt, also Code, der funktioniert, wo auch immer er im Speicher geladen wird.
Ein jal überschreibt ra mit einer neuen Rücksprungadresse. Wenn eine Funktion eine andere Funktion aufruft, ersetzt der innere Aufruf die gespeicherte Adresse des äußeren. Eine Funktion, die selbst Aufrufe macht, muss ra zuerst speichern und vor der Rückkehr wiederherstellen. Das Beispiel ruft square auf und hinterlässt die Rücksprungadresse in ra.
Beispiel
jal ra, square # call square; ra holds the return address
