“ FS” /“ GS”寄存器的用途是什么?


102

因此,我知道以下寄存器及其用途是什么:

  • CS =代码段(用于IP)

  • DS =数据段(用于MOV)

  • ES =目标段(用于MOVS等)

  • SS =堆栈段(用于SP)

但是,以下寄存器打算用于什么?

  • FS =“文件段”?

  • GS = ???

注意:我不是在问任何特定的操作系统,而是在问它们打算由CPU使用什么(如果有的话)。


24
据我所知,这两个中的F和G代表什么。只是CPU(和指令集)中有六个用户可指定的段寄存器的空间,并且有人注意到,除了“ S”粘性段外,字母“ C”和“ D”(代码和数据)是按顺序排列的,因此“ E”是“多余”部分,然后是“ F”和“ G”。
2012年

3
可能是的,除非您当时在场(否则我一直在另一边,离英特尔的设计团队不远),否则总是很难知道别人的想法。
2012年

20
试想一下我们可以通过BS寄存器获得多少乐趣:-}
艾拉·巴克斯特

5
我一直将GS用作“图形细分”。:-)
Brian Knoblauch 2012年

2
“ G”能量“ S”段怎么样?
SS安妮

Answers:


109

它们的目的是什么,以及Windows和Linux的用途是什么。

段寄存器的最初意图是允许程序访问许多不同的(大)内存段,这些段旨在独立并且是持久性虚拟存储的一部分。这个想法来自1966年的Multics操作系统,该操作系统将文件视为简单的可寻址内存段。没有BS“打开文件,写记录,关闭文件”,而只是“将这个值存储到该虚拟数据段中”并带有脏页刷新。

我们当前的2010年操作系统向后退了一大步,这就是为什么它们被称为“太监”。你只能解决您的进程空间的单段,给人一种所谓的“平(恕我直言沉闷)地址空间”。x86-32机器上的分段寄存器仍然可以用于实际的分段寄存器,但没有人打扰(前英特尔总裁安迪·格罗夫(Andy Grove)上个世纪颇有名气,当时他发现所有这些英特尔工程师都花了很多精力和精力。他的钱去实现这个功能,没有人会去使用它。安迪!

AMD决定采用64位时,他们决定不在乎是否将Multics作为选择(这是一种慈善的解释;不慈善的是他们对Multics一无所知),因此禁用了64位模式下段寄存器的一般功能。仍然需要线程访问线程本地存储,并且每个线程都需要一个指针……处于立即可访问线程状态的某个位置(例如,在寄存器中)……以访问线程本地存储。由于Windows和Linux在32位版本中都为此目的使用了FS和GS(感谢Nick的澄清),AMD决定让64位段寄存器(GS和FS)本质上仅用于此目的(我想您可以使它们指向您处理空间中的任何位置;如果应用程序代码可以加载或不加载它们,则不知道)。

在架构上更漂亮的恕我直言,使每个线程的内存映射具有一个绝对虚拟地址(例如0-FFF),这是它的线程本地存储空间(不需要[segment]寄存器指针!);我是在1970年代使用8位操作系统完成此操作的,它非常方便,就像可以使用另一堆寄存器一样。

因此,段寄存器现在有点像您的附录。它们起着残余作用。给我们集体造成损失。

那些不知道历史的人注定要重蹈覆辙。他们注定要做些愚蠢的事。


10
@supercat:一种更简单,更出色的方案,可以让它们寻址65536倍的存储,将段寄存器视为低16位的完整高16位扩展,这实际上就是286、386而Multics做到了。
Ira Baxter

3
@IraBaxter:该方法的问题在于80286样式的段具有足够高的开销,而最终不得不在每个段中存储许多对象,因此在每个指针上都存储了段和偏移量。相比之下,如果愿意将内存分配舍入为16字节的倍数,则8086样式的分段允许一个人单独使用该分段作为标识对象的一种方式。四舍五入到16个字节的分配在1980年可能有点令人讨厌,但是如果将每个对象引用的大小从8个字节减少到4个,今天将是一个胜利。
超级猫

3
这些寄存器在现代操作系统中使用。它们主要用于指出有关任务控制块的信息,至少在现在可用于x86芯片的两个主要OS中。而且,由于即使出于它们的原始意图,它们也不再是“通用”,因此您不能将它们大量使用。最好在x86-64系统上假装它们根本不存在,直到您需要它们可以在线程控制块中访问的信息为止。
艾拉·巴克斯特2014年

5
基于过时的科学,附录类比的确是不好的。它与免疫系统有关,因此绝对不是 “研究”的。它减损了实际职位。除此之外,这是一个很好的回应。
code_dredd

5
感谢分段和平面内存的有趣,无休止的处理:)在6809(带有和不带有分页内存),6502,z80、68k和80 [123]?86上也编写了代码,我的观点是分段记忆是恐怖的表演,我很高兴它被寄托在历史的垃圾箱中。使用FS和GS高效访问thread_local数据是历史错误的意外结果。
理查德·霍奇斯

44

