事实上,传统的 x86 操作码允许选择操作数大小(有时作为特定指令编码,有时通过前缀字节)和寄存器编号选择位。对于寄存器选择,指令编码中总是有三位。这允许总共有八个寄存器。
原来有四个,16bit的AX/BX/BP/SP,8bit的AL/AH/BL/BH。
再添加两个得到 CX/DX 加上 CL/CH/DL/DH。没有更多的 8 位寄存器,但在 16 位的寄存器选择中仍有两个未使用的值。
这在英特尔架构的另一个版本中由索引 regs DI/SI 提供。
完成后,他们已经用尽了 3 个寄存器选择位(并且无法为 SI/DI/BP/SP 提供 8 位寄存器)。
因此,AMD64 64 位模式设法使寄存器集翻倍的方式是使用前缀字节(“使用新的 regs”-前缀),类似于传统 x86 代码在 16 位和 32 位操作之间选择的方式。同样的方法用于提供“传统上”没有的 8 位寄存器,即SP/BP/SI/DI。
为了说明,例如,请参阅以下指令编码:
0: 00 c0 add %al,%al
2: 00 c1 add %al,%cl
4: 00 c2 add %al,%dl
6: 00 c3 add %al,%bl
8: 00 c4 add %al,%ah
a: 00 c5 add %al,%ch
c: 00 c6 add %al,%dh
e: 00 c7 add %al,%bh
10: 40 00 c4 add %al,%spl
13: 40 00 c5 add %al,%bpl
16: 40 00 c6 add %al,%sil
19: 40 00 c7 add %al,%dil
并且,对于 [16bit / 64bit] / 32bit,并排,因为它是如此说明性:
0 : [66/48] 01 c0 add %?ax,%?ax
2/3 : [66/48] 01 c1 add %?ax,%?cx
4/6 : [66/48] 01 c2 add %?ax,%?dx
6/9 : [66/48] 01 c3 add %?ax,%?bx
8/c : [66/48] 01 c4 add %?ax,%?sp
a/f : [66/48] 01 c5 add %?ax,%?bp
c/12: [66/48] 01 c6 add %?ax,%?si
e/15: [66/48] 01 c7 add %?ax,%?di
前缀 0x66 标记 16 位操作,0x48 是 64 位操作的前缀字节之一(如果您的目标和/或源是“新”高之一-编号的寄存器)。
回到你原来的问题,如何访问高位;好吧,较新的 CPU 具有用于此目的的 SSE 指令;向量寄存器的每个 8/16/32/64 位字段都可以通过例如单独访问shuffle 指令,事实上,Intel / AMD 现在在他们的优化库中提供的许多字符串操作代码不再使用普通的 CPU 寄存器,而是使用向量寄存器。如果您需要较大值的上/下半部分(或其他部分)之间对称,请使用向量寄存器。