我需要修改一些dll,但我不知道,在保护模式下,段寄存器(DS
,SS
,...)是多么令人兴奋。我在学校里学到了真正的16位模式,其中段寄存器在正常寄存器中乘以16加偏移量,在物理存储器中提供有效地址。在保护模式下,有一些平面内存模型和虚拟内存,每个进程“有”4GB内存,所以如果寄存器有32位,那么我只能通过“偏移”寄存器来寻址虚拟内存的每个字节。那么哪些瞳孔在保护模式下具有段寄存器,例如
mov eax, dword ptr ds:[20037DA0]
答案 0 :(得分:6)
基本上,目的与实际模式相同,只是它们的工作方式略有不同。您的示例中的DS在您的GDT中选择一个内存描述符(谷歌这个术语,如果您真的想要理解这一点,“全局描述符表”),其中包含基地址,结束地址,粒度等信息。然后将您的偏移量添加到基址, 结束。如果你在windows上(我在linux上打赌它一样),你根本不必担心这些段寄存器,正如你所说的扁平模型,这意味着所有内存应该只有一个描述符,所以如果你不改变这些寄存器应该像它们甚至不存在一样工作。
答案 1 :(得分:5)
一些历史背景
8086每个段始终使用固定的64KiB窗口,其起始地址由(段寄存器* 16)计算。由于80286在内存中有一些特殊的表(GDT和LDT)。这些表包含段的起始地址,长度和访问权限。段寄存器(CS,DS,ES,SS - 以及80386:FS,GS)包含这些表中的索引。
因此理论上,操作系统可以按照它想要的方式设置段的偏移量和长度:在8086 DS = 0x0123意味着:段是从地址0x01230开始的64KiB。在32位模式下,DS = 0x0123可能意味着:段从地址0xABCD开始,长度为0xEF字节 - 这取决于操作系统创建的GDT和LDT表的内容。尝试访问此范围之外的段(如果长度为< 0x1000,则DS:0x1000)将导致异常(中断)。
现状
然而,大多数现代32位操作系统不再使用段寄存器。由于访问权限问题,它们的值是根据模式(内核或用户)设置的。起始地址通常为0,长度为4GiB。
使用MMU完成实际内存保护,以便在用户模式下无法访问某些内存区域。在现代操作系统中,MMU绝对是必不可少的。它将“绝对”虚拟地址映射到检查访问权限违规的真实物理地址。
有一个例外:某些操作系统(例如Windows和Linux)使用FS和/或GS段来指向不同的内存区域。
因此,在64位模式下,x86处理器仅将CS寄存器用于访问权限问题,FS和GS可用于向每个地址添加偏移量。据我所知DS,ES和SS不使用,而寄存器FS和GS的内容无关紧要,但有一些特殊的寄存器明确地将偏移量添加到使用FS或GS的操作中。
答案 2 :(得分:1)
我会给你一个简单的答案,但是为了进一步的信息,我推荐下面的链接到AMD的架构文档,非常容易阅读。 PS:我没有在这里覆盖Xeon或PAE ..
IA-32(x86)架构具有用于RAM的32位物理地址总线。
32位总线进一步分为2个16位段,每个段能够访问2GB RAM,总共4GB。 这称为存储库切换。
为了保护英特尔和MS一起决定将一个段用于内核模式而另一个段用于用户模式 - 这就是Windows历史上具有2GB用户模式地址空间的原因。这是x86硬件限制,而不是Windows限制。
该段注册分离的内核空间和用户空间地址。 这就是记忆保护的实施方式。
此外,IA-32通用也有32位内部寄存器,因此无法寻呼。这是实模式(无地址转换)。
Paging需要36位,我认为(不要引用我)是IA32e进来的地方.IA-32e上的额外位允许从HDD进行分页,这是它可以在x64 Windows上运行的唯一方式,因为x64需要NX和它位于第63位。
请阅读AMD架构文档,我个人认为它们比英特尔版本更具信息量。
http://developer.amd.com/wordpress/media/2012/10/24593_APM_v21.pdf
推出了采用AMD64平板内存的PS,取消了细分市场。
然而,32位进程仍然需要段寄存器。 在AMD64上,当32位进程到达堆栈顶部时,指针被抛出到新段寄存器的基址上。这样32位应用程序可以有效地吃掉他们想要的RAM,没有限制。在......的原因之内......)
希望这有帮助。