通过一个例子证明了Windows xp x64版本是使用gs来获取线程块的。
由于微软的x64版本的编译器已经不支持嵌入汇编语句__ASM,所以写了两个小程序,一个c语言程序1.c,另一个汇编程序2.asm

1.c 源码如下:
#include <windows.h>

extern int GetPid();

int PrintGs(void *pid)
{
  printf("gs value = %ld\n",(long)pid);
  return 0;
}

int main(int argc, char* argv[])
{
  DWORD Pid;
  DWORD PidFromGs;

  Pid = GetCurrentProcessId();
  printf("pid=%d\n",Pid);
  PidFromGs = GetPid();
  printf("Pid from gs:[64]=%ld\n",(long)PidFromGs);
  return 0;
}
c语言编译命令:
cl /c 1.c

2.asm汇编程序源码如下:
include listing.inc

INCLUDELIB LIBCMT
INCLUDELIB OLDNAMES

PUBLIC  GetPid
EXTRN  PrintGs:PROC

_TEXT  SEGMENT
GetPid  PROC
  mov  rcx,gs
  sub  rsp,8
  call   PrintGs
  add  rsp,8
  mov  eax,gs:[64]
  ret  0
GetPid  ENDP
_TEXT  ENDS
END

汇编编译命令:
ml64 /c 2.asm

链接命令:
link 1.obj 2.obj

执行结果,和预期的一样,通过API取到的进程号,和从TEB数据结构上的取到的进程号,是一样的。
pid=2884
gs value = 43
Pid from gs:[64]=2884