【问题标题】:How is effective address calculated with fs and gs registers如何使用 fs 和 gs 寄存器计算有效地址
【发布时间】:2020-05-04 23:15:42
【问题描述】:

在 x86_64 中,fs 和 gs 寄存器涉及有限形式的分段。仅以fs为例,fs如何注册,FSBase MSR共同产生有效地址?

如果我更改 fs 基数而不更改 fs 会发生什么?还是改变 fs base 会自动改变 fs?

如果我更改 fs 寄存器而不更改 fs 基数会怎样?有效地址计算有何影响?

我们可以举个简单的例子

mov %fs:(%eax), %ebx

【问题讨论】:

  • 嗨,欢迎来到堆栈溢出。您需要提供所有详细信息并清楚地提及您想要什么以及您为解决此问题所做的工作。请参阅How to Ask 链接了解更多详细信息并相应更新您的问题。
  • 我的问题很简单。 fs 和 fsBase 都涉及时,如何计算有效地址? fs中存储的值是多少?
  • @JeroenHeier:这实际上已经很清楚了。这是通常不会出现的技术性和晦涩难懂的东西,但我认为知道答案(或正在寻找答案)的人能够很好地理解这个问题。

标签: assembly x86-64 cpu-registers addressing-mode memory-segmentation


【解决方案1】:

FS 架构寄存器与基于 FS 的内部寄存器是分开的。

与往常一样,使用段覆盖只会选择与该段关联的段基,而不是默认的 DS 基或 SS 基(在 64 位模式下固定为 0)。

fs架构寄存器本身的实际值与它无关。只有当您要 mov %fs, %eax 实际读取 FS 寄存器本身,而不是使用与之关联的内部基/限制“寄存器”时,它才会发挥作用。

由于有一些方法可以设置内部 FS 基础(例如使用wrmsr 或在更新的 CPU 上the wrfsbase instruction)比mov 更有效到%fs(使其加载基础并限制从GDT 或 LDT),操作系统通常会保留 FS 和 GS 架构寄存器 = 0,即空选择器。

在裸机上,您也可以这样做。不要费心用你想要的基数创建一个 GDT 条目,然后将选择器 moving 到 %fs%gs;只需直接使用wrmsrwrfsbase 设置基础即可。

如果我更改 fs 寄存器而不更改 fs 基数会怎样?

你不能,AFAIK。 mov %reg/mem, %fs 将触发从 GDT 或 LDT 加载内部段基址/限制寄存器(取决于您移动的值)。

请注意,有些人将这些内部事物称为“缓存”,但它们不是缓存。它们保证在您加载它们时保留这些值,因此如果您更改 GDT 条目而不使用该选择器重新加载段寄存器,它们将永远不会发生变化。

如何影响有效地址计算?

一如既往。基数+索引*比例+位移。请注意,“有效地址”只是完整地址的偏移部分,不包括段选择器或基址。 What is an effective address?

线性地址也照常计算:segment_base + offset,其中偏移部分为寻址方式指定的有效地址。

寻址模式默认使用 DS 段基址,除非寻址模式中的“基址寄存器”是 E/RBP 或 E/RSP,在这种情况下它是 SS 基址。但是前缀字节可以覆盖默认值;这就是%fs: 告诉汇编器发出的内容。

【讨论】:

  • 那么,fs的实际值在这种情况下完全没用吗?
  • @PoorGuy998:是的。在您发表评论之前,我刚刚更新了我的一些额外说明。你可能想看看差异。
  • 快速澄清一下,在上面的例子中,mov %fs:%eax, %ebx, ebx 中的最终值会只是 FsBase + eax 吗?假设空段加载到 fs
  • 不,EBX 中的最终值将是从内存中加载的值,地址为 FSBASE + EAX。
  • @PoorGuy998: %fs:%eax 不是有效的 AT&T 语法,因为它不是 memory 寻​​址模式。如果它确实组装了,那么 FS 前缀对于寄存器之间的 mov 将毫无意义。如果您在问题中写过mov %fs:(%eax), %ebx,那么就像@prl 评论的那样:从线性(虚拟)地址FSBASE + EAX 的内存中加载。
猜你喜欢
  • 2011-09-30
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-01-11
  • 1970-01-01
  • 2013-06-17
  • 1970-01-01
  • 2012-05-08
相关资源
最近更新 更多