一条指令可以同时处于两种寻址模式吗?

时间:2017-07-01 13:59:32

标签: assembly x86 addressing-mode

我已经阅读了从头开始编程一书中的以下内容:

  

处理器有许多不同的访问数据的方式,称为   寻址方式。最简单的模式是立即模式,其中   要访问的数据嵌入在指令本身中。例如,   如果我们想要将寄存器初始化为0,而不是给出   计算机一个地址从0读取,我们会立即指定   模式,并给它数字0。

     

寄存器寻址模式中,指令包含a   注册访问,而不是内存位置。剩下的   模式将处理地址。

这是否意味着例如指令mov eax, 123处于立即模式寄存器寻址模式

2 个答案:

答案 0 :(得分:7)

这不是具有特定寻址模式的整个指令,它是每个操作数分开的。 mov eax, 123示例中,您要说源是一个立即操作数,目标​​是一个寄存器操作数。

或者您可以说该指令的机器代码将使用mov r, imm32 encoding of mov,如果您想谈论整个指令所采用的形式。 (还有一个mov r/m, imm32形式的mov,但它更长,所以如果目的地实际上是内存,那么一个好的汇编器只会选择它。

但是,当其中一个操作数是寄存器时,为方便起见,可以说“如果需要,指令使用[base+index]寻址模式”。但实际上它是你所谈论的内存操作数,而不是整个指令。特别是如果你将寄存器和立即数视为“寻址模式”,即使没有涉及存储器地址。

此外,通常当人们说“寻址模式”时,他们谈论的是内存地址。从技术上讲,在x86中,大多数指令都有一个寄存器和一个寄存器/内存操作数,因此add eax, ecxadd eax, [ecx]之间的差异只是我认为mod/rm字节中的1位(跟在操作码之后) )。

某些指令有两个内存操作数。例如,push qword [rdi + rax*8]显式从[rdi + rax*8]加载并隐式存储到[rsp]。另一个示例是字符串说明movscmps,它们隐式使用[rdi][rsi]

但是没有指令有两个通用的r / m操作数可以让你使用the normal addressing modes的任意选择。因此,x86指令最多只有一个mod / rm字节。

立即操作数是否应该被称为“寻址模式”是有争议的,因为数据不是来自任何地方。这是教学的一部分。此外,指令的立即操作数形式与reg,reg / mem形式具有不同的操作码。

另请注意,大多数可以具有内存源或内存目标的整数指令都有两个操作码:一个用于op r/m, r,另一个用于op r, r/m。 (例如,请参阅the ref manual entry for and以及标记wiki中文档的更多链接。)无论如何,and eax, ecx可以使用两个操作码中的任何一个编码,并且由汇编程序决定挑。这种选择对性能没有影响。

答案 1 :(得分:2)

  

处理器有多种不同的访问方式,称为寻址模式。

这句话谈及"处理器"一般来说,不是某种处理器类型。

我认为这太笼统了,因为你总是会发现这样的句子有例外。实际上,在查看现代CPU时,您会发现比遵循此规则的CPU更多的例外情况。

确实对于"简单"像6800或6502这样的CPU 指令本身有一种寻址模式:

lda $3A

...例如使用"零页"或"直接"寻址方式。

其他CPU确实在一条指令中确实有两种不同的寻址模式。 "移动"以68000的指令为例:

move.w ($123).w, (a3, $4567)

对于 x86 CPU ,更难说:

在6800中,可以与mov al, bl进行比较的指令被命名为tba(没有参数),而mov al, [0x123]被命名为lda $123

所以你可能认为mov al, bl是一个没有参数的指令(隐含的寻址模式 - 因为指令被写为movblal而其他CPU上没有任何操作数)和{ {1}}是一个带有一个内存地址参数的指令(绝对寻址模式 - 因为该指令被写为mov al, [0x123],其他CPU上有一个操作数)。

(原始8086中唯一不允许您这样说的说明似乎是ldal 0x123m8, imm8寻址模式的说明,例如m16, imm16mov word ptr [123], 567 。)

当然,你可能也认为指令是add byte ptr [123], 45,而movalbl指令的两个参数。

因此,如果指令mov al, bl是具有寻址模式的指令,那么它取决于你的论证"暗示" (=无操作数)或"注册到注册"。