08048b51 <phase_2>:
8048b51: 55 push %ebp
8048b52: 89 e5 mov %esp,%ebp
8048b54: 56 push %esi
8048b55: 53 push %ebx因为会用到这些寄存器,所以被调用者要保存现场
8048b56: 83 ec 28 sub $0x28,%esp 开辟0x28个字节的空间
8048b59: 65 a1 14 00 00 00 mov %gs:0x14,%eax 堆栈金丝雀,检查栈是否受到修改
8048b5f: 89 45 f4 mov %eax,-0xc(%ebp)
8048b62: 31 c0 xor %eax,%eax
8048b64: 8d 45 dc lea -0x24(%ebp),%eax 猜测-0x24(%ebp)放的是第一个参数,-0x20(%ebp)放第二个参数,以此类推
8048b67: 50 push %eax
8048b68: ff 75 08 pushl 0x8(%ebp)
8048b6b: e8 b8 05 00 00 call 8049128 <read_six_numbers>读入6个数
8048b70: 83 c4 10 add $0x10,%esp 开辟16个字节的空间
8048b73: 83 7d dc 00 cmpl $0x0,-0x24(%ebp) 第一个参数不为0就爆炸
8048b77: 75 06 jne 8048b7f <phase_2+0x2e>
8048b79: 83 7d e0 01 cmpl $0x1,-0x20(%ebp)第二个参数为1才不爆炸
8048b7d: 74 05 je 8048b84 <phase_2+0x33>
8048b7f: e8 7c 05 00 00 call 8049100 <explode_bomb>
8048b84: 8d 5d dc lea -0x24(%ebp),%ebx 第一个参数给ebx
8048b87: 8d 75 ec lea -0x14(%ebp),%esi 第六个参数给esi
8048b8a: 8b 43 04 mov 0x4(%ebx),%eax ebx+4给eax,即ebx的下一个参数
8048b8d: 03 03 add (%ebx),%eax eax += ebx
8048b8f: 39 43 08 cmp %eax,0x8(%ebx) 现在的eax(两个参数相加的和)和ebx下下个参数相等才不爆炸,即0x8(%ebx) = 0x4(%ebx) + ebx
8048b92: 74 05 je 8048b99 <phase_2+0x48>
8048b94: e8 67 05 00 00 call 8049100 <explode_bomb>
8048b99: 83 c3 04 add $0x4,%ebx ebx + 4,相当于切换到下个参数
8048b9c: 39 f3 cmp %esi,%ebx 如果还没到对后一个,就循环执行
8048b9e: 75 ea jne 8048b8a <phase_2+0x39>
8048ba0: 8b 45 f4 mov -0xc(%ebp),%eax
8048ba3: 65 33 05 14 00 00 00 xor %gs:0x14,%eax
8048baa: 74 05 je 8048bb1 <phase_2+0x60>
8048bac: e8 df fb ff ff call 8048790 <__stack_chk_fail@plt>
8048bb1: 8d 65 f8 lea -0x8(%ebp),%esp
8048bb4: 5b pop %ebx
8048bb5: 5e pop %esi
8048bb6: 5d pop %ebp恢复现场
8048bb7: c3 ret
综合分析:
- 首先,整个函数的输入是六个数字
- 通过ebp加减一个数,来表示是第几个参数。根据炸弹爆炸或不爆炸的条件,首先可以确定第一个和第二个参数的值分别是0和1
- 下面就开始循环,第一个参数给ebx, 第六个参数给esi,ebx也通过加4,实现i++。每次计算完后,比较ebx和esi,相等则跳出
- 0x8(%ebx) = 0x4(%ebx) + ebx才不爆炸,相当于a[i]=a[i-1]+a[i-2],一个数可以由它前面两个数相加得到,这符合斐波那契数列的规律
- 通过计算可以得到这六个数是0 1 1 2 3 5
结果测试: