🦄

ARM64: ABI 規則

2023/05/01に公開

はじめに

本記事は、ARM64 (aarch64) の ABI 規則についてまとめています。

ARM64レジスタのおさらい

汎用 (整数) レジスタ

64ビットの31個の汎用レジスタがあり、x0〜x30 (正確にはxではなくrの方がいいのかもしれませんが、本記事ではxで統一します) と呼ばれます。各レジスタは64ビットの整数を格納できます。汎用レジスタは、整数演算やポインターの操作に使用されます。引数、戻り値、およびローカル変数の保存にも使用されます。

x30はリンクレジスタ (LR) の実体として利用されます。関数コールした時の戻り番地を記憶しておくレジスタです。

x31が存在しない(中途半端な)のは、常にゼロを示すゼロレジスタ (ZR) として割り当てられているためです。

他にも、いくつかの専用レジスタがあります。今回はVector等のいくつかのレジスタは記載を省略します。

  • プログラムカウンター(PC)
    • 次に実行される命令のアドレスを保持するレジスタです
  • スタックポインター(SP)
    • スタックのトップを指すレジスタです
  • ステータスレジスター(NZCV)
    • 直前の演算の結果に関するフラグを保持するレジスタです

レジスター割り当て規則


https://github.com/ARM-software/abi-aa/releases/download/2023Q1/aapcs64.pdf

整数値の引数と戻り値は、最大8つの汎用レジスター(x0〜x7)を使用して渡されます。これらのレジスターが不足している場合は、スタックを介して渡されます。

スタックは、ローカル変数、レジスターが不足する場合の引数の保存、および一部の呼び出し規則に使用されます。スタックのポインターは、x29レジスター(フレームポインター)によって指されます。スタック上のオブジェクトは、下向きに配置されます。

ライブラリ関数の呼び出し時には、一部のレジスターの内容が変更される可能性があります。これらのレジスターには、x0〜x7、x16、x17が含まれます。その他のレジスターの内容は変更されないとされます。

x18はplatform固有レジスタ?みたいでちょっと用途が良くわかりません。通常利用するレジスタとしての利用は避けた方がいい気がします。

Callee-savedレジスタ

x19〜x28はCallee-savedレジスタとして利用されます。

Callee-savedレジスタは、関数呼び出し規則において、呼び出された関数が呼び出し元の関数のレジスタ内容を維持する必要があるレジスタのことを指します。

通常、関数呼び出し時には、レジスターを使用して引数を渡し、関数が処理を行うために、呼び出された関数は一部のレジスタの内容を変更することができます。このような場合、呼び出された関数は、そのレジスタの変更前の内容を維持する必要があります。

Callee-savedレジスタには、呼び出された関数が維持する必要があるレジスタが含まれます。これには、一般的には、フレームポインタ(FP)、スタックポインタ(SP)、および一部の汎用レジスタが含まれます。これらのレジスタは、関数呼び出し規則によって、レジスタの保存と復元が定義されます。

呼び出し元の関数は、Callee-savedレジスタの変更を想定しておらず、呼び出された関数が呼び出し元の関数で使用する可能性のあるレジスターを使用している場合、その内容を保存し、関数終了時に復元する必要があります。

Callee-savedレジスタは、関数呼び出し規則の一部であり、プログラム実行時にレジスタ内容を維持することで、関数の正しい動作を保証します。

参考文献

Discussion