炸弹实验室阶段_4

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的反汇编代码。 而且我不确定我是否正确理解了这个function。

我没有在这里写入phase_4的反汇编代码,但它需要“%d%d”input,第一个整数应该在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)总是爆炸炸弹。

你猜你猜我在哪里错了,帮忙?

ediesifunc4的两个参数。 这是根据标准的调用约定,也可以从这些寄存器没有初始化的情况下推导出来,所以它们的值必须来自外部。 因此,原型是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 .. +55recursion地调用func4 。 行+60将两个调用的结果一起添加,行+64添加b 。 所以我们有:

 return func4(a - 1, b) + func4(a - 2, b) + b; 

从这里你可以计算任何input的返回值。

当然,如果你被允许使用debugging器,你可以让代码运行,看看eax的价值是什么;)