我正在阅读Programming from the ground up by Jonathan Bartlett。作者讨论了存储器寻址模式,并指出存储器地址引用的一般形式是:
ADDRESS_OR_OFFSET (%BASE_OR_OFFSET, %INDEX, MULTIPLIER)
由此计算出的最终地址:
FINAL_ADDRESS = ADDRESS_OR_OFFSET + %BASE_OR_OFFSET + MULTIPLIER * %INDEX
。
还指出,如果遗漏了任何部分,则在等式中仅将其替换为零。 ADDRESS_OR_OFFSET
和MULTIPLIER
必须是常量,而其他元素必须是寄存器。这些似乎是指定的唯一通用规则。
到目前为止,太好了。
然后作者讨论间接寻址模式,并举例说明:
movl (%eax), %ebx
将存储在eax
寄存器中的地址的值移到ebx
寄存器中。
要使其正常工作,应将(%eax)
解释为0(%eax,0,0)
,而不是0(0,%eax,0)
。是否有其他规则可以强制这种解释?
答案 0 :(得分:2)
书中的解释不是100%正确。 x86体系结构具有以下32位寻址模式:
$imm immediate result = imm
%reg register result = reg
disp(%reg) indirect result = MEM[disp + reg]
disp direct result = MEM[disp]
disp(%base, %index, %scale) SIB result = MEM[disp + base + index * scale]
在SIB(比例/索引/基数)和间接寻址模式中,disp
可以省略0字节位移。在SIB寻址模式下,base
和index
可以省去0标度和0索引;规模实际上不能被忽略。请注意,当我说“ leave out”时,只剩下值。 例如,(,,1)
的意思是“ SIB操作数,无位移,无基数,无索引和小数位数。”
在64位模式下,还可以使用rip
相对寻址模式:
disp(%rip) rip relative result = MEM[disp + rip]
此寻址模式对于编写与位置无关的代码很有用。
16位模式具有不同的寻址模式,但是它们并不重要,因此我不再赘述。
因此,对于您的示例:这很容易理解,因为它实际上是一种间接寻址模式,而不是一种以eax
作为寄存器且没有编号的 SIB 寻址模式。位移。