微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

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

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

我是组装新手,正在从 Programming from the Ground Up 那里学习。这本书在第 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\0"

.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移位计数但 x86 asm 源代码语法(包括 AT&T)使用乘数而不是移位计数来表示这一点,并且i << 0i * 1

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


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

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

一些反汇编程序将该编码表示为 index = %eiz,例如在 nopl 0(%eax,%eiz,1) 中显示有一个 SIB 字节但没有索引,但通常您只会看到 NOPS。当那个 SIB-with-no-index is necessary to encode (%esp) 时,它被简化为那个。)


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

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


还相关:

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。