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

Assembly CPU中的直接数操作数是如何工作的?,assembly,x86,risc,Assembly,X86,Risc,举个例子:x86_64 CPU读取128位指令 据我所知,这是x86处理器中经常发生的事情。 否则,例如,无法将64位数字添加到64位寄存器。对于数字>64,操作码将采用几位+64位 我想知道的是指令中的位限制是什么,以及如果指令大于位数据总线,如何读取指令。 此外,我还知道大多数RISC CPU使用固定大小的指令,所以如果直接传递数字操作数,指令的大小是否会增加一倍 x86_64 CPU读取128位指令 这不会发生,最大指令大小定义为15字节。您可以构造更长的指令,但它们将无效 不需要16个字

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

据我所知,这是x86处理器中经常发生的事情。 否则,例如,无法将64位数字添加到64位寄存器。对于数字>64,操作码将采用几位+64位

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

x86_64 CPU读取128位指令

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

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

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

我怀疑这个问题的部分原因是一个接一个地通过数据总线的指令的心理图像,这对于MIPS之类的系统来说是很好的,但是对于没有对齐要求的可变长度指令,就像x86中一样,你就是做不到这一点-无论你选择什么类型的块,它可能是,也可能是直接切断了一些指令。因此,从最简单的角度来看,解码是一个带缓冲区的状态机,解码第一条指令并将其从缓冲区中删除,在有空间时填充更多字节,当然现在更复杂了

x86_64 CPU读取128位指令

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

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

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


我怀疑这个问题的部分原因是一个接一个地通过数据总线的指令的心理图像,这对于MIPS之类的系统来说是很好的,但是对于没有对齐要求的可变长度指令,就像x86中一样,你就是做不到这一点-无论你选择什么类型的块,它可能是,也可能是直接切断了一些指令。因此,从最简单的角度来看,解码是一个带缓冲区的状态机,解码第一条指令并将其从缓冲区中删除,在有空间时填充更多字节。当然,现在更复杂了。

顺便说一句,嵌入指令中的操作数数据称为即时数据

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

例如,8086必须处理比其16位数据总线更宽的指令编码,而不需要任何一级缓存来隐藏这种效果

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

因此,CPU只需要一个与允许的最大指令(不包括前缀)一样大的缓冲区。这是,这正是这个房间的大小

直到解码器看到整个指令为止,这是一种简化:8086分别解码前缀,并将它们作为修饰符记住。8086缺少后期CPU的15字节最大总insn长度限制,因此您可以

像Intel P6和SnB系列这样的现代CPU从一级I-cache获取至少16B块的代码,并实际并行解码多条指令@哈罗德的回答很好地涵盖了你问题的其余部分

有关现代x86 CPU如何工作的详细信息,请参见TagWiki中的、和其他链接

此外,David Kanter的SandyBridge著作中还详细介绍了该微体系结构系列的前端。 顺便说一句,操作数da 嵌入到指令中的ta称为即时数据

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

例如,8086必须处理比其16位数据总线更宽的指令编码,而不需要任何一级缓存来隐藏这种效果

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

因此,CPU只需要一个与允许的最大指令(不包括前缀)一样大的缓冲区。这是,这正是这个房间的大小

直到解码器看到整个指令为止,这是一种简化:8086分别解码前缀,并将它们作为修饰符记住。8086缺少后期CPU的15字节最大总insn长度限制,因此您可以

像Intel P6和SnB系列这样的现代CPU从一级I-cache获取至少16B块的代码,并实际并行解码多条指令@哈罗德的回答很好地涵盖了你问题的其余部分

有关现代x86 CPU如何工作的详细信息,请参见TagWiki中的、和其他链接

此外,David Kanter的SandyBridge著作中还详细介绍了该微体系结构系列的前端。

在具有固定字指令大小的RISC上,通常没有加载任何立即数的指令,只加载其中的一部分,如果无法使用这种立即数,则完全立即数由多条指令构建,从而可以在单个加载中对其进行编码。在x86上,指令大小不是固定的,并且指令长度与需要的一样长:movabs rax,0x1234567889ABCDEF0=48 B8 F0 DE BC 9A 78 56 34 12=10字节每个movabs rax,nn有10B,即使在使用0立即数加载时,因此,即使在x86上,每个操作码/操作数的指令大小也是固定的。每个指令的编码都在手册中。英特尔官方PDF的HTML摘录非常方便:。另请参阅有关x86的其他链接。了解Ped7g很好。我对手册很熟悉,只是找不到一个直接的anwser。在具有固定字指令大小的RISC上,通常没有加载任何立即数的指令,只有部分指令,如果不能使用这样的立即数,则完全立即数由多个指令构建,因此可以在单个加载中对其进行编码。在x86上,指令大小不是固定的,并且指令长度与需要的一样长:movabs rax,0x1234567889ABCDEF0=48 B8 F0 DE BC 9A 78 56 34 12=10字节每个movabs rax,nn有10B,即使在使用0立即数加载时,因此,即使在x86上,每个操作码/操作数的指令大小也是固定的。每个指令的编码都在手册中。英特尔官方PDF的HTML摘录非常方便:。另请参阅有关x86的其他链接。了解Ped7g很好。我对手册很熟悉,只是找不到一个直接的anwser。如果我从你的帖子中正确理解的话,x86 CPU有一个单独的“单元”,它获取指令并解码指令,将其转换为微代码并将其提供给处理核心?我已经了解到,多核CPU需要这样的东西来分离工作负载,但单核也需要这样做?@RabbitBones22:这个图是单核的前端。每个核心都有自己的获取/解码硬件,以及自己的专用一级I-cache。这里没有任何东西与多核有关,如果您将Sandybridge扩展为单核设计,则不会更改此设计。无论如何,是的,每个核心都有自己的获取/解码/执行管道,其中解码阶段将每个x86指令解码为通常为一个但有时为多个内部微操作。如果我从您的帖子中正确理解,x86 CPU有一个单独的“单元”,用于获取指令和解码指令,将其转换为微代码并将其提供给处理核心?我已经了解到,多核CPU需要这样的东西来分离工作负载,但单核也需要这样做?@RabbitBones22:这个图是单核的前端。每个核心都有自己的获取/解码硬件,以及自己的专用一级I-cache。这里没有任何东西与多核有关,如果您将Sandybridge扩展为单核设计,则不会更改此设计。无论如何,是的,每个内核都有自己的获取/解码/执行管道,其中解码阶段将每个x86指令解码为通常一个但有时是多个内部微操作。