x86 cpu有什么样的地址指令?

时间:2018-11-15 17:51:08

标签: x86 cpu computer-science cpu-architecture instruction-set

我了解了一个地址,两个地址和三个地址指令,但是现在我想知道x86使用哪种地址指令?

1 个答案:

答案 0 :(得分:5)

x86是一台寄存器机,使用[rdi + rax*4]之类的寻址方式,其中一条指令的最多1个操作数可以是显式存储器地址,而不是寄存器。 (尽管有些指令可以有2个内存操作数,但其中一个或两个都是隐式的,尽管:What x86 instructions take two (or more) memory operands?

典型的x86整数指令有2个操作数,两个操作数都是显式的,例如add eax, edx ,它执行eax+=edx

旧版x87 FP代码在x87堆栈中使用1-operand指令,例如faddp st1 ,其中x87堆栈的顶部(st0)是隐式操作数。 SSE2是x86-64的基线,因此不再被广泛使用。

现代FP代码使用SSE / SSE2 2操作数指令,例如addsd xmm0,xmm1或3操作数AVX编码,例如vaddsd xmm2, xmm0, xmm1

有x86指令带有0、1、2、3甚至4个显式操作数。

有多种指令格式,但是显式的reg / memory操作数通常在操作码字节之后的ModR / M字节中进行编码。它具有3个字段:

    r / m操作数的
  • 2位模式(注册直接reg,间接注册[reg],[reg + disp8],[reg+disp32])。带位移位的模式表示这些字节跟随ModR / M字节。
  • 3位r / m字段(用于该操作数或存储器寻址模式的寄存器,一个转义码,表示ModRM后有一个Scale / Index / Base字节,可以为Scaled-Index寻址模式编码) r / m操作数)。有关特殊情况/转义码的详细信息,请参见rbp not allowed as SIB base?
  • 3位reg字段,始终是一个寄存器。

大多数指令至少有两种编码可用:reg /内存目标或reg /内存源。如果您想要的操作数都是寄存器,则可以使用add r/m32, r32add r32, r/m32之一的操作码。

公用指令还具有用于立即源格式的其他操作码,但是通常它们将ModR / M中的reg字段用作额外的操作码位,因此您仍然只能获得2个操作数,例如add eax, 123。例外情况是imul的立即数加上286,例如imul eax, [rdi + rbx*4], 12345。它没有与其他立即指令共享编码空间,而是在操作码隐含的ModR / M plus 中具有寄存器dst和r / m源。

某些单操作数指令使用与将reg字段用作额外的操作码位相同的技巧,但没有立即数。例如neg r/m32not r/m32inc r/m32shl / shr /旋转将编码转换为隐式1(而不是cl或即时)。因此,很遗憾,您无法复制和移动(直到BMI2)。

有些特殊情况下的编码可以提高代码密度,例如push rax / push rdx的单字节编码会将reg字段打包到操作码字节的低3位中。在16/32位模式下,inc / dec任何寄存器的一字节编码。但是在64位模式下,这些0x4?代码用作REX前缀,以扩展regr/m字段以提供16个体系结构寄存器。


还有一些带有某些或所有隐式操作数的指令,例如movsb,它将一个字节从[rsi]复制到[rdi],并且可以与rep前缀重复rcx次。

或者mul ecxedx:eax = eax * ecx。一个显式源操作数,一个隐式源和2个隐式目标寄存器。 div / idiv相似。

具有至少1个显式reg / mem操作数的指令对其使用ModR / M编码,但是具有零显式操作数(如movsbcdq)的指令没有ModR / M字节。他们只是有操作码。有些指令根本没有like mfence,甚至没有隐含的操作数。

不能通过ModR / M来立即发送操作数,只能通过操作码本身来发出信号,因此push imm32 or push imm8拥有自己的操作码。隐式目标([rsp]处的内存,RSP本身已更新为rsp-=8)。


LEA是一种变通方法,它可以使x86 3操作数移位加法,例如lea eax, [rdi + rdi*2 + 123]可以在一条指令中完成eax = rdi*3 + 123。请参见Using LEA on values that aren't addresses / pointers?。目标寄存器在ModR / M的reg字段中编码,而两个源寄存器在寻址模式下编码。 (涉及到一个SIB字节,该字节的存在通过ModR / M字节使用编码来表示,否则将表示base = RSP。)


VEX前缀(由AVX引入)提供3个操作数的指令,例如bzhi eax, [rsi], edxvaddps ymm0, ymm1, [rsi](对于许多指令,第二个源是可选的内存,但对于某些人来说,这是第一个来源。)

第三个操作数被编码为2或3字节的VEX前缀。


有3个操作数的非VEX指令,例如vpblendvb xmm1, xmm2/m128, <XMM0>之类的SSE4.1变量混合,其中XMM0是使用该寄存器的隐式操作数。

AVX版本使其具有非破坏性(在VEX前缀中编码有单独的目标),使混合控制操作数显式(编码为1字节的高4位)即时)。 这为我们提供了一个包含4个显式操作数VPBLENDVB xmm1, xmm2, xmm3/m128, xmm4的指令。


x86非常狂野,并且已经扩展了许多次,但是典型的整数代码主要使用2操作数指令,并附带大量LEA来保存指令。