1 2;--- sample demonstrates how to 3;--- + define static TLS variables ( "__declspec(thread)" in MSC) in assembly. 4;--- + access static thread variables. 5;--- + use OPTION CODEVIEW to make debugger access the items correctly. 6 7;--- from an assembly point of view, there is not much gained with 8;--- static TLS. Unlike in C, access isn't transparent, it's quite similiar 9;--- to variables allocated vis TlsAlloc(). 10 11;--- assemble: jwasm -coff win32tls.asm 12;--- link: link win32tls.obj /subsystem:console kernel32.lib msvcrt.lib 13 14 .386 15 .model FLAT, stdcall 16 option casemap:none 17 18;--- TLS directory definition from PE/COFF specification (32-bit) 19IMAGE_TLS_DIRECTORY32 struct 20StartAddressOfRawData DWORD ? 21EndAddressOfRawData DWORD ? 22AddressOfIndex DWORD ? 23AddressOfCallBacks DWORD ? 24SizeOfZeroFill DWORD ? 25Characteristics DWORD ? 26IMAGE_TLS_DIRECTORY32 ends 27 28HANDLE typedef ptr 29 30;--- Win32 functions used in this program 31CloseHandle proto :ptr 32CreateMutexA proto :ptr, :dword, :ptr 33CreateThread proto :ptr, :dword, :ptr, :ptr, :dword, :ptr 34ExitProcess proto :dword 35ReleaseMutex proto :ptr 36Sleep proto :dword 37WaitForMultipleObjects proto :dword, :ptr, :dword, :dword 38WaitForSingleObject proto :ptr, :dword 39 40;--- CRT functions used in this program 41memset proto c :ptr, :dword, :dword 42printf proto c :vararg 43 44;--- macro to define a text constant 45CStr macro Text:VARARG 46local szText 47 .const 48szText db Text,0 49 .code 50 exitm <offset szText> 51endm 52 53;--- macro to access thread variables 54TLSACC macro var 55 mov eax,fs:[2Ch] ;this is Win32-specific 56 mov edx,tls_index 57 mov eax,[eax+edx*4] 58 exitm <[eax + sectionrel var]> 59endm 60 61ifdef __JWASM__ 62;--- if option -Zi is set and debugger is to show correct value 63;--- of static thread variables, option codeview:1 must be set. 64 option codeview:1 65endif 66 67_TLS segment dword alias(".tls") public 'TLS' 68tls_start label byte ;start of initialized thread variables 69var1 DD -1 70tls_end label byte ;end of initialized thread variables 71_TLS ends 72 73 .const 74 75;--- the important thing is public "_tls_used". 76;--- if the linker finds this global label, it will set the TLS data 77;--- directory entry in the PE binary. 78 79 public _tls_used ;tell the linker that a TLS directory is wanted 80_tls_used IMAGE_TLS_DIRECTORY32 <tls_start, tls_end, tls_index, tls_cb_array> 81 82;--- zero-terminated array of TLS callbacks 83tls_cb_array label ptr 84 dd tls_callback 85 dd 0 86 87 .data 88 89tls_index dd -1 ;this variable will receive the index allocated by the loader 90 91 .data? 92 93g_hMutex HANDLE ? 94 95 .code 96 97 assume fs:nothing 98 99;--- thread callback - does nothing 100tls_callback proc hMod:HANDLE, Reason:dword, Reserved:ptr 101; invoke printf, CStr("tls_callback: reason=%d",10), Reason 102 ret 103tls_callback endp 104 105;--- thread procedure 106 107threadproc proc uses ebx lParam:dword 108 109;--- use mutex to serialize access to printf (not needed for msvcrt) 110 invoke WaitForSingleObject, g_hMutex, 5000 111 lea eax, TLSACC(var1) 112 mov ecx, TLSACC(var1) 113 invoke printf, CStr("thread(%u): init var1=%d &var1=%Xh",10), lParam, ecx, eax 114 invoke ReleaseMutex, g_hMutex 115 116;--- release time slice so the other threads will get a chance to run 117 invoke Sleep, 0 118;--- modify the thread variable 119 mov ecx, lParam 120 mov TLSACC(var1), ecx 121 122;--- use mutex to serialize access to printf (not needed for msvcrt) 123 invoke WaitForSingleObject, g_hMutex, 5000 124 mov ecx, TLSACC(var1) 125 invoke printf, CStr("thread(%u): mod. var1=%d",10), lParam, ecx 126 invoke ReleaseMutex, g_hMutex 127 128 ret 129 align 4 130 131threadproc endp 132 133 134start: 135 136mainCRTStartup proc 137 138local hConInp:HANDLE 139local hThread[10]:HANDLE 140 141 invoke printf, CStr("main: tls_index=%d",10), tls_index 142 143;--- create a mutex to synchronize access to printf() 144 invoke CreateMutexA, 0, 0, 0 145 mov g_hMutex, eax 146 147;--- reset thread handles 148 invoke memset, addr hThread, 0, sizeof hThread 149 150;--- start threads 151 mov esi,0 152 lea ebx, hThread 153 .while esi < lengthof hThread 154 invoke CreateThread, 0, 4000h, offset threadproc, esi, 0, 0 155 mov [ebx], eax 156 inc esi 157 ;invoke printf, CStr("main: %u. CreateThread()=%X",10), esi, eax 158 add ebx, sizeof HANDLE 159 .endw 160 161;--- wait until all threads are done 162 invoke WaitForMultipleObjects, lengthof hThread, addr hThread, 1, 5000 163 164 invoke CloseHandle, g_hMutex 165 166 mov ecx, TLSACC(var1) 167 lea eax, TLSACC(var1) 168 invoke printf, CStr("main: var1=%d &var1=%X",10), ecx, eax 169 170 invoke ExitProcess, 0 171 ret 172 align 4 173mainCRTStartup endp 174 175 END start 176