Digging into the implementation of Win32 API functions that work with TIB (Thread Information Block), such as:
TlsAlloc
, TlsFree
, TlsSetValue
, TlsGetValue
GetLastError
, SetLastError
GetMessage
, PeekMessage
and etc.one finds out that all of them access the TIB, sometimes called TEB (Thread Environment Block), by reading the contents of the fs:[0x18]
selector.
OTOH this is unnecessary, since the fs
register directly points to it. According to this article and what I see in practice, the fs
register holds the address to the beginning of the TIB structure, whereas at offset 0x18 it has a pointer to itself.
What could be the reason to access the TIB indirectly nevertheless?
Any instruction using FS
requires an override, which adds a byte to the instruction (and generally requires assembly language to use it at all). The pointer at FS:18
is (at least if memory serves correctly) based off of DS
instead, so it can be used without an override, saving a byte when it's used and (most importantly for many people) can be used directly from a higher level language such as C or C++ instead of requiring assembly language.