2015-02-12 143 views
0

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

回答

3

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

有可能在处理器中优化近跳转以便在解码后立即从某个地址开始预取指令;实际上近远跳变的唯一区别在于CS的显式重载(并且设置了用于指令解码的新策略),这可能被设计为触发流水线冲洗。

1 [在86跳转指令] 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 
} 
+0

谢谢....但如果管道冲洗只能从管线中移除的说明,为什么书上说,它完成当前管道中的所有指令。 – sarthak 2015-02-12 07:54:30

+0

管道冲洗AFAIK,必须意味着只清除管道中的_invalid_或潜在无效的指令。但是管道中也有有效的指示,这些指示意味着要完成。一种纯粹推测的方法是,远程调用将一个标识放置到流水线上,这实际上完成了所有指令直到远程调用,将所有其他指令标记为无效,并开始用与该流水线关联的微代码填充流水线远调用。 – 2015-02-12 08:42:47