call疑似

call

疑似
RISC-V アセンブリ 参考

lyszt.netはcallおよびその他のRISC-V命令をより詳しく扱っています。

説明

call は関数を実行し、戻り値を処理します。関数へジャンプし、戻りアドレスを ra に格納することで、関数が戻れるようにします。これは擬似命令であり、通常は以下の命令に展開されます。

jal ra, label

関数が遠すぎて単一のジャンプでは届かない場合、アセンブラはその距離をカバーするより長いシーケンスに置き換えます。関数名を指定して call を書くことで意図を明示し、形式の選択はアセンブラに委ねられます。jal の項目では、ジャンプと戻りアドレスの保存について説明しています。以下の行は square 関数を呼び出します。

call square

関数を呼び出すには、呼び出し側と呼び出された側の間で情報がどのように受け渡されるかについての取り決めも必要です。その取り決めが呼び出し規約です。呼び出し側は関数の入力を引数レジスタ(a0、a1 など)に入れ、関数が戻ったら a0 から結果を読み取ります。双方が同じ規則に従うため、別々に書かれたコードでも連携して動作します。

すべての call は ra を上書きします。自身で呼び出しを行う関数は、呼び出しを行う前に関数が受け取った ra を保存し、自身が戻る前にその値を復元します。これを行わないと、内側の呼び出しの戻りアドレスが外側のものを置き換えてしまい、関数は戻れなくなります。他に何も呼び出さない関数は ra を保存する必要はありません。

RISC-V マニュアルには、標準的なソフトウェア呼び出し規約が戻りアドレスレジスタとして x1 を使用すると記載されています。jal はプラスマイナス 1 MiB(MiB は 1,048,576 バイト)以内のターゲットに到達します。それより遠いターゲットには auipc に続く jalr が必要で、これは 32 ビットの pc 相対アドレス範囲のどこにでも到達できます。

この例では、a0 に 6 を入れて square を呼び出し、その後 a0 に 36 が得られます。引数は規約を通じて入り、結果は規約を通じて出てきます。

展開先

jal ra, label

アセンブラはこの疑似命令を、上記に示された実際の命令または複数の命令に置き換えます。

例

call square      # jumps to square; ra holds the return address