6.2. THREAD LOCAL STORAGE
mov DWORD PTR _rand_state[ecx], eax
and eax, 32767 ; 00007fffH
ret 0
_my_rand ENDP
_TEXT ENDS
rand_stateis now in theTLSsegment, and each thread has its own version of this variable.
Hereishowit’saccessed: loadtheaddressoftheTIBfromFS:2Ch,thenaddanadditionalindex(ifneeded),
then calculate the address of theTLSsegment.
Then it’s possible to access therand_statevariable through the ECX register, which points to an unique
area in each thread.
TheFS:selectorisfamiliartoeveryreverseengineer, itisspeciallyusedtoalwayspointtoTIB, soitwould
be fast to load the thread-specific data.
TheGS:selector is used in Win64 and the address of theTLSis 0x58:
Listing 6.16: Optimizing MSVC 2013 x64
_TLS SEGMENT
rand_state DD 01H DUP (?)
_TLS ENDS
_DATA SEGMENT
$SG85451 DB '%d', 0aH, 00H
_DATA ENDS
_TEXT SEGMENT
init$ = 8
my_srand PROC
mov edx, DWORD PTR _tls_index
mov rax, QWORD PTR gs:88 ; 58h
mov r8d, OFFSET FLAT:rand_state
mov rax, QWORD PTR [rax+rdx*8]
mov DWORD PTR [r8+rax], ecx
ret 0
my_srand ENDP
my_rand PROC
mov rax, QWORD PTR gs:88 ; 58h
mov ecx, DWORD PTR _tls_index
mov edx, OFFSET FLAT:rand_state
mov rcx, QWORD PTR [rax+rcx*8]
imul eax, DWORD PTR [rcx+rdx], 1664525 ; 0019660dH
add eax, 1013904223 ; 3c6ef35fH
mov DWORD PTR [rcx+rdx], eax
and eax, 32767 ; 00007fffH
ret 0
my_rand ENDP
_TEXT ENDS
InitializedTLSdata
Let’s say, we want to set some fixed value torand_state, so in case the programmer forgets to, the
rand_statevariable would be initialized to some constant anyway (line 9):
1 #include <stdint.h>
2 #include <windows.h>
3 #include <winnt.h>
4
5 // from the Numerical Recipes book:
6 #define RNG_a 1664525
7 #define RNG_c 1013904223
8