Arm64呼び出し規約
レジスタの扱い
Section titled “レジスタの扱い”最初の戻り値は R0 レジスタで返す。複数ある場合は調べていない。
スタックポインタ
Section titled “スタックポインタ”スタックポインタ(SP)のアドレスは RSP として参照できる。実際は R31 レジスタなのだけど、これは命令によって ZR (ゼロレジスタ)と SP (スタックポインタ)のどちらかの意味に解釈される。
Armv8では R13 レジスタで固定。
リターンアドレス
Section titled “リターンアドレス”関数からの戻り先アドレスは R30 レジスタに入っている。リンクレジスタ(LR)と呼ばれる。関数呼び出しがネストしている場合は、スタックに退避しろとドキュメントに書いてある。
Armv8では R14 レジスタ。
実際のコードでは次のようにレイアウトしている。MOV 命令の .W と .P フラグはArm用Goアセンブリのサフィックスに書いた。
// [元のFP(R29)][元のLR(R30)]// ^R29 ^RSP
MOVD.W R30, -64(RSP) // RSP -= 64; *RSP = R30MOVD R29, -8(RSP) // *(RSP-8) = R29SUB $8, RSP, R29 // R29 = RSP - 8...MOVD -8(RSP), R29MOVD.P 64(RSP), R30RETフレームポインタ
Section titled “フレームポインタ”フレームポインタは R29 レジスタに入っている。
プログラムカウンタ
Section titled “プログラムカウンタ”プログラムカウンタ(PC)は R15 レジスタで参照する。
https://blog.felixge.de/go-arm64-function-call-assembly/
関数呼び出し
Section titled “関数呼び出し”Goアセンブリでは以下のように記述する。
TEXT ·mainf(SB),NOSPLIT,$0 CALL ·subf(SB)
TEXT ·subf(SB),NOSPLIT,$0 RETこのとき CALL は BLR 命令を生成する。BLR はリンクレジスタに戻り先アドレスをセットしてからジャンプするので、RET 命令で正しい呼び出し元へ戻ることができる。