3.4.3 解读
现在回到列表 3-3 的示例。我们思考一下指令的解码。CPU 中负责解码的指令解码器会一直将命令从老系统的 CISC 指令翻译为更方便的 RISC 指令。流水线允许最多同时执行六条指令。
为了达成上面这些效果,寄存器的概念实际上是一个虚拟概念。在微代码执行期间,解码器从一个物理寄存器的“银行”选择一个可用的寄存器。一条大指令一结束,效果就立刻对上层程序员可见了:某些物理寄存器的值可能被拷贝到了,现在被赋值到的这一个,让我们叫它 rax。
数据之间的相互依赖会拖累流水线,降低性能。最差的场合可能同一个寄存器会被几条连续的指令先后读取和修改(想想 rflags 寄存器)。
如果修改 eax 需要保证寄存器的高位原封不动,那么就会引入多余的依赖,即当前指令与任何其它修改过 rax 或者 rax 一部分的指令会构成依赖。在每次写 eax 时,如果我们忽略掉高 32 位,我们就可以消灭这种依赖,因为我们不再在乎之前 rax 或者 rax 的一部分的值。
这种行为是在寄存器涨到 64 位的时期才被引入的,为了和以前的行为兼容,不会影响寄存器的低位操作。如果不做这种兼容的话可能一些老的二进制程序在赋值的时候就没法工作了,例如,bl 寄存器在被修改时会修改整个 ebx 寄存器,这在 64 位寄存器还没被引入时显然是不正确的。