我正在读Nick Blundell写的书“从零开始写操作系统”。在其中一章中,解释了如何从16位模式转换到32位模式。它说,在转移到32位模式之前,我们应该确保当前在流水线(CPU内的指令流水线)内的所有16位模式的指令都被执行。它说,为了实现这一点,我们应该进行远跳转,这会导致流水线刷新,书中说这会完成当前流水线不同阶段的所有指令。
但我对流水线刷新的理解是,由于程序流程的改变,从指令流水线中移除了条件分支之后的所有指令。
我对这些描述感到困惑,有人能解释一下在管道刷新过程中发生了什么吗?
此外,书中说,近距离跳跃可能不足以进行管道冲洗。我也不明白这一点。
发布于 2015-02-12 07:43:58
当不执行预取和解码/翻译的指令时,需要流水线转储清除来从流水线清空这些指令。这在条件跳转之后和转换到段之后都是必需的,在段中,指令集必须使用与16位实数模式不同的逻辑来解码。可用操作码、分段模型和默认操作数/地址大小前缀位(仅举几例)可能存在差异。
可以在处理器中优化近跳转,以便在解码后立即开始从某个地址预取指令;实际上,近跳转和远跳转的唯一区别是显式地重新加载CS (并为指令解码设置新的策略),这可能已经被设计为触发流水线刷新。
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
}
https://stackoverflow.com/questions/28470783
复制相似问题