2

こんにちは、アセンブリを学び、x86_64 で浮動小数点数を扱う方法を学ぼうとしています。私が理解していることから、引数は xmm0、xmm1、xmm2 などで渡され、結果は xmm0 で返されます。だから私は一緒に倍増する単純なアセンブリ関数を作ろうとしています。ここに関数があります

.text

.global floatadd
.type floatadd,@function

floatadd:
    addsd %xmm1,%xmm0
    ret

そして、これも私が使用しているCコードです。

#include<stdio.h>

int main(){
    double a = 1.5;
    double b = 1.2;
    double c = floatadd(a,b);
    printf("result = %f\n",c);
}

私はgdbで何が起こっているかを追跡しようとしています。関数にブレークポイントを設定すると、xmm0 が 1.5、xmm1 が 1.2 であり、それらを合計すると 2.7 であることがわかります。gdb print $xmm0 で v2_double = {2.7000000000000002, 0} が得られます ただし、関数がメインから戻って呼び出すと

cvtsi2sd %eax,%xmm0 

Print $xmm0 は v2_double = {2, 0} になります。gcc がそれを呼び出す理由、または 64 ビット レジスタの代わりに 32 ビット レジスタを使用する理由がわかりません。修飾子 %lf と %f を使用してみましたが、どちらも同じことを行います。

何が起こっている?

4

1 に答える 1

3

floatadd問題は、呼び出す前に宣言に失敗したことです。そのため、コンパイラはintinを返すと想定し%eax、その int を double に変換します。宣言を追加します。

double floatadd(double, double);

メイン前。

警告を有効にするためにコンパイラが使用-Wallする、または同等のものを使用すると、おそらくこの問題について通知されます...

于 2013-10-23T00:55:15.250 に答える