%fs
,%gs
,%cs
,%ss
,%ds
和%es
密切相关。 有人可以解释在用户程序和内核程序中如何使用这些寄存器吗?
#1 楼
内核角度:我将尝试从内核角度回答,涵盖各种操作系统。
内存分段是访问内存区域的旧方法。
所有主要包括OSX,Linux(版本0.1)和Windows(版本NT)的Windows操作系统现在正在使用分页,这是访问内存的更好方法(IMHO)。
英特尔一直在向后引入兼容性。因此,它的处理器(IA-64除外,我们看到了它是如何发生故障的...)
因此,在初始状态(重置后),处理器以称为实模式的模式启动,在此模式下,通过默认情况下支持旧版软件。
在操作系统启动过程中,处理器被更改为保护模式,然后进入启用的分页。
分页之前,段寄存器的使用方式类似于this
在实模式下,每个逻辑地址都直接指向物理内存中的位置,每个逻辑地址由两个16位部分组成:逻辑地址的br />段部分包含
段的基址,其粒度为16个字节,即,段可以从
物理地址0、16、32,...,220开始-16。逻辑地址的偏移量部分包含段内的偏移量,即,物理地址可以分别计算为
physical_address := segment_part × 16 + offset
(如果启用了地址线A20),qbr12079q(如果为A20)关闭)。每个段的大小为216个字节。 [Wikipedia] 让我们看看一些示例(286-386时代):
286体系结构引入了4个段:CS(代码段)DS(数据段) )SS(堆栈段)ES(额外段)
386体系结构引入了两个新的通用段寄存器FS,GS。
典型的汇编操作码(采用Intel语法)如下所示:
mov dx, 850h
mov es, dx ; Move 850h to es segment register
mov es:cx, 15h ; Move 15 to es:cx
使用分页(保护模式)段寄存器不再用于寻址内存位置。在保护模式下,将
(segment_part × 16 + offset`) mod 220
替换为16位选择器,选择器的13个高位(第3位至第15位)包含描述符表中条目的索引。下一位(位2)指定是与GDT还是LDT一起使用。选择器的最低两位
(位1和位0)被组合以定义请求的特权
;其中值为0的优先级最高,值为
3的优先级最低。 [wikipedia]
段仍然用于在GDT中强制执行硬件安全性由英特尔
x86系列处理器从80286开始,目的是定义程序执行期间使用的各种内存区域的特征,包括基地址,大小和访问特权。 />,例如可执行性和可写性。这些内存区域在Intel术语中称为
段。 [wikipedia]
因此,实际上,处于保护模式的段寄存器用于将索引存储到GDT。
多个操作系统,例如Windows和Linux ,将某些细分用于内部使用。例如,Windows x64使用
segment_part
寄存器来访问TLS(线程本地存储),而在Linux中,它用于访问cpu特定的内存。用户角度:
从用户角度,在最近使用分页的操作系统中,内存以所谓的“平面模式”工作。
每个进程都以线性方式访问其自己的内存(4GB),因此基本上不需要段寄存器。
它们仍然是寄存器,因此它们当然可以用于其他各种组装操作。
评论
不错的答案,但是我会在所有主要操作系统上加点澄清...使用分页。我不了解linux,但是正如您稍后在回答中指出的那样,NT仍然使用段来进行保护(至少在x86上)。特权级别或环链接到段。因此,将地址空间细分为(至少)四个段。地址空间仍然看起来像是4gb平面,但是较低的2(或3)GB是具有环3访问权限的一个网段,较高的2(或1)是具有环0访问权限的网段。
–洛伦佐·德马特(LorenzoDematté)
13年5月23日在8:45
其他两个段是用户空间的低端和高端(0-2GB)的(短-64kb长)区域。它们有助于捕获空指针并标记“可用用户空间的完成”。总的来说,这种内存管理技术称为“页面分割”,即IIRC:有多个段(只有几个),每个段都被页面化。
–洛伦佐·德马特(LorenzoDematté)
13年5月23日在8:46
@LorenzoDematté您是正确的...随时根据您的见解编辑我的答案。
–烛光
13年5月23日在10:21
是的,这就是为什么我认为没有必要进行编辑且注释足够的原因:)
–洛伦佐·德马特(LorenzoDematté)
13年5月23日在12:44
movs,850h;将850h移至es段寄存器中上面的指令不存在因为不可能用立即数加载段寄存器。只能用其他非段寄存器的内容,RAM位置的内容或从堆栈的堆栈中弹出一个值mov es:cx,15h来加载一个段寄存器。将15移到es:cx上面的指令也不存在。因为不能将CX用作地址寄存器,所以只能将ECX用作地址寄存器。
–user2127
13年5月30日在5:36
#2 楼
FS指向异常处理链,CS和DS从OS中填充了代码和数据段。 SS是电池/电池组段。据我所知,GS和ES是免费的。内核或用户模式无关紧要(XLAT,MOVS等某些指令使用了它们,因此您必须在以同样的方式),但以防万一我在谈论用户空间中的编程。
我以前没有注意到,但是您使用的是%fs而不是FS,所以您可能是意思是Linux,这是另一回事了(在保护/实模式下,您也可能会更加清楚)。您还可以从stackexchange上的其他答案中看到,Linux显然在FS和GS中为您提供了“线程本地存储”和“处理器数据区域”。 CS,DS和SS仍应为代码/数据/堆栈。
为了便于说明,我不知道在Mac上如何使用这些寄存器。
对于64位,这取决于:如果不处于兼容模式(可以在其中执行64位和32位代码),则DS,ES和SS会被忽略,并且诸如POP SS的指令会给出错误。没有分段(内存模型是平面的),应该没有实模式(但我认为您仅指保护模式?),如果我没记错的话,也就没有硬件任务切换。
有是有关64位模式下CS,FS和GS(尤其是隐藏部分)的更多详细信息,但是由于它不经常使用,最好省略它们。
您可以查看AMD手册系列处理器,尤其是在64位旧版模式下:http://developer.amd.com/resources/documentation-articles/developer-guides-manuals/
评论
没有发布图片的“足够的声誉”很奇怪...
– lunadir
13年5月4日在12:31
安腾(IA-64)具有段寄存器对我来说是新的。你可以解释吗?!
– 0xC0000022L♦
13年5月4日在16:31
好吧,是的,实际上不应该有任何段,因为没有段...无论如何,在从ia-32到ia-64编程的过渡过程中,段寄存器都映射到了应用寄存器GR16-GR17(或者这样写) )
– lunadir
13年5月4日在16:58
Linux从未使用过分段,而是一直使用分页。关于Windows,因为NT,它也使用分页,所以除非您在进行DOS编程/反转,否则此处描述的内容不再相关。
–烛光
13年5月5日在1:06
我的一个碰巧是正在反转DOS二进制文件,因此找到此信息非常宝贵。
– L0j1k
15年7月6日在5:57
#3 楼
我写了一个Windows特定问题的答案,该问题被标记为重复并关闭,并且关闭标志引用了此线程,因此我在此处发布了答案OS win7 sp1 32位计算机
内核转储使用sysinternals的livekd
16位段寄存器包含
13位选择器
表描述符的1位
requester_privilege_level的2位
>
Selector tl rpl
0000000000000----0---00
,因此将cs和fs转换为二进制将
kd> r cs;r fs
cs=00000008 = 0b 00001 0 00
fs=00000030 = 0b 00110 0 00
2位rpl表示0、1、2、3振铃(因此00 = 0 =环零)
gdt = 1位表示0,1(0表示GDT,1表示LDT)
全局描述符表和局部描述符表
高13位代表段选择器
因此cs = 0x08具有段选择器0b 001 = 0x1即gdtr @ 1
&fs = 0x30具有段选择器0f 0b 110 = 0x6,即gdtr @ 6
内核cs,fs与用户cs,fs
不同,可以从windbg的dg命令中注意到
kd> dg @cs <<<<<<<--- kernel
P Si Gr Pr Lo
Sel Base Limit Type l ze an es ng Flags
---- -------- -------- ---------- - -- -- -- -- --------
0008 00000000 ffffffff Code RE Ac 0 Bg Pg P Nl 00000c9b
0:000> dg @cs <<<<<<<<----user
P Si Gr Pr Lo
Sel Base Limit Type l ze an es ng Flags
---- -------- -------- ---------- - -- -- -- -- --------
001B 00000000 ffffffff Code RE Ac 3 Bg Pg P Nl 00000cfb
kd> dg @fs <<<<<<<<------- kernel
P Si Gr Pr Lo
Sel Base Limit Type l ze an es ng Flags
---- -------- -------- ---------- - -- -- -- -- --------
0030 82f6dc00 00003748 Data RW Ac 0 Bg By P Nl 00000493
0:000> dg @fs
P Si Gr Pr Lo
Sel Base Limit Type l ze an es ng Flags
---- -------- -------- ---------- - -- -- -- -- --------
003B 7ffdf000 00000fff Data RW Ac 3 Bg By P Nl 000004f3
您可以从osdevwiki_gdtrobert-collins_ddj_article
收集有关gdt的足够信息,以在此处使用livekd手动进行操作
使用windbg,您可以获得描述符和任务门寄存器
kd> rM 100
gdtr=80b95000 gdtl=03ff idtr=80b95400 idtl=07ff tr=0028 ldtr=0000
每个gdtr条目都是64位,因此您可以拥有7f gdtr条目,因为您看到gdtl是3ff 0x80 * 0x08-1 = 0x400-1 = 0x3ff(索引从0开始而不是1) )等
kd> dq @gdtr+8 l1 gdtr@1 = gdtr+0n1*0x8 =0n8 = 0x8
80b95008 00cf9b00`0000ffff = gdtr+0n6*0x8 =0n48 = 0x30
kd> dq @gdtr+30 l1
80b95030 824093f6`dc003748
kd> dq @gdtr+38 l1
80b95038 7f40f3fd`e0000fff
手动对游戏的最后两个gdtr条目进行位游戏
-------------------------------------------------------------------------------------------
gdtrentry [63: [55: [51: [47: [39: [15:
56] 52] 48] 40] 16] 0]
base gdrs L p d t Base Base Limit
Hi rb0y h r l y Mid Low
-------------------------------------------------------------------------------------------
bit position 66665555 5555 5544 4 44 44444 33333333 3322222222221111 1111110000000000
32109876 5432 1098 7 65 43210 98765432 1098765432109876 5432109876543210
-------------------------------------------------------------------------------------------
824093f6dc003748 10000010 0100 0000 1 00 10011 11110110 1101110000000000 0011011101001000
as hex 0x82 0100 0 1 0 0x13 0xF6 0xDC00 0x3748
--------------------------------------- ---------------------------------------------------
7f40f3fde0000fff 01111111 0100 0000 1 11 10011 11111101 1110000000000000 0000111111111111
as hex 0x7F 0100 0 1 3 0x13 0xFD 0xE000 0x0FFF
-------------------------------------------------------------------------------------------
评论
这个答案最初是为这个问题而写的。
–绿色环保
17年6月14日在7:40
@blabb:奇怪!您为什么不发布关于其他问题的答案?这个问题是特定于Linux的,而您的答案是特定于Windows的。以某种方式,您的答案会更好地适合另一个问题。你不觉得吗(不过,很不错的答案!)
–恐怖
17年6月14日在8:33
啊,另一个问题已经解决了!!!那我投票赞成重新开放。
–恐怖
17年6月14日在8:34
@perror是,该问题已作为重复问题被关闭,并且注释引用了该线程,因此我不得不在此处发布
– blabb
17年6月15日,下午3:06
评论
您需要特定于操作系统是的,你是对的。我将问题编辑为特定于Linux。
我建议您阅读分步汇编语言-duntemann.com/assembly.html
Google的Native Client技术使用分段来实施沙箱。您可以查看实施以获取更多见解。