【问题标题】:x86 transition from 16bit to 32bit modex86 从 16 位模式过渡到 32 位模式
【发布时间】:2015-02-12 06:27:20
【问题描述】:

我正在阅读 Nick Blundell 的《从零开始编写操作系统》一书。在其中一章中,解释了我们如何从 16 位模式过渡到 32 位模式。它说在移动到 32 位模式之前,我们应该确保当前在管道(CPU 内的指令管道)内的所有 16 位模式的指令都被执行。为了做到这一点,我们应该做一个远跳,这会导致管道刷新,书上说这是完成当前处于管道不同阶段的所有指令。
但是我对流水线刷新的理解是,由于程序流程的变化,从指令流水线中删除了条件分支之后的所有指令。
我对这些描述感到困惑,有人可以解释一下管道冲洗期间发生的一切。
此外,这本书说,接近跳跃可能不足以进行管道冲洗。这个我也不懂。

【问题讨论】:

    标签: assembly x86 microprocessors


    【解决方案1】:

    当不执行这些指令时,需要管道刷新以从管道中清空预取和解码/翻译的指令。这在条件跳转和转换到指令集必须使用与 16 位实模式不同的逻辑解码的段之后都是必需的。可用的操作码、分段模型和默认操作数/地址大小前缀位(仅举几例)可能存在差异。

    有可能在处理器中对近跳转进行了优化,以便在解码后立即从某个地址开始预取指令;实际上,近跳转和远跳转的唯一区别是 CS 的显式重新加载(以及为指令解码设置新策略),这可能是为了触发流水线刷新而设计的。

    1[x86 中的跳转指令]1

    if(IsNearJump()) {
        if(IsRelativeJump()) TemporaryEIP = EIP + Destination; //EIP is instruction following JMP instruction;
        else TemporaryEIP == Destination;
        if(!IsWithinCodeSegmentLimits(TemporaryEIP)) Exception(GP(0));
        if(OperandSize == 32) EIP = TemporaryEIP;
        else EIP = TemporaryEIP & 0xFFFF; //OperandSize == 16
        //END
    }
    if(IsFarJump() && (PE == 0 || (PE == 1 && VM == 1)) { //real-address or virtual-8086 mode
        TemporaryEIP = Destination.Offset; //Destination is ptr16:32 or [m16:32]
        if(!IsWithinCodeSegmentLimits(TemporaryEIP)) Exception(GP(0));
        CS = Destination.SegmentSelector; //Destination ptr16:32 [m16:32]
        if(OperandSize == 32) EIP = TemporaryEIP; //Destination ptr16:32 [m16:32]
        else /*OperandSize == 16*/ EIP = TemporaryEIP & 0xFFFF; //clear upper 16 bits;
        //END
    }
    

    【讨论】:

    • 谢谢....但是如果管道刷新只是从管道中删除指令,为什么书上说它完成了当前管道中的所有指令。
    • 管道刷新 AFAIK,必须意味着仅刷新管道中的 invalid 或可能无效的指令。但是流水线中也有有效的指令,这些指令是要完成的。一种纯粹是推测的方法是,远调用向管道放置一个哨兵,这实质上完成了直到远调用的所有指令,将所有其他指令标记为无效并开始用与远方通话。
    猜你喜欢
    • 1970-01-01
    • 2020-06-18
    • 2018-08-07
    • 2021-04-22
    • 2014-07-29
    • 1970-01-01
    相关资源
    最近更新 更多