1

アトミックに値をインクリメントする単純なインターフェイスを作成しようとしています。私は次のことをしようとします(Cで)

void foo()
{
    int counter = 0;
    assembly_xadd(&counter);
    printf("counter is %d\n");
}

カウンターは0です

xaddを適切に使用しているかどうかわからないアセンブリのコードは次のとおりです。

.global assembly_xadd

assembly_xadd:

    PUSHL %ebp
    MOVL %esp,%ebp
    PUSHL %edi  

    MOVL $0x1,%eax                                                    
    MOVL 0x8(%ebp),%edi                                               
    XADDL  %edi,%eax                             

    MOVL %edi,%eax    

    POPL %edi
    MOVL %ebp,%esp
    POPL %ebp
    RET
4

3 に答える 3

1

あなたが欲しいのはですXADDL %eax, (%edi)。Gas 構文では、宛先は常に 2 番目の値であり、 address のメモリを変更する必要があることに注意してください%edi。代わりに、アドレスに 1 つ追加%ediして %eax に保存しています。一般に、レジスタ操作は常にアトミックであるため、2 つのレジスタを使用することは役に立ちませんxadd(アトミック メモリ アクセスに関して)。

で行っていることはMOVL 0x8(%ebp),%edi、32 ビット整数のアドレスを に移動すること%ediです。また、私が想定している元の値を返したい場合MOVL %edi,%eaxは、そうすべきではありませんMOVL %edi,%eax%eaxには、 の以前の値が既に含まれています(%edi)

于 2013-02-12T02:32:34.647 に答える
0

xadd は、ここではインライン アセンブラで実装されています。

別の関数を呼び出すためのコード スペースのオーバーヘッドでさえ、xadd が占めるスペースよりも大きいため、プログラム全体がアセンブリでない限り、おそらくインラインが必要です。プログラム全体をアセンブリーで作成している場合 (マゾヒズムのため? 不合理なスペースの制約のため?)、おそらく xadd を直接使用したいと思うでしょう。もちろん、たとえば Perl や Python コードにリンクしたい場合のように、アセンブリ関数が妥当なアイデアである場合もいくつかあります (ただし、十分に注意しないと、それ自体が危険な結果をもたらす可能性があります)。 )、または関数ポインタをどこかに渡す必要がある場合。それでも、インライン アセンブラを実装してから、C で関数部分を作成します。

于 2013-02-13T19:32:58.267 に答える
0

Linux カーネルのアトミック変数の実装を見てみましょうinclude/arch/x86/include/asm/atomic.h(リンクは 3.8-rc7 のバージョンへのリンクです)。

于 2013-02-12T01:38:05.180 に答える