386+处理器中的复位向量

6
维基百科关于重置向量的页面(适用于386+处理器):CS寄存器的选择器部分值在重置时为F000h,CS寄存器的基址部分值为FFFF0000h,在实模式下,重置时IP寄存器的值为FFF0h,形成分段地址FFFFF000h:FFF0h。我阅读有关计算机启动的所有文献都说处理器以实模式启动,因此“选择器”不应涉及。那么为什么这里提到了选择器?还有,这里所指的“基址部分”是什么,并存储在哪个寄存器中?基本上,我不明白386处理器与之前的处理器如何设置重置向量。

请参见 https://dev59.com/GWDVa4cB1Zd3GeqPbTxF,这是一个非常相关的问题,并提供了额外有见地的答案。 - wmjdgla
2个回答

4
需要访问的地址是存储重置向量的最后16个字节的内存地址。 由于8086/80186和80286+处理器之间的差异,CS的值不同。在80286处理器及以上版本中,存在一个全局描述符表(GDT),用于指定系统上的内存访问和利用方式。8086没有GDT,因此内存访问基本上是固定的。即使在286+的实模式下,也存在GDT条目。您提到的“基址”和“选择器”仅是GDT条目的“基址”和“选择器”部分。因此,由于存在GDT条目并且对286+处理器在所有处理器模式下都产生影响,重置向量的设置会发生变化。在新启动的系统上,使用以下段:偏移值:
8086/80186 (16-bit):             0xFFFF:0x0000
80286      (16-bit):             0xF000:0xFFF0
80386+     (32-bit):         0xFFFFF000:0xFFF0
           (64-bit): 0xFFFFFFFFFFFFF000:0xFFF0

基本上,在80286和更高版本的处理器上,偏移量和段值是相同的,除了在32位和64位处理器上,段值被符号扩展。


1
@fante - 我已经重新表述了我的答案,以更好地反映我对我的陈述的意思。此时不应该有任何错误或歧义。 - Adrian Collado

1

是的,在上电后,所有x86 CPU都处于Real Mode下,但在找到CS赋值之前会有奇怪的行为!!!。

读完一些x86文档,这些是事实:

上电后,'CS register'、'CS cache register'和'EIP'的初始值为:

CS= F000h (16位宽度,应该始终如此!)

CS_segment_start_address= FFFF_0000h (一个32位的值,指向RAM中的某个位置?)。 CS_segment_lenght= 0_FFFFh (20位大小值,是的,这是64KB)。

CS_segment在内存中是'Present'。

CS_segment是一个'可读/可写'的块。

CS_segment已经被'访问'。

EIP= 0000_FFF0h

现在,请注意以下生命的事实。

==SOF==(事实开始)

在获取新指令时(无论处于哪种模式:实模式、保护模式等),似乎硬件寻址逻辑始终使用某些“CS缓存寄存器”值来确定要放置在地址总线引脚上的地址。具体来说:
下一条指令地址 = CS段起始地址 + EIP
==EOF==(事实结束)
因此,在上电后,我们有以下数字:
下一条指令地址 = FFFF_0000h + 0000_FFF0h = FFFF_FFF0h
这意味着,我们是否可以在上电后访问RAM的最后一个角落,远离1MB限制?是的!!!圣杯!!!
但是,请等一等,不要着急跑和跳!!!这只是旨在(由软件开发人员)将“far jump”放置到BIOS ROM区域中的某些代码块中!
然而,是主板确保重置向量(0xFFFFFFF0h)处的指令是跳转到映射到系统BIOS入口点(0x0000: 0x000F0000h)的内存位置的远跳转。总之,每个“主板”都实现了这个“跳跃黑客”。 [Gustavo Duarte有一个很好的解释,请查看他的博客:http://duartes.org/gustavo/blog/post/how-computers-boot-up/]
根据上面的解释,最后提到的那个“远跳转”会使用良好行为的“实模式”值更新“CS_segment_start_address”: 类似于CS= XYZWh(使用远程'jump'、远程'call'或任何其他方法完成)的赋值将被翻译为: CS_segment_star_address= 000X_YZW0h(其中XYZW是CS nibbles值)
回到通常的业务中,进行4位左移,1MB限制,64KB段长度等操作!
最后几句话,我猜这个行为是为了确保您的上电(启动?)代码始终位于RAM的最后一个角落。这样它将为未来的操作系统处理留下足够的RAM空间。
[对我来说,把这个“重置”向量放在中断向量表中的第0个向量位置会更有意义。]
如果我错了,请纠正我。希望这可以帮助你。
附注:什么是CS缓存寄存器?它是与正在使用的CS选择器相关联的描述符值。所有其他段也具有这些“缓存寄存器”值以进行快速访问。请记住,在x86 CPU上,您不能随意禁用“分段”。您必须处理它。阅读一些涉及分段的“保护模式”了解更多信息...不幸的是(或者幸运的是?)分段已经过时了。分页已经取代了它作为保护机制。
顺便说一句,一些维基百科文章似乎带着错误的逻辑进行编辑。要小心!!!

在你的回答中,你提到了“CS_segment_start_address= FFFF_0000h(一个32位的值,指向RAM中的某个地方?)”。我很好奇这个位置的物理位置在哪里?显然它应该在主存储器带的某个地方,但如果我们假设地址按字节映射,那么实际上是4G-16个字节,但不是所有32位计算机都有4G的内存。如果计算机只有2G的内存,那么这个0xFFFFFFF0h将指向哪里?我能否假设这个地址是“已安装的任何内存- 16个字节”? - jimx
@jimx:你已经理解了一个我之前没有想明白的“黑点”。并且解释也有一点不同于你提出的。维基百科说:“平台逻辑将该地址映射到系统ROM,而镜像地址000FFFF0h。”这一点被Gustavo Duarte阐述得更加清楚:“主板确保复位向量(0xFFFFFFF0h)处的指令是跳转到映射到BIOS入口点的内存位置。”总之,每个“主板”都实现了这个“跳转黑客”。请查看他聪明的博客网站:http://duartes.org/gustavo/blog/post/how-computers-boot-up/ - fante
“CS=XYWZh” 是打错了吗?下一行你用的是 XY_ZW_。另外,BIOS 的入口点是 0x0000:0x000F0000h 吗?假设 BIOS 镜像大小为1MB(0x100000),因此在镜像中,复位向量位于偏移量0xFFFF0。由于复位向量映射到0xFFFFFFF0,这意味着BIOS映像映射到0xFFFFFFF0 - 0xFFFF0 = 0xFFF00000.反推0x000F0000的计算结果得到一个不可能的BIOS映像大小0xFFF10000。 - wmjdgla

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接