9.1.3 引数の設定、参照に関する規則

引数に対する一般的な規則と、引数の割り付け方について述べます。

引数が実際どのように割り付けられるかは、「8.2.5 引数割り付けの具体例」を参照ください。

(1)

引数の渡し方

引数の値を、必ずレジスタまたはスタック上の引数の割り付け領域にコピーしたあとで関数を呼び出します。呼び出した側の関数では、リターン後に引数の割り付け領域を参照することはありませんので、呼び出された側の関数で引数の値を変更しても呼び出した側の処理は直接には影響を受けません。

(2)

型変換の規則

(a)

関数原型によって型が宣言されている引数は、宣言された型に変換します。

(b)

関数原型によって型が宣言されていない引数の型変換は、以下の規則に従って変換します。

-

2バイト以下の整数型は、4バイト整数型に変換されます。

-

float型の引数は、double型に変換します。

-

上記以外の引数は、変換しません。

(3)

引数の割り付け領域

引数は、レジスタに割り付ける場合とスタック上の引数領域に割り付ける場合があります。引数の割り付け領域を図 9.2に示します。

通常、ソースプログラムにおける引数の宣言順に、番号の小さいレジスタから順に割り付けを行い、レジスタが全て割り付いたらスタックに割り付けます。但し、可変個の引数を持つ関数など、レジスタが余っていてもスタックに割り付ける場合もあります。また、C++プログラムの非静的関数メンバのthisポインタは、常にR1に割り付けられます。

引数割り付け領域の一般規則を表 9.2に示します。

図 9.2

スタックフレームの割り付け、解放に関する規則

表 9.2

引数割り付け領域の一般規則

レジスタで渡される引数

スタック渡しになる引数

対象の型

引数格納用レジスタ

割り付け方

signed char, (unsigned)char, bool, _Bool, (signed)short, unsigned short, (signed)int, unsigned int, (signed)long, unsigned long, float、double*1, long double*1, ポインタ, データメンバへのポインタ, リファレンス

R1〜R4のうち1つ

signed char, (signed)shortは符号拡張、(unsigned)char, unsigned shortはゼロ拡張を行った結果を割り付ける

その他の型はそのままレジスタに割り付ける

(1) 引数の型がレジスタ渡しの対象の型以外のもの

(2) 関数原型により可変個の引数を持つ関数として宣言しているもの*3

(3) R1〜R4のうち、まだ他の引数に割り当てられていないものの本数が、割り当てに必要な本数より少ない場合

(signed)long long, unsigned long long, double*2, long double*2

R1〜R4のうち2つ

下位4バイトを番号の少ない方に、上位4バイトを番号の大きい方に割り付ける

16バイト以内でサイズが4の倍数の構造体型、共用体型、クラス型

R1〜R4のうち、サイズを4で割った数

メモリイメージの先頭から4バイトずつ、レジスタ番号が増える方向に割り付ける

注 1.

dbl_size=8を指定しなかった場合です。

注 2.

dbl_size=8を指定した場合です。

注 3.

関数原型により可変個の引数をもつ関数として宣言している場合、宣言の中で対応する型のない引数およびその直前の引数はスタック渡しになります。型のない引数は、2バイト以下の整数はlong型に、float型はdouble型にそれぞれ変換して、全て境界調整数が4の引数として取り扱います。

 int f2(int,int,int,int,...);
 :
 f2(a,b,c,x,y,z); → x、y、z はスタック渡しになります。

(4)

スタック渡しとなる引数の割り付け方

表 9.2で、スタック渡しとなる引数の、配置アドレス、およびスタックへの配置の仕方は以下となります。

-

各引数は、その境界調整数に応じたアドレスに配置します。

-

引数並びの左から右の順に、スタックが深くなる方向に配置されるように、スタックの引数用領域に格納します。すなわち、引数Aとその右隣の引数Bがともにスタック渡しとなる場合、引数Bのアドレスは、引数Aの配置アドレスに引数Aの占有サイズを加えたアドレスを、引数Bの境界調整数に整合させたアドレス、となります。