2

以下のインライン アセンブリ コードに問題はありますか? 関数 spinlock_lock を実行すると、「不正な命令 (コア ダンプ)」が発生しました。

void spinlock_lock(struct spinlock * lock) {

    int a;
    __asm__ __volatile__("movl %0, %%eax;"
                         "test %%eax, %%eax;"
                         "jnz spinlock_lock;"
                         :"=r"(a)
                         :"r"(lock->cmos_lock)
                         :"eax");

    __asm__ __volatile__ ("lock; cmpxchg %%edx, %0\n"
                          :"=r"(a)
                          :"r"(lock->cmos_lock)
                          :"edx", "memory");
4

1 に答える 1

2

問題はあなたのブランチです。通常(x86)呼び出された関数は、他のコードを実行する前に、フレームポインタをスタックに保存します

ブランチは関数全体jnz spinlock_lockのエントリポイントにブランチバックするため、インラインアセンブラに戻る前にフレームポインタを再度保存します。フレームポインタを十分な回数保存すると、スタックが不足します。言うまでもなく、インラインアセンブラの外部に分岐してインラインアセンブラを離れると、レジスタに自分が思っていることが含まれなくなる可能性があります。

おそらく、インラインアセンブラ内にラベルを配置し、代わりにそれに分岐する必要があります。

また、命令はレジスタに対して動作できますが、レジスタオペランドを使用しているため、cmpxchg %edx, %0組み合わせることはできません。lock動作させるには、一致するパラメータの制約をからにlock cmpxchg変更する必要があります。rm

ここlock cmpxchgでメモリオペランドの必要性の説明を参照するか、ここでアセンブラなしのスピンロックの代替gcc実装を確認することをお勧めします。

于 2012-09-16T21:47:48.790 に答える