【问题标题】:How do direct number operands in a CPU work?CPU中的直接数字操作数如何工作?
【发布时间】:2017-02-18 16:36:45
【问题描述】:

举个例子:x86_64 CPU 读取 128 位指令。

据我了解,这基本上是 x86 处理器中发生的事情。 否则,例如,无法将 64 位数字添加到 64 位寄存器(操作码将占用几位 + 64 位的数字 > 64)。

我想知道的是指令中的位限制是多少,以及如果指令大于位(数据总线),如何读取指令。 此外,我也知道大多数 RISC CPU 使用固定大小的指令,所以如果你直接传递一个数字操作数,指令的大小是不是简单地翻了一番?

【问题讨论】:

  • 在具有固定字指令大小的 RISC 上,通常没有指令加载“任何”立即数,只有一部分,然后由几条指令构建完整的立即数(如果不能使用这样的立即数,可以在单个负载中对其进行编码)。在 x86 上,指令大小不固定,并且指令长度根据需要:movabs rax,0x123456789abcdef0 = 48 B8 F0 DE BC 9A 78 56 34 12 = 10 字节(每个 movabs rax,nn 有 10B,即使在立即加载 0 时也是如此,因此每个操作码/操作数的指令大小甚至是固定的在 x86 上)
  • 每条指令的编码都在手册中。英特尔官方 PDF 的 HTML 摘录很方便:felixcloutier.com/x86。另请参阅 stackoverflow.com/tags/x86/info 以获取有关 x86 的其他链接。
  • 很高兴知道 Ped7g。我对手册很熟悉,只是找不到直接的答案。

标签: assembly x86 risc


【解决方案1】:

x86_64 CPU 读取 128 位指令

这不会发生,最大指令大小定义为 15 个字节。您可以构造更长的指令,但它们将是无效的。

您不需要 16 个字节来拥有一条采用 64 位立即操作数的指令。一开始只有几个 x64 指令可以做到这一点,例如mov r64, imm64,它被编码为REX.W B8+r io,因此是 10 个字节。几乎所有采用立即数的 64 位 x64 指令都采用符号扩展的较短立即数,即 8 位或 32 位。

在 RISC ISA 中,通常不可能有一个与字长一样大的立即数,您必须分两步在寄存器中构造大值或从内存中加载它们。但是 x64 和它的 x86 根源一样,绝对不是 RISC。

我怀疑这个问题(部分)是由一个接一个通过数据总线的指令的心理形象所激发的,这对 MIPS 等来说很好,但是使用可变长度指令,没有像 x86 中那样的对齐要求你就是不能那样做——无论你选择什么样的块,它可能(而且很可能是)直接通过一些指令。因此,从最简单的角度来看,解码是一个带有缓冲区的状态机,对第一条指令进行解码并将其从缓冲区中删除,当有空间时填充更多字节(当然现在更复杂了)。

【讨论】:

    【解决方案2】:

    顺便说一句,直接嵌入到指令中的操作数数据称为“立即”数据。


    这不是现代 CPU 的工作方式,但数据总线比最长指令窄实际上不是问题。

    例如,8086 确实必须处理比其 16 位数据总线更宽的指令编码,而无需任何 L1 缓存来隐藏这种影响。

    据我了解,8086 只是不断将字(16 位)读入解码缓冲区,直到解码器一次看到整条指令。如果有剩余字节,则将其移动到解码缓冲区的前面。下一个 insn 的指令获取实际上与刚刚解码的指令的执行并行发生,但代码获取仍然是 8086 的主要瓶颈。

    因此 CPU 只需要一个与允许的最大指令(不包括前缀)一样大的缓冲区。那是6 bytes for 8086,这正是8086's prefetch buffer 的大小。

    “直到解码器看到整个指令”是一种简化:8086 分别解码前缀,并将它们“记住”为修饰符。 8086 没有后期 CPU 的最大 15 字节总 insn 长度限制,所以你可以fill a 64k CS segment with repeated prefixes on one instruction)。


    现代 CPU(如 Intel P6 和 SnB 系列)以至少 16B 的块从 L1 I-cache 获取代码,并实际并行解码多条指令。 @Harold 很好地涵盖了您的其余问题。

    另请参阅Agner Fog's microarch guide,以及来自 标签 wiki 的其他链接,详细了解现代 x86 CPU 的工作原理。

    此外,David Kanter 在 SandyBridge 的文章中详细介绍了该微架构系列的前端。

    【讨论】:

    • 如果我从您的帖子中理解正确,x86 CPU 有一个单独的“单元”,用于获取指令和解码指令,将其转换为微代码并将其提供给处理核心?我已经明白多核 CPU 需要这样的东西来分离工作负载,但它也适用于单核?
    • @RabbitBones22:这个图是单核的前端。每个内核都有自己的获取/解码硬件,以及自己的私有 L1 I-cache。这里与多核无关,如果您将 Sandybridge 缩小为单核设计,您也不会更改此设计。无论如何,是的,每个内核都有自己的获取/解码/执行管道,其中解码阶段将每条 x86 指令解码为通常一个但有时是多个内部微操作。
    猜你喜欢
    • 1970-01-01
    • 2019-10-19
    • 1970-01-01
    • 1970-01-01
    • 2014-10-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-04-12
    相关资源
    最近更新 更多