【问题标题】:What does the declaration“extern struct cpu *cpu asm("%gs:0");” mean?声明“extern struct cpu *cpu asm("%gs:0");”是什么意思意思是?
【发布时间】:2017-01-27 11:33:08
【问题描述】:

当我阅读 xv6 源代码时,我对下面声明的语法感到困惑。谁能给我解释一下?

extern struct cpu *cpu asm("%gs:0");

【问题讨论】:

  • asm 在变量声明之后通常允许您为链接目的指定变量的名称,但在这种情况下,您根本没有指定名称,而是某种寄存器引用。
  • 下次 - 请先谷歌!

标签: gcc x86 inline-assembly xv6


【解决方案1】:

我假设您了解extern struct cpu *cpu 的含义。您的问题是:asm("%gs:0") 部分是什么意思?

这段代码使用了一个名为asm labels的gcc扩展来表示变量cpu是由汇编字符串%gs:0定义的。

这不是这个扩展的预期用途,它被认为是hack

关于 gs(和 fs)here 的讨论非常好,但总之 gs 指向当前线程的本地存储。 gs 的数据格式取决于您的操作系统(Windows 与 Linux 非常不同)。这个特殊的代码是说在 gs 的偏移量 0 处,有一个指向 struct cpu 的指针。

【讨论】:

  • 请参阅discussion on a recent duplicate 以了解黑客无法编译+汇编的情况(32 位 PIC 代码,或任何时候编译器尝试将mov 地址作为立即数写入寄存器) ,或者更糟糕的是它编译但使用了错误的地址(使用 RIP 相对寻址的 64 位代码)
【解决方案2】:

这是asm label 的一个特例。如果您引用 cpu 变量,它会指示编译器发出 %gs:0 而不是通常的符号名称。大概%gs 之前已经设置为per-cpu 存储区域,struct cpu 指针位于偏移量零处。目的是让每个cpu访问自己的数据。

【讨论】:

  • 所以这只是调用 gs 'cpu' 引用的段中偏移 0 字节的内存?
  • 我会说这在某种程度上仍然是对该功能的滥用。我有一种感觉,它可以使编译器在某些情况下生成无效代码。
  • 获取地址失败,但您可能不会这样做,因为您知道它不在同一个从零开始的段中。现在,让我们看看是否可以让编译器将地址作为优化的一部分。
  • 不能与位置无关代码一起使用。在 32 位代码中。它将尝试生成类似于%gs:0@GOT(%ebx) 的指令,这当然是无效的。 64 位代码不是问题,因为它只会使用 RIP 相对寻址,因为输出的指令是 `%gs:0(%rip)`
  • @MichaelPetch:它在 64 位模式下编译,但使用像 movq %gs:0(%rip), %rax 这样的 RIP 相对寻址模式。 godbolt.org/g/jSvB2g(Godbolt 默认不启用 -pie,所以这是简单的位置相关代码。反汇编输出显示它确实使用 rel32 = 0,而不是使用偏移量 -RIP 来编码绝对地址0.即线性地址为GS_base + RIP)
猜你喜欢
  • 1970-01-01
  • 2015-11-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-12-06
  • 1970-01-01
  • 2016-12-12
相关资源
最近更新 更多