【问题标题】:How CPU predicts, the instruction and data limits in the sequence of binary information of binary file?CPU如何预测二进制文件的二进制信息序列中的指令和数据限制?
【发布时间】:2020-06-04 17:26:18
【问题描述】:

CPU如何区分指令和数据?

CPU 在执行代码时如何确定指令的长度(从 1 字节到最大 15 字节不等)?如果假设 cpu 不确定指令的长度,它可能会将数据作为指令的一部分。在这种情况下,可能会出现不希望的结果或 cpu 不执行该指令(如果不在操作码表中)。 cpu如何判断,是数据还是指令?

【问题讨论】:

    标签: x86 cpu-architecture machine-code instruction-set illegal-instruction


    【解决方案1】:

    它不必预测。 从逻辑上讲,它一次解码一个字节,直到看到一条完整的指令。(或 disp32 或 imm32 的 dword 块,或由较早字节隐含的指令的其他多字节部分。)该指令由前缀和操作码 + modrm + SIB 字节隐含。看了这些之后,CPU 就知道它还需要获取多少指令字节。

    但是真正的 CPU 只需要给出这样做的假象,并且 可以查看后面的字节,只要它最终会做正确的事情,如果它们不是应该执行的指令的一部分。

    在实际实现中,只要您最终做对了,推测性地加载后面的字节就没有问题。

    例如L1 指令缓存使用 64 字节行,因此逻辑执行达到一个字节意味着整个 64 字节内存块将在 I-cache 中,即使它 在 L1 D-cache 中,因为您对同一行中的其他字节执行了一些数据加载指令。

    当然,从 L1I 缓存中获取也不是一次单个字节。在现代 x86 上,解码查看 32 或 16 字节的块以查找指令边界。例如让我们看看 P6 系列,它没有 uop 缓存,所以它总是从 L1I 获取/解码。

    来自Agner Fog's microarch PDF,在 PPro/PII/PIII 部分:

    6.2 指令获取

    指令码以对齐的 16 字节块从代码缓存中获取,并转换为双精度 可以容纳两个 16 字节块的缓冲区。双缓冲的目的是为了 可以对跨越 16 字节边界的指令进行解码(即地址可整除) 16)。代码从双缓冲区传递到块中的解码器,我将 调用 IFETCH 块(指令提取块)。 IFETCH 块最长为 16 个字节。在 大多数情况下,取指单元使每个 IFETCH 块从一条指令开始 边界而不是 16 字节的边界。但是,取指令单元需要 来自指令长度解码器的信息,以便知道指令在哪里 边界是。如果此信息无法及时获得,则它可能会启动 IFETCH 块 以 16 字节为边界。这种并发症将在下面更详细地讨论。

    预解码器流水线阶段然后找到指令边界(假设它们都是有效指令),然后(根据分支预测单元所做的预测)将 3 条指令的机器代码并行发送到 3 个解码器. (Core2 扩大到 4 个解码器,Skylake 扩大到 5 个解码器,尽管流水线宽度保持在 4 微秒宽)。

    如果某处存在非法指令(或无条件的jmp,或恰好被采用的jcc),那么稍后的“指令”将毫无意义,并在发现该事实后被丢弃。

    https://www.realworldtech.com/nehalem/5/ 谈论 Nehalem 中的解码阶段,这是上一代 P6 系列微架构。但 Agner Fog 的描述可能更有助于理解 CPU 如何查看一堆字节,然后只使用逻辑上应该作为指令执行的字节

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2016-09-26
      • 2020-11-06
      • 2022-10-15
      • 2012-06-11
      • 2014-10-01
      • 1970-01-01
      • 2019-07-15
      相关资源
      最近更新 更多