装配 - CMP 未按预期工作

Posted

技术标签:

【中文标题】装配 - CMP 未按预期工作【英文标题】:Assembly - CMP not working as expected 【发布时间】:2015-03-03 22:47:25 【问题描述】:

我是汇编代码的新手,我正在使用 gdb 编写具有以下内容的代码:

=> 0x080485ee <+132>:   cmp    %eax,0x80498d4(,%ebx,4)
   0x080485f5 <+139>:   je     0x80485fc <main+146>
   0x080485f7 <+141>:   call   0x8048540 <bomb>

我在该行用断点停止了它并输入了这些 gdb 命令:

(gdb) print $eax
$10 = 134519000
(gdb) print 0x80498d8
$11 = 134519000
(gdb) print $ebx
$12 = 1

据我了解,cmp 指令应该比较 %eax 和 0x80498d4 + (%ebx * 4) 的值,它们是相等的,所以代码应该设置零标志并触发 je 跳转到 main+146 on下一行。但是当我单步执行代码时它不会跳转:

(gdb) stepi 2
   0x080485ee <+132>:   cmp    %eax,0x80498d4(,%ebx,4)
   0x080485f5 <+139>:   je     0x80485fc <main+146>
=> 0x080485f7 <+141>:   call   0x8048540 <bomb>

有人可以帮我理解为什么没有设置零标志并且 je 没有跳转到 main+146 吗?

【问题讨论】:

(我知道你可能不知道这一点,但其他人可能知道)Wot 语法! 0x80498d4(,%ebx,4) 是否确实转换为更正确格式的 [0x80498d4+4*ebx] 这是内存引用,不是立即数,所以你需要使用x命令而不是p,或者自己取消引用指针。 【参考方案1】:

总结

您没有将内存访问转换为正确的 C 表达式以在 GDB 中进行评估。应该是*(int*)(0x80498d4 + $ebx*4)

说明

指令问题是cmp %eax,0x80498d4(,%ebx,4),我们分解一下将0x80498d4(,%ebx,4)部分翻译成C的步骤:

为位移创建一个 GDB 便利变量以节省一些输入:

set variable $d = 0x80498d4

将Displacement + Index*Scale寻址方式转化为地址:

set variable $addr = $d + $ebx*4

取消引用地址。这就是你所缺少的:

set variable $v = *(int*)$addr

以上三个步骤相当于:set variable $v = *(int*)($d + $ebx*4)。因此:

将内存中的值与 EAX 进行比较:

p $eax == $v

EAX 设置为内存中的值以实现跳转:

set variable $eax = $v

【讨论】:

【参考方案2】:

如果我反编译这个汇编代码,我会得到这样的 C 代码:

if (p!=q[i])
  bomb();

其中 p 是 EAX 中保存的值,q 似乎是一个数组的基地址,其元素每个有 4 个字节,即这个基地址 0x80498d4,而 i 是 EBX 中保存的值,用作所述的索引数组。

但您希望上述表达式的行为如下:

if (p != &q[i])  /* or (p != q+i)
  bomb();

这对我来说更有意义:EAX 中的值显然是一个地址(一个指针),所以应该与另一个指针进行比较,它恰好是 q[i] 的地址(实际上,q[ 1] 因为 EBX=1) 具有相同的值,所以要么 q 是一个指针数组,要么原始的 C 代码应该像我写的第二个代码一样。

无论哪种方式,您编写的汇编代码都会将寄存器与内存值进行比较。事实上,唯一返回在这样的表达式(常量 + 寄存器 * 标度)中计算的值而不访问内存的汇编指令是 LEA 指令。所有其他人都使用这些表达式将有效地址计算为 LEA,然后使用该地址访问内存。

【讨论】:

以上是关于装配 - CMP 未按预期工作的主要内容,如果未能解决你的问题,请参考以下文章

navigationController?.navigationBar.isUserInteractionEnabled 未按预期工作

$() 函数未按预期工作

libgdx ScissorStack 未按预期工作

UICollectionViewLayout 未按预期工作

CollapsingToolbarLayout 未按预期工作

返回ObjectsAsFaults 未按预期工作