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

时间:2016-10-10 09:26:25

标签: assembly x86 risc

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

据我所知,这只是x86处理器中发生的事情。 否则,不可能例如将64位数字添加到64位寄存器(操作码将占用几位+ 64位,数字> 64)。

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

2 个答案:

答案 0 :(得分:6)

  

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那样的对齐要求你不能这样做 - 不管你选择什么样的块,它可能(并且很可能)通过一些指令切割。因此,在最简单的视图中,解码是具有缓冲区的状态机,解码第一条指令并将其从缓冲区中删除,在有空间时填充更多字节(当然现在它更复杂)。

答案 1 :(得分:4)

BTW,嵌入到指令中的操作数数据称为“立即”数据。

这不是现代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文章详细介绍了该微体系结构系列的前端。
article