寄存器FSGS是段寄存器。它们没有处理器定义的目的,而是由操作系统运行它们来赋予目的。在Windows 64位中,该GS寄存器用于指向操作系统定义的结构。 FS并且GS通常被OS内核用于访问线程特定的内存。在Windows中,该GS寄存器用于管理线程特定的内存。linux内核用于GS访问cpu特定的内存。


1
它们是打算用于OS定义的目的,还是便于代码执行某些操作*dest++ = lookup[*src++];,如果dest,lookup和src位于三个不相关的位置,否则它们将很尴尬。
2013年

8
在Windows上,FS确实是用于线程特定的存储。请在此处查看FS所指向的块的文档化地图,
网址为

2
不只是在Windows上。GS还用于OS X上的TLS。64位内核还使用GS来在上下文切换期间跟踪系统结构。操作系统将使用SWAPGS达到此目的。
美国东部时间

11

FS用于指向Windows进程上的线程信息块(TIB)。

一个典型的例子是(SEH),它存储了一个指向回调函数的指针 FS:[0x00]

GS通常用作指向线程本地存储(TLS)的指针。您之前可能会看到的一个示例是堆栈金丝雀保护(stackguard),在gcc中,您可能会看到类似以下内容:

mov    eax,gs:0x14
mov    DWORD PTR [ebp-0xc],eax

2
这实际上并不能回答问题。问题指出:注意:我不是在问任何特定的操作系统,而是在问它们打算由CPU使用什么(如果有的话)。
Michael Petch

9
@MichaelPetch是的,我知道我只是想为那些在SO中阅读此q / s的人添加此为好信息
zerocool

2

根据《英特尔手册》,在64位模式下,这些寄存器旨在用作某些线性地址计算中的其他基址寄存器。我从第3.7.4.1节(第4卷中的第86页)中删除了此内容。通常,当CPU处于此模式时,线性地址与有效地址相同,因为在此模式下通常不使用分段。

因此,在这个平坦的地址空间中,FS和GS不仅在寻址本地数据而且在寻址某些操作系统数据结构(第2793页,第3.2.4节)中都发挥着作用,因此这些寄存器旨在供操作系统使用,但是那些特定的设计人员确定。

在32位和64位模式下使用替代时,会有一些有趣的技巧,但这涉及特权软件。

从“原始意图”的角度来看,很难说,它们只是多余的记录。当CPU处于实地址模式时,这就像处理器以8086高速运行,并且这些寄存器必须由程序显式访问。为了进行真正的8086仿真,您应该在virtual-8086模式下运行CPU,并且不会使用这些寄存器。


2

TL; DR;

“ FS” /“ GS”寄存器的用途是什么?

只需访问默认数据段(DS)之外的数据。就像ES。


长读:

因此,我知道以下寄存器及其用途是什么:

[...]

好吧,但DS几乎不是“某些”数据段,而是默认数据段。默认情况下所有操作都发生(* 1)。这是所有默认变量都位于-本质上databss。这是x86代码非常紧凑的部分原因。所有最常用的基本数据(加上代码和堆栈)都在16位速记距离之内。

ES用于访问其他所有内容(* 2),以及DS的64 KiB之外的所有内容。类似于文字处理程序的文本,电子表格的单元格或图形程序的图片数据等。与通常假定的情况不同,该数据的访问量不大,因此使用前缀比使用较长的地址字段所受的伤害小。

类似地,在进行字符串操作时可能必须加载(和重新加载)DS和ES只是一个小麻烦-至少这被其当时最好的字符处理指令集之一所抵消。

真正令人痛心的是,当用户数据超过64 KiB且必须开始操作时。尽管某些操作一次只对单个数据项完成(请考虑A=A*2),但大多数操作需要两个(A=A*B)或三个数据项(A=B*C)。如果这些项目位于不同的段中,则每个操作将重新加载ES几次,从而增加了相当大的开销。

最初,使用来自8位世界(* 3)的小型程序和同样小的数据集,这没什么大不了的,但是它很快就成为了主要的性能瓶颈-尤其是对于程序员(和编译器)。最终,随着386英特尔的加入,英特尔又增加了另外两个段,从而可以进行任何一元二进制三元运算,并且元素分布在内存中,而无需始终重新加载ES。

对于编程(至少在汇编中)和编译器设计,这是一个很大的收获。当然,可能还有更多,但是有了三个瓶颈就基本消失了,因此无需过度操作。

明智地将字母F / G命名为E之后的字母连续。至少从CPU设计的角度来看,没有任何关联。


* 1-将ES用于字符串目标是一个例外,因为仅需要两个段寄存器。没有它们就没有太大用处-或始终需要一个段前缀。这可能会杀死令人惊讶的功能之一,即使用(非重复)字符串指令(由于其单字节编码)而导致极高的性​​能。

* 2-因此,事后看来,“其他所有细分”的命名方式要比“其他细分”更好。

* 3-牢记8086只是在8800完成之前的一个止步措施,始终是非常重要的,它主要用于嵌入式世界,以吸引8080/85客户。


1
哇,谢谢你解释这一切!这说明了很多,并且很有道理!+1
user541686
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.