我已经阅读了从头开始编程一书中的以下内容:
处理器有许多不同的访问数据的方式,称为 寻址方式。最简单的模式是立即模式,其中 要访问的数据嵌入在指令本身中。例如, 如果我们想要将寄存器初始化为0,而不是给出 计算机一个地址从0读取,我们会立即指定 模式,并给它数字0。
在寄存器寻址模式中,指令包含a 注册访问,而不是内存位置。剩下的 模式将处理地址。
这是否意味着例如指令mov eax, 123
处于立即模式和寄存器寻址模式?
答案 0 :(得分:7)
这不是具有特定寻址模式的整个指令,它是每个操作数分开的。 在mov eax, 123
示例中,您要说源是一个立即操作数,目标是一个寄存器操作数。
或者您可以说该指令的机器代码将使用mov r, imm32
encoding of mov
,如果您想谈论整个指令所采用的形式。 (还有一个mov r/m, imm32
形式的mov
,但它更长,所以如果目的地实际上是内存,那么一个好的汇编器只会选择它。
但是,当其中一个操作数是寄存器时,为方便起见,可以说“如果需要,指令使用[base+index]
寻址模式”。但实际上它是你所谈论的内存操作数,而不是整个指令。特别是如果你将寄存器和立即数视为“寻址模式”,即使没有涉及存储器地址。
此外,通常当人们说“寻址模式”时,他们谈论的是内存地址。从技术上讲,在x86中,大多数指令都有一个寄存器和一个寄存器/内存操作数,因此add eax, ecx
和add eax, [ecx]
之间的差异只是我认为mod/rm
字节中的1位(跟在操作码之后) )。
某些指令有两个内存操作数。例如,push qword [rdi + rax*8]
显式从[rdi + rax*8]
加载并隐式存储到[rsp]
。另一个示例是字符串说明movs
和cmps
,它们隐式使用[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
以及x86标记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 0x123
和m8, imm8
寻址模式的说明,例如m16, imm16
或mov word ptr [123], 567
。)
当然,你可能也认为指令是add byte ptr [123], 45
,而mov
和al
是bl
指令的两个参数。
因此,如果指令mov al, bl
是具有寻址模式的指令,那么它取决于你的论证"暗示" (=无操作数)或"注册到注册"。