CPU 中的直接数字操作数如何工作?

How do direct number operands in a CPU work?

举个例子:一个x86_64CPU读取一个128位的指令

据我了解,这主要发生在x86处理器中。 否则不可能将 64 位数字添加到 64 位寄存器(操作码将需要几位 + 64 位用于数字 > 64)。

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

a x86_64 CPU reading a 128 bit instruction

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

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

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

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

顺便说一句,直接嵌入到指令中的操作数数据称为 "immediate" 数据。


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

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

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

所以 CPU 只需要一个与最大允许指令(不包括前缀)一样大的缓冲区。那是 6 bytes for 8086, and this is exactly the size of .

"until the decoder sees a whole instruction" 是一种简化:8086 单独解码前缀,"remembers" 它们作为修饰符。 8086 缺少后来 CPU 的 15 字节最大总 insn 长度限制,因此您可以 fill a 64k CS segment with repeated prefixes on one instruction).


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

另请参阅 Agner Fog's microarch guide, and other links from the 标记维基,详细了解现代 x86 CPU 的工作原理。

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