本文以InterlockedIncrement為例,來說明Windows Interlocked系列函數的實作原理。
一、InterlockedIncrement反彙編代碼
如下C++代碼:
#include <windows.h>
int main()
{
LONG l = 1;
LONG j = InterlockedIncrement(&l);
return 0;
}
對應的反彙編代碼如下:
LONG l = 1;
002D08A8 mov dword ptr [l],1
LONG j = InterlockedIncrement(&l);
002D08AF mov eax,1
002D08B4 lock xadd dword ptr [l],eax
002D08B9 inc eax
002D08BA mov dword ptr [j],eax
這裡寫圖檔描述
從上面代碼可以看出,InterlockedIncrement主要是通過lock和xadd這2個彙編指令來實作的。
二、lock與xadd指令
2.1 lock
lock字首用于鎖定指定的記憶體位址,當這個特定記憶體位址被鎖定後,它就可以阻止其他的系統總線讀取或修改這個記憶體位址,進而實作原子操作。
可以結合lock使用的彙編指令如下:
BT, BTS, BTR, BTC
XCHG, XADD
ADD, OR, ADC, SBB
AND, SUB, XOR
NOT, NEG, INC, DEC
2.2 xadd
xadd指令完成交換并相加的功能。如XADD r/m32, r32,即交換r32 與r/m32;并将相加的和存儲到 r/m32中。
關于xadd指令可以參考:
http://scc.qibebt.cas.cn/docs/optimization/VTune(TM)%20User’s%20Guide/mergedProjects/analyzer_ec/mergedProjects/reference_olh/instruct32_hh/vc325.htm
三、InterlockedIncrement過程分析
InterlockedIncrement的處理過程如下:
【1】将eax指派為1,即mov eax, 1
【2】使用一個xadd指令完成了下面的操作,通過僞代碼表示如下:
// [l]和eax交換
temp = [l]
[l] = eax
eax = temp
// 将相加的和儲存到[l]參數中
[l] = eax + [l]
從上面僞代碼可以看到,一個xadd指令完成了多步操作,且是針對記憶體位址的操作,是以這行指令使用了lock字首修飾。
【3】因為InterlockedIncrement函數傳回值也會傳回自增的結果,且因win32彙編的函數傳回值儲存在eax中,是以此時eax還要自增1(即inc eax)。