いくつかの SSE2 操作を実行する 64 ビット x86 アセンブリ (gcc および GAS の AT&T 構文) で記述された関数があります。逆アセンブルで gdb を使用し、レジスタ値を調べて結果を確認したので、正しい結果が生成されていることがわかりました。retq 命令の後、セグメンテーション違反が発生します。私はアセンブリに不慣れなので(そしてクラスを受講したことはありません)、関数/メインプログラムインターフェイスを正しく処理していないと推測しています。関数は 2 つのポインターと int を受け取り、float を返すことが期待されます。これは、アセンブリ関数で入力/出力を処理する方法です。
float foo(float *x,float *y,unsigned int s)
{
__asm__ __volatile__(
"movl -0x14(%%rbp),%%ecx \n\t" //ecx = s
"movq -0x8(%%rbp),%%rax \n\t" //rax -> x
"movq -0x10(%%rbp),%%rdx \n\t" //rdx -> y
"subq $4,%%rsp \n\t" //function result
#sse2 operations that end up with the answer in xmm4...
"movss %%xmm4,(%%rsp) \n\t" //store result
"flds (%%rsp) \n\t" //load function result
"addq $4,%%rsp \n\t" //adjust stack
"ret \n\t"
:
:"g"(s)
:"%ecx","%rax","%rdx"
);
}
そして、これがセグメンテーション違反の原因と思われる行です (これは、逆アセンブリの ret の直後の命令です):
0x00007fffffffe0d0 in ?? ()
=> 0x00007fffffffe0d0: 00 00 add %al,(%rax)
関数を実行した後、rax の下位ビットの値を rax に戻す理由はわかりませんが、クラッシュしているようです。アセンブリ関数で rax を使用することは許可されていませんが、それは汎用であり、破壊されたと宣言していますか?
この部分を見る必要があるかどうかはわかりませんが、これは gcc が関数を処理する方法です。関数を呼び出す行の逆アセンブリを含めました。
#asm dealing with function inputs
callq 0x400520 <foo>
movss %xmm0,-0x48(%rbp)
mov -0x48(%rbp),%eax
mov %eax,-0x34(%rbp)
2 番目の質問は、なぜ xmm0 の値を勝手に 2 つの場所に移動するのですか? 関数の結果を xmm0 にするべきでしたか、それとも xmm0 の使用を避けるべきなのでしょうか? 私は非常に混乱しており、助けていただければ幸いです。私の初心者の投稿を読むのに時間を割いてくれた人に、前もって感謝します:)