非専門的シンギュラリティー研究所

無限に動き続けるシステムを表す方法を AI なども使って考えていきます。

アセンブラ(15)

GCC の調査(2)

double の sin
double sin_double_cpp(double x)
{
    return sin(x);
}

から作られるアセンブリ言語のコードは以下のようになります。

_Z14sin_double_cppd:
	link.w %fp,#0
	move.l 12(%fp),-(%sp)
	move.l 8(%fp),-(%sp)
	jsr sin
	addq.l #8,%sp
	unlk %fp
	rts

x の上位32ビットを x0、下位32ビットを x1 とします。スタックが

0 4
スタックの入り口 x0 x1

の状態でこの関数が呼び出されると

0 4 8 12 16 20
スタックの入り口 x0 x1 fp pc x0 x1

の状態で sin が呼び出されます。sin は d0 レジスタと d1 レジスタに sin x を返します。

float の sin
float sin_float_cpp(float x)
{
    return sin(x);
}

から作られるアセンブリ言語のコードは以下のようになります。

_Z13sin_float_cppf:
	link.w %fp,#0
	move.l 8(%fp),-(%sp)
	jsr __extendsfdf2
	addq.l #4,%sp
	move.l %d1,-(%sp)
	move.l %d0,-(%sp)
	jsr sin
	addq.l #8,%sp
	move.l %d1,-(%sp)
	move.l %d0,-(%sp)
	jsr __truncdfsf2
	addq.l #8,%sp
	unlk %fp
	rts

スタックが

0
スタックの入り口 x

の状態でこの関数が呼び出されると

0 4 8 12
スタックの入り口 x fp pc x

の状態で __extendsfdf2 が呼び出されます。d0 レジスタと d1 レジスタに x を倍精度浮動小数点数に変換したものを返します(x0 と x1 とします)。

0 4 8 12 16
スタックの入り口 x0 x1 fp pc x

の状態で sin が呼び出されます。sin は d0 レジスタと d1 レジスタに sin x を返します。これを y0 と y1 とすると

0 4 8 12 16
スタックの入り口 y0 y1 fp pc x

の状態で __truncdfsf2 が呼び出されます。(sin x を)単精度浮動小数点数に変換されたものが d0 レジスタに返されます。

整数から倍精度浮動小数点数への変換
double int_to_double_cpp(int x)
{
    return double(x);
}

から作られるアセンブリ言語のコードは以下のようになります。

_Z17int_to_double_cppi:
	link.w %fp,#0
	move.l 8(%fp),-(%sp)
	jsr __floatsidf
	addq.l #4,%sp
	unlk %fp
	rts

スタックが

0
スタックの入り口 x

の状態でこの関数が呼び出されると

0 4 8 12
スタックの入り口 x fp pc x

の状態で __floatsidf が呼び出されます。__floatsidf は d0 と d1 レジスタに x を倍精度浮動小数点数に変換したものを返します。

整数から単精度浮動小数点数への変換
float int_to_float_cpp(int x)
{
    return float(x);
}

から作られるアセンブリ言語のコードは以下のようになります。

_Z16int_to_float_cppi:
	link.w %fp,#0
	move.l 8(%fp),-(%sp)
	jsr __floatsisf
	addq.l #4,%sp
	unlk %fp
	rts

スタックが

0
スタックの入り口 x

の状態でこの関数が呼び出されると

0 4 8 12
スタックの入り口 x fp pc x

の状態で __floatsisf が呼び出されます。__floatsisf は d0 レジスタに x を単精度浮動小数点数に変換したものを返します。