并不是整个指令都有一定的寻址模式,而是每个操作数都是单独的。In your mov eax, 123
例如,您可以说源是立即数操作数,目标是寄存器操作数。
或者你可以说该指令的机器代码将使用mov r, imm32的编码mov http://felixcloutier.com/x86/MOV.html,如果你想谈论整个指令所采取的形式。 (还有一个mov r/m, imm32
的形式mov
,但它更长,所以一个好的汇编器只会在目标实际上是内存的情况下选择它)。
然而,当其中一个操作数是寄存器时,为了方便和简洁,您可以说“该指令使用一个[base+index]
如果您愿意的话,可以将其称为“寻址模式”。但实际上您正在谈论的是内存操作数,而不是整个指令。特别是如果您将寄存器和立即数算作“寻址模式”,即使不涉及内存地址。
此外,通常当人们说“寻址模式”时,他们指的是内存地址。从技术上讲,在 x86 中,大多数指令都有一个寄存器和一个寄存器/内存操作数,因此两者之间的区别add eax, ecx
and add eax, [ecx]
我认为只有 1 位mod/rm
字节(位于操作码之后)。
有些指令有两个内存操作数。例如,push qword [rdi + rax*8]
显式加载自[rdi + rax*8]
并隐式存储到[rsp]
。另一个例子是字符串指令movs
and cmps
,其中使用[rdi]
and [rsi]
隐含地。
但是没有指令具有两个通用 r/m 操作数,可以让您任意选择正常寻址模式 https://stackoverflow.com/questions/34058101/referencing-the-contents-of-a-memory-location-x86-addressing-modes。所以一条 x86 指令最多有一个 mod/rm 字节。
立即操作数是否应该被称为“寻址模式”是有争议的,因为数据不是来自任何地方。这是指令的一部分。此外,指令的立即操作数形式具有与 reg、reg/mem 形式不同的操作码。
另请注意,大多数可以具有内存源或内存目标的整数指令都有两个操作码:一个用于op r/m, r
和一个用于op r, r/m
。 (例如,参见参考手册条目and http://felixcloutier.com/x86/AND.html以及更多文档链接x86 /questions/tagged/x86标记维基。)无论如何,and eax, ecx
可以使用这两个操作码中的任何一个进行编码,并且由汇编器来选择。该选择对性能没有影响。