x86 AT&T 寻址模式中基址寄存器的省略

Posted

技术标签:

【中文标题】x86 AT&T 寻址模式中基址寄存器的省略【英文标题】:Omission of base register in x86 AT&T addressing mode 【发布时间】:2018-04-22 09:08:13 【问题描述】:

我正在尝试解码 intel IA32 x86 cmp 命令的语法。

有问题的命令是

cmp 0x804a38(,%ebx,4), %eax

我对发生的事情有一个粗略的估计 - 然后从eax 中减去(ebx *4 的内容)+0x0804a38,然后设置条件代码。

但是,我知道我错了,因为之后的跳转命令没有执行 - 它的 je

我在这里做错了什么?是因为 cmp 缺少参数吗?

【问题讨论】:

欢迎来到 SO。请查看此处了解如何改进您的问题(格式化、校对、提供代码等):***.com/help/how-to-ask 你要和 eax 比较的是 (0x804a38 + ebx * 4) 的内容,对吧?你的说法是模棱两可的。 从你的问题的措辞听起来你完全错过了这样一个事实,即第一个参数是内存引用,即0x80...+ebx*4 被计算为内存地址,然后从中加载 4 字节值内存地址,并与eax比较。在 Intel 语法中,指令看起来像这样:cmp eax,[ebx*4+0x804a38](在 Intel 语法中,内存引用在方括号中,而不是普通括号中,并且语法很宽松,即 [0x804a38+ebx*4] == [ebx*4+0x804a38],大多数汇编程序甚至会为您计算简单的表达式,比如[ebx*4+label+15] 【参考方案1】:

在 Intel x86 机器指令的 SIB(scale-index-base)表示法中允许省略基址寄存器。

来自Intel SDM,第 2 卷,表 2-3:

表格下方突出显示的行、列、值和注释指定了相应的 SIB 字节值。

但是,我知道我错了,因为之后的跳转命令没有执行

cmp 指令本身已正确编码。这是其他地方的问题:要么是它的内存参数导致错误,要么是下面的 je 指令(你没有显示),或者你只是误解了代码执行的结果。

【讨论】:

【参考方案2】:

你的意思是je 不会跳,会掉下来吗?这意味着它执行但发现条件为假。当内存中的 4 个字节与 EAX 中的 4 个字节不匹配时会发生这种情况,因此cmp 不会设置 ZF。

je执行的唯一方法是如果cmp 导致了分段错误或其他原因,因此程序在到达cmp 之后的指令之前就死了。

是的,您正在正确解码 AT&T 寻址模式语法,它是一个没有基址寄存器的缩放索引,只是一个 disp32。)cmp 没有缺少参数,寻址模式缺少基础(这是完全正常的)。 %ebx 被用作静态双字数组的缩放索引

Referencing the contents of a memory location. (x86 addressing modes)。 (我不确定 AT&T 语法寻址模式是否有很好的链接,但机器可以编码的内容是固定的;AT&T 和 Intel 语法都可以表达机器可以执行的每种寻址模式。)

【讨论】:

我记得至少在一段时间之前(~2009)GNU 的工具链在一个缺失的基础上使用了eiz:***.com/questions/2553517/what-is-register-eiz @GrigoryRechistov:根据我的经验,它仅在使用 SIB 字节的寻址模式中将其用作缺少 index 的占位符,但不适用于 base=%esp没有索引,其中 SIB 字节仍然是强制性的。即告诉您寻址模式在不需要时被填充,例如作为长 NOP 的一部分。 哎呀,确实不是 base 而是 index!谢谢 @GrigoryRechistov:另外,我刚刚检查过,GAS 不接受mov (%ebx, %eiz, 4), %eax 作为输入。无论如何,OP的代码可能是反汇编输出(给定数字位移),但我认为%eiz(/%riz?)对于binutils来说是一个仅输出的东西。 @PeterCordes 是的,但是(%eax,,1) 已经足够明确了。不知道为什么需要额外的%eiz

以上是关于x86 AT&T 寻址模式中基址寄存器的省略的主要内容,如果未能解决你的问题,请参考以下文章

X86 AT&T常用寄存器及其操作指令

基于转换的索引模式到间接寻址模式(x86 汇编)

AT&T汇编语言及其寻址方式

MOV AX,ES:[BX] 指令中,源操作数字段的寻址方式是啥?

x86中没有段的直接寻址?

(计算机组成原理)第四章指令系统-第二节3:数据寻址之偏移寻址(基址寻址变址寻址和相对寻址)