天天看點

Windows Interlocked系列函數

本文以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)。