0

我试图了解glibc 中 tls.h的以下代码段在做什么以及为什么:

/* Macros to load from and store into segment registers.  */
# define TLS_GET_FS() \
  ({ int __seg; __asm ("movl %%fs, %0" : "=q" (__seg)); __seg; })

fs我想我理解将寄存器中存储的值移动到__seg. 但是,我有一些问题:

  1. 我的理解是fs只有16位。这个对吗?当值被移动到四字内存位置时会发生什么?这是否意味着高位被设置为 0?

  2. 更重要的是,我认为__seg在段开始时声明的变量的范围仅限于该段。那么怎么__seg用呢?我确信作者glibc有充分的理由这样做,但我无法通过查看源代码来弄清楚它是什么。

我尝试为这段代码生成程序集,我得到了以下信息?

 #APP
 # 13 "fs-test.cpp" 1
 movl %fs, %eax
 # 0 "" 2
 #NO_APP

所以在我的情况下,它看起来像是eax用于__seg. 但我不知道这是否总是会发生,或者是否只是我编译的小测试文件中发生的事情。如果它总是要使用eax,为什么不这样编写程序集呢?__seg如果编译器可能会选择其他寄存器,那么由于在宏末尾超出范围,程序员如何知道要访问哪个寄存器?最后,当我在 glibc 源代码中对它进行 grep 时,我没有在任何地方看到这个宏,所以这进一步增加了我对其用途的困惑。任何关于代码在做什么以及为什么的解释都值得赞赏。

4

1 回答 1

1

我的理解是fs只有16位。这个对吗?当值被移动到四字内存位置时会发生什么?这是否意味着高位被设置为 0?

是的。

在段开始处声明的变量 __seg 仅限于此段。那么 __seg 有什么用呢?

您必须阅读 GCC statement-expression extension。语句表达式的值是其中最后一个表达式的值。最后__seg;的 the 将是无用的,除非将其分配给其他东西,例如:

int foo = TLS_GET_FS();

最后,当我在 glibc 源代码中对它进行 grep 时,我没有看到在任何地方使用这个宏

TLS_{GET,SET}_FS实际上似乎没有使用。它们可能在某个版本中使用过,然后在引用它们的代码被删除时意外遗留下来。

于 2012-04-12T05:56:43.127 回答