如果我在x86AT&T语法中省略了比例因子和索引寻址模式,会发生什么?

我是组装新手,我正在从头开始编程学习它。在第 41 页和第 42 页,该书讨论了索引寻址模式。

内存地址引用的一般形式是:
ADDRESS_OR_OFFSET(%BASE_OR_OFFSET,%INDEX,MULTIPLIER)
所有字段都是可选的。要计算地址,只需执行以下计算:
FINAL ADDRESS = ADDRESS_OR_OFFSET + %BASE_OR_OFFSET + MULTIPLIER * %INDEX
ADDRESS_OR_OFFSET 和 MULTIPLIER 必须都是常量,而另外两个必须是寄存器。如果任何部分被遗漏,它只是在等式中用零代替。

所以我决定稍微玩一下这个。我写了下面的一段代码:

.code32
.section .data
str:
    .ascii "Hello world"

.section .text
.global _start
_start:
    movl $2, %ecx       # The index register.
    mov str(, %ecx, ), %bl
    movl $1, %eax
    int $0x80

我希望得到 72(H 的 ASCII 代码)作为程序的退出结果,因为没有任何乘数(根据这本书,应该用零代替)。但令人惊讶的是,我得到了 108(l 的 ASCII 代码)。我认为这可能是.ascii一回事,并试图查看是否可以使用不同的数据类型获得不同的结果。我得到了相同的结果.byte

我尝试使用 AT&T 语法在 x86 程序集中查找索引寻址模式,但找不到任何有用的信息(可能是因为我不知道要搜索什么)。

有什么我遗漏的或者是书中的错误吗?鉴于我是该领域的新手,如果您详细说明,我真的很感激。

回答

如果任何部分被遗漏,它只是在等式中用零代替。

这本书的一般规则对于比例因子不是很准确。1如果省略,则默认比例因子。

x86 索引缩放在机器代码中用作 2 位移位计数。
也就是说ASM默认为一个移位计数<< 0但86 ASM源代码的语法(包括AT&T)使用乘法器代替移位计数来表示这一点,i << 0i * 1

如果不需要索引,则需要在寻址模式中省略索引寄存器的提及。


请注意,默认值是汇编程序/语法的属性,在这种情况下是 AT&T,而不是 x86 本身的属性。机器代码中不能有“默认值”——没有办法在一个字节中省略位,它们必须是 0 或 1。你要么有一个包含所有字段的 SIB 字节(scale-index-base),或者你没有(由 ModRM 字节表示)在这种情况下根本没有索引。

有一个 SIB 编码意味着没有索引,因此在机器代码中,您仍然可以拥有一个根本没有索引的 SIB 字节,但您不会将其描述为乘数为零。

一些反汇编程序将该编码表示为 index = %eiz,例如 in nopl 0(%eax, %eiz, 1)以显示有一个 SIB 字节但没有索引,但通常您只会在 NOPS 中看到它。当需要使用无索引的 SIB进行编码时(%esp),它会简化为。)


x86 机器码有多种语法。尽管我所知道的所有人都同意没有比例仅意味着 shift=0,例如[str + eax + ecx]在英特尔语法中;通常,如果大于 1,则选择第一个寄存器作为基址,选择第二个作为索引。

当然,在英特尔语法中,要强制 ECX 成为没有基址寄存器的索引,您需要使用[str + ecx*1]故意在 SIB 编码上浪费一个字节。
[str + ecx]在英特尔是 AT&T str(%ecx)


还相关:

  • 关于 [base + index*scale + disp] 的几个问题
  • 引用内存位置的内容。(x86 寻址模式)
  • https://stackoverflow.com/tags/att/info

以上是如果我在x86AT&amp;T语法中省略了比例因子和索引寻址模式,会发生什么?的全部内容。
THE END
分享
二维码
< <上一篇
下一篇>>