2

インライン アセンブリを C に書き込もうとしています。入力として 2 つの配列があります。必要なのは、array1 の 1 つの要素を array2 にコピーすることです。現時点では次のようになります。

asm (
 "movl %0,%%eax;"
 "movl %1,%%ebx;"
 "movl (%%eax),%%ecx;"
 "movl %%ecx,(%ebx);"

 "xor %%ecx,%%ecx;"
 "movl 4(%%eax),%%ecx;"
//do something on %ecx
 "movl %%ecx,4(%ebx);"  //write second
 :
 :"a"(array1),"b"(array2)
);

セグメンテーション違反が発生するのはなぜですか?

4

3 に答える 3

8

インライン アセンブラ コードが壊れています。clobber リストに追加せずに EAX と EBX を直接使用することはできません。そうしないと、コンパイラはどのレジスタが変更されたかを認識できません。

変更したレジスタの 1 つに、後でセグメンテーション違反の原因となった非常に重要な何かが含まれている可能性が非常に高いです。


このコードは、1 つの要素を array1 から array2 にコピーします。

asm (
 "movl (%0), %%eax \n\t" /* read first dword from array1 into eax */
 "movl %%eax, (%1) \n\t" /* write dword into array2
 : /* outputs */
 : /* inputs */ "r"(array1),"r"(array2)
 : /* clobber */ "eax", "memory"
);

適切なレジスタ制約を備えたより良いバージョンでは、次のようにハードコードされた EAX が削除されます。

int dummy;
asm (
 "movl (%1), %0 \n\t"
 "movl %0, (%2) \n\t"
 : /* outputs, temps.. */ "=r" (dummy) 
 : /* inputs */           "r"(array1),"r"(array2)
 : /* clobber */          "memory"
);

ところで - 一般的に、あなたはまだアセンブラに慣れていないように感じます。インライン アセンブラを記述することは、すべてのコンパイラ マジックにより、正しく行うのが少し難しくなります。アセンブラーでいくつかの単純な関数を書き始め、それらを最初に別の .S ファイルに入れることをお勧めします..その方がはるかに簡単です..

于 2009-11-01T14:05:34.873 に答える
3

あなたの最良の選択肢はCコードです:

target_array[target_idx] = source_array[source_idx];

これにより、インデックスが制御されている限り、セグメンテーション違反が回避されます。

于 2009-11-01T00:38:06.683 に答える
0

memcpy はどうですか?

于 2010-04-08T12:26:15.230 に答える