Assembly 当处理器试图访问一个不存在的物理地址时,会发生什么情况?

Assembly 当处理器试图访问一个不存在的物理地址时,会发生什么情况?,assembly,x86,Assembly,X86,设想一台32位x86计算机,内存小于3 GB,CPU设置为禁用分页和扁平段描述符(0x0为基础,0xffffff为数据和代码的有效限制) 当ring0中的指令尝试使用mov指令引用没有任何内存地址支持的物理地址时,会发生什么情况 QEMU仿真只是暂停,并出现类似“致命:尝试在RAM或ROM之外执行代码”的错误 这些异常与内存问题有关: 它不应该是“段不存在(#NP)”:它只在加载段寄存器时发生,但我实际上可以毫无问题地加载扁平段 不应生成“堆栈错误(#SS)”,因为代码不引用堆栈 “一般保护(#

设想一台32位x86计算机,内存小于3 GB,CPU设置为禁用分页和扁平段描述符(
0x0
为基础,
0xffffff
为数据和代码的有效限制)

当ring0中的指令尝试使用
mov
指令引用没有任何内存地址支持的物理地址时,会发生什么情况

QEMU仿真只是暂停,并出现类似“致命:尝试在RAM或ROM之外执行代码”的错误

这些异常与内存问题有关:

  • 它不应该是“段不存在(
    #NP
    )”:它只在加载段寄存器时发生,但我实际上可以毫无问题地加载扁平段
  • 不应生成“堆栈错误(
    #SS
    )”,因为代码不引用堆栈
  • “一般保护(
    #GP
    )”不应该发生,因为代码在环0中运行,并且段被设置为允许访问每个物理地址
  • 分页已禁用,因此也不是“页面错误(
    #PF
    )”
  • 而且这不是对齐问题,所以它不应该触发“对齐检查(
    #AC
    )”

  • 我没有选择了,不知道该怎么办。

    据我回忆,这可能是页面错误中断(向量位置14)

    “分页”在这里是一个宽泛的术语,任何内存访问都会产生该故障。但是,虚拟主机可能不知道如何正确处理它

    至少我假设你实现了所有的异常向量,所以如果发生任何一个异常,你会得到一条消息,日志,一些它出错的东西?这就是我要做的。直接在输出缓冲区(D800:0000?)中写入一条小消息将非常有用。只要在那里复制一个字符串,仿真器就会在控制台中显示它

    异常向量在我的手册6.4.1中,它在“中断或异常处理程序的调用和返回操作”下。这对客人应该做什么最有帮助(但实际上…)

    仔细想想,向运行guest的主机而不是guest本身报告这些“坏”错误并非不可能。一种可能性是,如果你不能确定的话,你可以直接用代码启动你的电脑,看看CPU在这种情况下会做什么。。。(假设您有所有异常的处理程序,那么您应该得到一个明确的答案。)

    事实上,我发现了一份您可能会感兴趣的文档:

    请看第20.3章。这就是x86仿真中的所有中断。这是您的答案:处理器将异常发送到virtual-8086监视器,然后必须将其转发回您。如果他们不这么做,那么。。。你对此无能为力。也许你的模拟器有一个选项可以帮助你

    因为它被设计为在8086处理器上运行,所以在虚拟8086模式任务中运行的8086程序包含一个8086样式的中断向量表,它从线性地址0开始。如果virtual-8086监视器正确地将中断或异常向量定向回它来自的virtual-8086模式任务,则8086程序中的处理程序可以处理该中断或异常。virtual-8086监视器必须执行以下步骤,将中断或异常发送回8086程序:

  • 使用8086中断向量在8086程序中断表中找到适当的处理程序

  • 将8086程序的EFLAGS(仅低阶16位)、CS和EIP值存储在特权级别3堆栈上。这是virtual-8086-mode任务正在使用的堆栈。(8086处理程序可以使用或修改此信息。)

  • 将特权级别0堆栈上的返回链接更改为指向特权级别3处理程序过程

  • 执行IRET指令,将控制权传递给8086程序处理程序

  • 当来自特权级别3处理程序的IRET指令触发一般保护异常(#GP)并因此有效地再次调用virtual-8086监视器时,恢复特权级别0堆栈上的返回链接,以指向原始的、中断的特权级别3过程

  • 将EFLAGS映像的低阶16位从特权级别3堆栈复制到特权级别0堆栈(因为有些8086处理程序修改这些标志以将信息返回到导致中断的代码)

  • 执行IRET指令,将控制权传递回中断的8086程序。 请注意,如果操作系统打算支持所有基于8086 MS DOS的程序,则有必要使用该程序提供的实际8086中断和异常处理程序。这是因为有些程序修改自己的中断向量表,以替换(或串联钩子)自己的专用中断和异常 处理程序



  • 另外,这是针对x86的。请注意,当我使用6502访问不存在的内存时,我只会得到垃圾。仅此而已……

    我的理解是,非分页内存访问直接进入总线,导致未定义的行为(取决于芯片组、总线类型等)——请参阅

    注意:尝试读取/写入不存在的内存时,您永远不会出现错误——理解这一点很重要:您不会得到有效的结果,但也不会得到错误


    如果禁用分页,且当前段的限制为4GiB(在32位模式下),则不存在“不存在”地址:

    在这种情况下,所有2^32个可能的地址都存在,可以读写

    如果对没有RAM、ROM等的地址执行读写操作取决于CPU外部的硬件,而不是CPU i,会发生什么情况