一条指令的诞生与“宿命”


第一部分:指令的“诞生”

1. 顶层:“鸡生蛋还是蛋生鸡”的设计

在设计一套全新的指令集时,设计师首先面临一个类似“鸡生蛋还是蛋生鸡”的哲学抉择,这个抉择决定了指令长度的基本形态:

2. 具体因素:构成指令“胖瘦”的“零部件”

无论采用何种哲学,一条指令的长度都是其内部各个“零部件”长度的总和。

第二部分:指令的“解码”

CPU(特别是处理变长指令的CISC CPU)是如何“测量”出一条指令的长度的。

CPU事先并不知道指令有多长,它依赖于硬件**指令译码器(Instruction Decoder)**进行“走一步,看一步”的串行解码。

  1. 取指与缓冲:CPU从内存中一次性抓取一块数据(包含多条指令)到内部的指令缓冲区。

  2. 前缀解析:译码器从缓冲区的当前指针位置开始,逐字节检查是否存在可选的前缀(如x86的66H, REX等),每识别一个前缀,指针就后移一字节。

  3. 操作码解码(最关键一步):译码器读取到第一个非前缀字节,即操作码。根据这个操作码的值,译码器通过内部的硬连线逻辑(像查字典一样)瞬间得知该指令的“模板”——它后面是否需要ModR/M字节?需要多长的立即数?

  4. 后续字段解析:根据操作码提供的“情报”,译码器继续向后读取并解析ModR/M、SIB、地址偏移量、立即数等后续字节。每解析一部分,它就更清楚指令还剩下多少未读部分。

  5. 确定边界:当一条指令所需的所有部分都被“吃掉”后,译码器就知道了这条指令的总长度。当前指针指向的位置,就是下一条指令的开始。这个“拆盲盒”的过程至此完成一轮。


第三部分:执行中的安全与保障