2013-02-12 44 views
1

我想写一个简单的接口来自动增加一些值。我尝试做如下(C)如何使用XADD增加内存中的值?

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 
+3

嗯,你代码中的'xadd'没有引用任何内存吗? – 2013-02-12 01:13:20

+0

我传递了第一个参数,它是存储整数的地址。这是行 >> MOVL 0x8(%ebp),%edi – 2013-02-12 01:18:06

+0

那么,什么?你的'xadd'仍然会把'edi'加到'eax'上,只是注册,并且和(在'eax'中)不会写入内存。然后,即使是这样,如果你想以原子方式修改它,'xadd'的目的仍然会被击败,因为'xadd'需要直接添加到内存操作数。最后,在'xadd'上需要一个'lock'前缀。 – 2013-02-12 01:26:08

回答

1

你想要的是XADDL %eax, (%edi)。请记住,使用gas语法时,目标始终是第二个值,并且您要更改内存地址%edi。您需要在地址%edi中添加一个并将其存储在%eax中。在genearl中,有两个寄存器的xadd是无用的(原子存储器访问明智),因为寄存器操作总是原子的。

你正在做什么与MOVL 0x8(%ebp),%edi正在将32位整数的地址移动到%edi。另外,如果你想返回原来的值,这是我所假设的MOVL %edi,%eax,对于,你不应该这样做MOVL %edi,%eax%eax已包含以前的值(%edi)

0

xadd在嵌入式汇编程序中实现here

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