我想了解tls.h in glibc的以下代码段正在做什么以及为什么:
/* Macros to load from and store into segment registers. */
# define TLS_GET_FS() \
({ int __seg; __asm ("movl %%fs, %0" : "=q" (__seg)); __seg; })
我想我理解将fs
寄存器中存储的值移动到__seg
的基本操作。但是,我有一些问题:
我的理解是fs
只有16位。它是否正确?当值移动到四字记忆位置时会发生什么?这是否意味着高位设置为0?
更重要的是,我认为在段的开头声明的变量__seg
的范围仅限于此段。那么__seg
有用吗?我确信glibc
的作者有充分的理由这样做,但我无法弄清楚它是如何看待源代码的。
我尝试为此代码生成程序集,我得到了以下内容?
#APP
# 13 "fs-test.cpp" 1
movl %fs, %eax
# 0 "" 2
#NO_APP
所以在我的情况下,eax
似乎使用了__seg
。但我不知道是否总会发生什么,或者它是否只是我编译的小测试文件中发生的事情。如果总是使用eax
为什么组装不会这样写?如果编译器可能选择其他寄存器,那么程序员将如何知道访问哪一个,因为__seg
超出了宏的末尾范围?最后,当我在glibc源代码中使用它时,我没有看到这个宏在任何地方使用过,所以这进一步增加了我对其目的是什么的困惑。感谢您对代码正在做什么以及为什么做出任何解释。
答案 0 :(得分:1)
我的理解是fs只有16位。它是否正确?当值移动到四字记忆位置时会发生什么?这是否意味着高位设置为0?
是
在段的开头声明的变量__seg仅限于此段。那么__seg如何有用?
你必须阅读GCC statement-expression extension。语句表达式的值是其中最后一个表达式的值。最后的__seg;
将毫无用处,除非有人将其分配给其他内容,如下所示:
int foo = TLS_GET_FS();
最后,当我在glibc源代码中使用它时,我没有看到这个宏在任何地方使用
TLS_{GET,SET}_FS
实际上似乎没有被使用。它们可能在某个版本中使用,然后在删除引用它们的代码时意外遗留。