18
\ \ begingroup \美元

第一个答案是这个问题在Super User上给出了一个令我满意的解释,首先解释了为什么重置向量不在地址0(后来,我意识到这并不是为什么RAM的结束不能放在0xFFFFFFFF,然后向下增长)。但是,0xFFFFFFF0是一个很奇怪的地址。为什么x86在32位地址空间的前面16个字节开始执行?这16个字节是用于特殊用途的吗?

\ \ endgroup \美元
    37
    \ \ begingroup \美元

    X86指令通常会占用一个以上的字节,一个合理的重置程序几乎肯定会指向多个指令。

    如果重置向量指向0xFFFF_FFFF,那么只有一个单字字节的指令能适应这个内存映射;因此,几乎任何有用的重置功能都需要指令跨越0xFFFF_FFFF/0xFFFF_0000线性地址边界(因为代码段是用基数0xFFFF_0000设置的)

    通过将重置代码放置在这个地址,可以适应一些指令(包括跳转),而不需要0xFFFF_0000的有效内存。

    \ \ endgroup \美元
    6
    • 2
      \ \ begingroup \美元 实际上,即使是一次跳转,最小大小也应该是2个字节,而跳转是唯一能容纳这么小空间的有用指令。 \ \ endgroup \美元- - - - - -Ruslan 7月6日20分,9点47分
    • \ \ begingroup \美元 @ChrisStratton,谢谢,对术语做了一个快速修正 \ \ endgroup \美元- - - - - -毫微法拉 7月6日13:30
    • 2
      \ \ begingroup \美元 两个可能的初始化例程:cli;jmp远……(6字节);cli;cld;mov ax, 0xFFFF, mov ds, ax, jmp far [address](12字节)。当我拆开一张2001年的bios时,它使用了另一种变体的跳转表。 \ \ endgroup \美元- - - - - -约书亚 7月6日15点59分
    • \ \ begingroup \美元 @Joshua Intel编程手册上说,通常没有什么比跳转更简单的了,它通常是一个5字节的FAR跳转。这时应该没有任何其他类型的启动代码了,除了跳转。IBM确实进行了FAR跳转,而且由于有未使用的字节,所以5字节跳转遵循一个BIOS日期字符串或6个字符和两个字节的机器ID数据。注意,2001年时代的bios可能已经将自己解压到RAM中,因此实际上,您在引导后看到的可能与冷引导后的物理状态不匹配。 \ \ endgroup \美元- - - - - -Justme 7月6日16:36分
    • 4
      \ \ begingroup \美元 @Joshua CLI指令无关紧要。Reset按钮给CPU一个硬件复位,从一个定义的状态开始执行BIOS代码,我向你保证中断是禁用的。在硬件重置之后,也没有RAM可用,直到RAM控制器被初始化,然后所有的向量都被设置到位。病毒不可能在重置键下存活,除非它已经将自己写入BIOS。这已经发生了。 \ \ endgroup \美元- - - - - -Justme 7月6日20分17:09分
    25
    \ \ begingroup \美元

    它位于内存顶部以下16个字节的原因来自于初始8086 CPU寄存器在重置期间是如何加载的。甚至这可能与老的8085 CPU的兼容性有关。这种兼容性已经被移植到后来的芯片上,如80286、80386等。

    当然,他们可以选择任何值,但是由于中断向量是固定在内存区域的底部的,在那里,它打算有RAM,程序ROM打算被放在内存区域的顶部。

    虽然可以选择内存顶部的任何地址,但尽可能接近最后的内存地址是有意义的,这样它就不会规定ROM区域必须有多大,而且您可以使用尽可能小的ROM。

    而且它也不能太靠近最后一个内存地址,以便为指令提供足够的空间,至少可以跳转到其他地方执行代码。短跳操作码是两个字节,近跳操作码是三个字节,远跳操作码需要5个字节,因此为区域预留至少5个字节是有意义的。

    由于8086有一个20位(或1兆字节)的地址空间,设计者选择它使用分段内存方法,其中有一个16位段和16位偏移指向线性20位地址。这意味着每个段寄存器可以选择一个基址为16位偏移,基址粒度为16字节。基本上,16位8085的寻址只是通过添加段寄存器进行了扩展。

    因此,在硬件重置期间,程序计数器(IP)寄存器被设置为0x0000,就像在8085 CPU上一样。为了到达内存的末尾,代码段(CS)寄存器被设置为0xFFFF。这使得CPU从内存末尾的16个字节开始。

    有许多有效的CS: IP组合加起来的线性地址0 xffff0,但这确实是最有可能的最简单的方法,因为所有位的寄存器都含有相同的值,与零位,IP和CS与一位,所以加载一个特殊的结合位寄存器并不是必要的。

    然而,后来的cpu已经在一定程度上破坏了这种兼容性,但在某种程度上这并不重要。

    例如,80286用0xFFF0加载IP寄存器。因为它使用24位内存总线访问16 mb的内存,和罗仍然必须结束时16兆字节可寻址内存,CS寄存器值重置为0 xf000,以便实模式CS: IP指向0 xffff0和CS选择器基础设置的基地址0 xff0000设置物理内存的基础,使物理地址为0xFFFFF0。这样,如果你只是重新设计旧的8086系统来拥有80286,它就可以与启动原始ROM兼容。

    当扩展到32位80386时,它还加载带有0x0000FFF0的32位IP寄存器、带有0xF000的CS寄存器和带有0xFFFF0000的CS选择器基,因此物理地址是0xFFFFFFF0。因此,如果一个80286系统被重新设计为采用80386SX CPU,它就可以与启动原始ROM兼容。

    \ \ endgroup \美元

      你的答案

      点击“发布你的答案”,即表示你同意我们的服务条款隐私政策饼干的政策

      不是你想要的答案?浏览其他带标签的问题问你自己的问题