x86从16位转换为32位模式

时间:2015-02-12 06:27:20

标签: assembly x86 microprocessors

我正在阅读Nick Blundell撰写的“从头开始编写操作系统”一书。在其中一章中,我们将解释如何从16位模式转换到32位模式。它表示在转移到32位模式之前,我们应该确保执行当前位于流水线内部的所有16位模式指令(CPU内的指令流水线)。为了实现这一目标,我们应该做一个远程跳转,导致管道冲洗,书中说正在完成目前管道不同阶段的所有指令。
但是我对管道刷新的理解是,由于程序流程的改变,从指令管道中删除条件分支后的所有指令。
我对这些描述感到困惑,有人可以解释管道冲洗过程中发生的一切 此外,该书称近距离跳跃可能不足以进行管道冲洗。我也不明白这一点。

1 个答案:

答案 0 :(得分:3)

当不执行这些指令时,需要管道刷新来清空来自管道的预取和解码/转换的指令。在条件跳转之后和转换到段之后都需要这一点,其中指令集必须用与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
}