Dump of assembler code for function func4
<+0>: mov %rbx,-0x18(%rsp)
<+5>: mov %rbp, -0x10(%rsp)
<+10>: mov %r12,-0x8(%rsp)
<+15>: sub $0x18,%rsp
<+19>: mov %edi,%ebx
<+21>: mov %esi,%ebp
<+23>: test %edi, %edi
<+25>: jg 0x400fb2<func4+34>
<+27>: mov $0x0,%ebp
<+32>: jmp 0x400fd2<func4+66>
<+34> cmp $0x1, %edi
<+37>: je 0x400fd2<func4+66>
<+39>: lea -0x1(%rbx),%edi
<+42>: callq 0x400f90 <func4>
<+47>: mov %eax,%r12d
<+50>: lea -0x2(%rbx),%edi
<+53>: mov %ebp,%esi
<+55>: callq 0x400f90 <func4>
<+60>: lea (%r12,%rax,1),%eax
<+64>: add %eax,ebp
<+66>: mov %ebp, %eax
<+68>: mov (%rsp),%rbx
<+72>: mov 0x8(%rsp), %rbp
<+77>: mov 0x10(%rsp),%r12
<+82>: add $0x18,%rsp
<+86>: retq
这是func4的反汇编代码。 而且我不确定我是否正确理解这个功能。
我在这里没有编写phase_4的反汇编代码, 但它需要&#34;%d%d&#34;输入,并且第一整数应该在范围1 <= x <4中。 所以它应该是1,2或3。 寄存器%edi的值最初为7。 在调用func4之后,代码比较0x10(%rsp)和%eax的值 所以我应该知道调用func4后的%eax值。
我想,func4的反汇编代码意味着
put the stack
ebx = edi
ebp = esi
if edi is not zero
if edi is one: then eax=ebp.
rearrange the stack
return.
else: edi = -0x1(rbx)
func4
r12d = eax
edi = -0x2(rbx)
esi = ebp
func4
eax = rax+r12+ebp
rearrange the stack and return.
else
ebp=0
eax=ebp
return
但凭据我的理解,我无法解决它。 例如,如果%rsp的原始地址是0x7fffffffd5a8 那么地址会更小,直到edi的值变为0。 我发现0x7fffffffd56f的值为0 - 并且第一个func4调用结束 - 但是在0x7fffffffd56e的值也为0之后 - 所以第二个func4调用结束 - 并且所有寄存器都变为0,包括eax。
所以我认为第二个数字的答案是零, 但是(1,0),(2,0),(3,0)总是爆炸炸弹。
你猜到我错在哪里并帮忙?
答案 0 :(得分:2)
edi
和esi
是func4
的两个参数。这是根据标准调用约定,但也可以从这些寄存器未经初始化使用的事实推断出来,因此它们的值必须来自外部。因此,原型是int func4(int a, int b)
。
行+23
检查是否a > 0
,如果是,则跳开。因此,如果条件为假,我们可以轻松跟踪发生的情况:
if (a <= 0) return 0;
行+34
正在检查是否为a == 1
,如果是,则返回ebp
的当前值,但已从esi
初始化,这是第二个参数,b
:
if (a == 1) return b;
否则,行+39
.. +55
以递归方式调用func4
。行+60
将两个调用的结果一起添加,行+64
添加b
。所以我们有:
return func4(a - 1, b) + func4(a - 2, b) + b;
由此可以计算任何输入的返回值。
当然,如果您被允许使用调试器,您可以让代码运行并查看eax
的值是什么;)