0

C と ASM コードの間で配列へのポインターを渡したい。4 つの double 値の配列があり、それらを asm に渡し、xmm にロードし、乗算して 4 つの値へのポインターを C に戻す必要があります。データを xmm0 にロード中にエラーが発生しました。

このポインタを ASM に渡して C に戻す方法は? 4 つの数値すべてを xmm0 にロードする方法は?

コードは次のとおりです。

.text

.globl calkasse
.type calkasse, @function

calkasse:   
pushq %rbp
movq %rsp, %rbp

movq 8(%rbp), %rax
movaps 16(%rax), %xmm0
mulps %xmm0,%xmm0

movq  %rbp,   %rsp
popq   %rbp
ret

および C コード:

double (*calkasse(double (*)[4]))[4];

int main(void) {

double suma=0.0;
double poczatek=1.0;
double koniec=5.0;
double step=0.001;
double i=poczatek;
double array[4];
double (*wynik)[4];

    array[0] = i;
    array[1] = i+step;
    array[2] = i+(2*step);
    array[3] = i+(3*step);
    wynik = calkasse(&array);
    suma+=*wynik[0]+*wynik[1]+*wynik[2]+*wynik[3];
return 1;
}
4

2 に答える 2

0

プロジェクトをアセンブリ ファイルとしてコンパイルしてから、これらの変更を行う必要があります。インライン アセンブリを使用すると、C コードとインライン アセンブリの間でシステムに大量の変更が加えられます (つまり、私のテストで見たものからすると 1 トンです)。基本的に、組み立て部分に入る前に、システムの状態をそのまま破壊します。インラインアセンブリの意味を理解するために、CコードがCライブラリを使用する必要があるため、これが明らかな理由です。したがって、この間、永続性が失われ、値がプッシュおよびポップされます。

アセンブリに入る前にレジスタを破棄しないようにするには、作成後にオブジェクト ファイルにアセンブリを追加してみてください。GDB を使用して、追加を開始する前にコードが何を行っているかを把握できます。探しているアドレスを手動で取得できるはずです。その後、それを変数に配置するだけです。レジスタに挿入すると、コードを追加した後にアセンブリをトレースして、正しいレジスタに正しいタイミングで配置したことを確認する必要があるため、変数に配置します。変数に配置する場合は、mov 命令 (または leal IIRC) を使用してポインター値を変数に取得し、C コードでこの変数を null に設定するだけです。次に、アセンブリを実際に手動で記述する前に、C コードを記述できます (基本的に、変数はモックです)。お役に立てれば、

于 2013-05-30T20:13:22.260 に答える
0

コンパイラが予測どおりに動作するようにする必要があります。AC 関数はさまざまな方法でコンパイルできます。また、OS とプラットフォームに依存します。たとえば、レジ​​スタ/レジスタの最適化/OS禁止レジスタを介した関数パラメータの受け渡しを許可すると、コンパイルが変更されます。最適化をオフにして関数を書いてみて、コンパイラのアセンブリ出力を見てください。そうすれば、少なくとも 1 つの OS とプラットフォームで一貫性のある、より制御されたコンパイルのケースが得られます。その後、インライン アセンブリをその関数に追加できます。アセンブリ出力に常に注意してください...これには中程度のリバースエンジニアリングが必要です。

于 2013-05-31T18:16:56.660 に答える