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的反汇编代码,但是它需要"%d %d“的输入,第一个整数应该在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。我发现0x7fffffd56f的值是0--第一个func4调用结束--但是在0x7fffffffd56e的值之后--所以第二个func4调用结束--所有寄存器都变成0,包括eax。
所以我认为第二个数的答案是零,但是(1,0),(2,0),(3,0)总是爆炸炸弹。
你猜我哪里错了,帮我?
发布于 2014-10-11 16:16:18
edi和esi是func4的两个参数。这是根据标准的调用约定,但也可以从这样的事实推断,这些寄存器是使用没有初始化,因此它们的值必须来自外部。因此,原型是int func4(int a, int b)。
行+23检查是否a > 0,如果是,则跳转。因此,我们可以很容易地跟踪如果条件为false会发生什么:
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的值;)
https://stackoverflow.com/questions/26315403
复制相似问题