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 寻址模式中基址寄存器的省略的主要内容,如果未能解决你的问题,请参考以下文章