关于x64架构中16位寄存器的REX前缀及0x66前缀的技术疑问
关于REX前缀与0x66前缀的疑问
背景
文档中定义的REX前缀位结构如下:
REX Bits: |7|6|5|4|3|2|1|0| |0|1|0|0|W|R|X|B| W bit = 操作数大小,1表示64位,0表示传统模式(取决于操作码) R bit = 将ModR/M寄存器字段扩展为4位,0选择rax-rsi,1选择r8-r15 X bit = 扩展SIB的'index'字段,作用与R类似,针对SIB字节(内存操作数) B bit = 扩展ModR/M的r/m或'base'字段,或SIB字段。
我理解**legacy(传统模式)**指的是32位模式;也明确所有REX字节均以0100开头。
通过汇编实验得到以下结果:
$ echo 'mov %al, %al' | as -al -o /dev/null - | tail -1 1 0000 88C0 mov %al,%al $ echo 'mov %ax, %ax' | as -al -o /dev/null - | tail -1 1 0000 6689C0 mov %ax,%ax $ echo 'mov %eax, %eax' | as -al -o /dev/null - | tail -1 1 0000 89C0 mov %eax,%eax $ echo 'mov %rax, %rax' | as -al -o /dev/null - | tail -1 1 0000 4889C0 mov %rax,%rax
疑问
- 针对
%ax的0x66是REX前缀吗?该字节是否有其他名称? 0x66的二进制是0110 0110,不符合REX前缀以0100开头的规则,这是怎么回事?- 这是否意味着我必须翻转第三位来设置16位模式寄存器?
解答
0x66不是REX前缀,它的正式名称是操作数大小前缀(Operand Size Override Prefix),属于x86架构早于AMD64(x86-64)就存在的传统前缀。- 你说得没错,REX前缀的高位4位固定是
0100(对应十六进制0x40~0x4F范围),0x66的二进制结构和REX前缀完全无关,二者是两套独立的前缀机制:REX是专门为64位模式设计的扩展前缀,而0x66是用来临时修改操作数大小的传统前缀。 - 不需要翻转任何位。在x86-64模式下,默认操作数大小是32位,当你要使用16位操作数(比如
%ax这类16位寄存器)时,就需要通过0x66前缀来覆盖默认的操作数大小规则。这和REX前缀的作用完全不同:REX前缀是用来启用64位操作数或扩展寄存器(r8~r15)的寻址,而0x66是用来在64位模式下临时切换回16位操作数模式。
内容的提问来源于stack exchange,提问作者ton
相关产品推荐
相关产品推荐

