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). 请记住,使用气体语法,目标始终是第二个值,并且您要更改地址处的内存%edi。相反,您将地址加一%edi并将其存储在 %eax 中。一般来说,xadd有两个寄存器是没有用的(原子内存访问明智的),因为寄存器操作总是原子的。

您正在做的MOVL 0x8(%ebp),%edi是将 32 位整数的地址移动到%edi. 另外,如果你想返回原始值,这是我假设MOVL %edi,%eax的,你不应该这样做MOVL %edi,%eax%eax已经包含 的先前值(%edi)

于 2013-02-12T02:32:34.647 回答
0

看看Linux内核中的原子变量实现,在include/arch/x86/include/asm/atomic.h(链接是3.8-rc7中的版本)

于 2013-02-12T01:38:05.180 回答
0

xadd在这里用内联汇编器实现。

除非您的整个程序是汇编程序,否则您可能需要内联,因为即使调用单独函数的代码空间开销也大于 xadd 占用的空间。如果您在汇编中编写整个程序(因为受虐狂?不合理的空间限制?)您可能只想直接使用 xadd 。当然,在某些情况下,汇编函数是一个合理的想法,例如,如果您想将其链接到 Perl 或 Python 代码中(但如果您不是非常非常小心,这本身可能会产生危险的后果),或者如果您需要在某处传递函数指针。但即便如此,我还是会实现内联汇编器,然后在 C 中创建函数部分。

于 2013-02-13T19:32:58.267 回答