我一直在努力了解一些我在课堂上必须做的实验室的汇编代码,并且希望由那些能指出我正确方向的人来解释。 代码如下:
0x080488bb <+0>: push %esi
0x080488bc <+1>: push %ebx
0x080488bd <+2>: sub $0x34,%esp
0x080488c0 <+5>: mov $0x0,%esi
0x080488c5 <+10>: mov $0x0,%ebx
0x080488ca <+15>: lea 0x1c(%esp,%ebx,4),%eax
0x080488ce <+19>: mov %eax,0x4(%esp)
0x080488d2 <+23>: movl $0x8048c8d,(%esp)
0x080488d9 <+30>: call 0x80484e0 <__isoc99_scanf@plt>
0x080488de <+35>: test %eax,%eax
0x080488e0 <+37>: jns 0x80488ee <phase_3_of_5+51>
0x080488e2 <+39>: movl $0x3,(%esp)
0x080488e9 <+46>: call 0x80487c2 <explode>
0x080488ee <+51>: mov 0x1c(%esp,%ebx,4),%eax
0x080488f2 <+55>: add %eax,%esi
0x080488f4 <+57>: add $0x1,%ebx
0x080488f7 <+60>: cmp $0x5,%ebx
0x080488fa <+63>: jne 0x80488ca <phase_3_of_5+15>
0x080488fc <+65>: cmp $0x64,%esi
0x080488ff <+68>: je 0x804890d <phase_3_of_5+82>
0x08048901 <+70>: movl $0x3,(%esp)
0x08048908 <+77>: call 0x80487c2 <explode>
0x0804890d <+82>: add $0x34,%esp
0x08048910 <+85>: pop %ebx
0x08048911 <+86>: pop %esi
0x08048912 <+87>: ret
根据我收集的内容,此功能将接受两个输入(来自两个推送)。 __isoc99_scanf @ plt将一系列输入保存为字符串。
第一部分我很困惑的是&#34;测试%eax,%eax&#34;这本质上是比较eax的价值吗?我查看了堆栈溢出中的另一个线程,其中有一个有类似问题的人,其中一个解决方案说%eax必须为零才能使该语句为真。
如果上述陈述为真,我们继续前进至+51。 +51表示存储在0x1c中的eax = esp + ebx * 4。然后我们添加eax + esi并将其存储在esi中。然后我们将1添加到ebx。然后我们将5与ebx进行比较。如果不相等则返回+15。如果它相等则移动到+65,将64与esi进行比较。如果它们相等则功能结束。
如果我的解释错误,或者您认为可以澄清的部分,请告诉我。
编辑:我的主要目标是弄清楚我应该输入什么,以便程序在不调用爆炸函数的情况下完成。
我已将其缩小为两个输入,ebx必须为5才能继续通过一个部分。 esi必须是64才能继续下一部分。我唯一的问题是esi依赖于eax的价值,我不知道。
4和48不是正确的答案,有什么建议吗?
谢谢!
答案 0 :(得分:3)
test %eax,%eax
向and
注册eax
。此操作的唯一实际效果是设置CPU标志。下一条指令是jns 0x80488ee <phase_3_of_5+51>
。如果由于前一个test
指令而未设置符号位,则跳转到+51 。
基本上,如果eax
的高位为0,则它采用分支。如果高位为1,则它会通过。
答案 1 :(得分:0)
From what I gathered this function will take two inputs(from both the pushes)
如果你的意思是前两行,那些只是将寄存器esi
和ebx
保存在堆栈上,因为调用约定说它们必须保留。最后的代码将恢复它们。这与此函数占用的参数数量或scanf
将处理的数量无关。
scanf
获得2个参数,第一个是格式字符串,位于内存中的地址0x8048c8d
。我想如果你查看它的价值,你会发现它只是一个"%d"
。第二个参数是堆栈上的局部变量的地址,这将接收输入数字。 (它实际上是数组的一个元素,但这并不重要。)
然后检查scanf
的返回值以查看是否EOF
或发生了错误。
行+51
然后加载已转换的输入数字并将其添加到esi
,然后递增ebx
并循环回读取另一个数字(如果它小于5)。这意味着,代码一个接一个地读取五个数字,并总结它们。
最后,将总和与0x64
进行比较,其中十进制为100。
TL; DR:您需要输入总和为100的任意5个数字。