2013-02-12 39 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中創建函數部分。