在不是所有指令长度都一样的架构中,计算机如何知道要读取多少个字节作为一条指令呢?例如在Intel IA-32中,有些指令是4个字节,有些是8个字节, 那么它如何知道是否读取4个或8个字节呢?是这样的,第一条在计算机开机时被读取的指令具有已知的大小,并且每个指令都包含下一条指令的大小。
为了每个周期解码多条指令,实际上有两种策略:并行进行推测性解码或等待长度被确定并使用该信息将指令流解析成单独的指令。对于像IBM的zArchitecture(S/360后代)这样的ISA,长度在16位包中是通过第一个包中的两个位轻松确定的,因此等待长度被确定更加合理。(RISC V稍微复杂的长度指示机制仍然对非推测性解码友好。) 对于类似于microMIPS或Thumb2的编码,它们只有两个由主操作码确定的长度,而不同长度指令的编码差异显著,因此可能更倾向于使用非推测性解码,特别是考虑到可能窄的解码和注重能效,尽管在小型解码宽度下进行一些推测也是合理的。
对于x86,AMD用的一种策略是在指令缓存中使用标记位来指示哪个字节结束了一条指令,以避免过多的解码能量消耗。有了这些标记位,可以很容易地找到每条指令的起始位置。这种技术的缺点是会增加指令缓存未命中的延迟(需要预解码指令),并且仍然需要解码器检查长度是否正确(例如,在跳转到先前为指令中间的位置时)。在Pascal的回答上进行扩展,在x86架构上,第一个字节指示正在解码的指令属于哪个类别:
1字节长度,这意味着它已经被读取并且可以进一步处理,
1字节操作码和几个字节(所谓的ModRM和SIB字节),用于指示后面跟随的操作数(寄存器、内存地址)及其操作数。
指令前缀,其中:
REP
,锁定语义-LOCK
)REX
和VEX
前缀分别用于实现64位和矢量指令,但仅在64位模式下解释为此类指令。由于其格式,REX
涵盖了原始指令集中大量现有指令,这些指令在64位中不再可用(我想VEX
前缀也是如此,尽管我对此一无所知)。它的字段指示以下指令操作数大小,或访问仅在64位上可用的额外寄存器(R8
到R15
和XMM8
到XMM15
)。VAX 是另一种体系结构(从70年代末到80年代末很流行),采用类似的原理支持可变长度指令。对于其最初的迭代版本,指令可能是按顺序解码的,因此一个指令的结束指示着下一个字节上的新指令的开始。正如您所知,制造这些产品的公司还生产了它的极端相反,即 RISC Alpha CPU,它成为了当时最快的CPU之一(如果不是最快的),具有固定长度的指令,这显然是为了应对当时蓬勃发展的流水线、超标量技术的要求而做出的选择。