CSAPP Bomb phase_4:递归

 

查询地址 :0x804a1f3

所以要输入两个参数

 

综合分析:

  1. 首先,整个函数的输入是两个数字,调用的func4的函数是一个递归函数。
  2. 通过phase_4后面比较返回值和19,第二个参数和19的大小,不相等则爆炸,推出递归函数的返回值是19,第二个参数是19。
  3. 通过调用前的传参,可以判断三个参数依次是:V1(输入的第一个数)、0、14
  4. 分析func4,结合我上面写的注释,可以总结该递归函数的原理:
    int func4(int v1, int x1, int x2)
    
    {
    
          int result = x1+((x2–x1)+(x2–x1)>>31)/2;
    
          if(v1 < result)
    
              return result + fun4(v1, x1, result-1);
    
          if(v1 > result)
    
              return result + fun4(v1, result+1, x2);
    
          else
    
              return result;
    
       }
  5. 最后返回值要为19,并且此时递归结束的条件是结果等于输入的第一个数v1,根据递归关系,可以推出第一个数是4

测试结果:

08048c83 <func4>:
 8048c83:	55                   	push   %ebp
 8048c84:	89 e5                	mov    %esp,%ebp  开辟栈帧
 8048c86:	56                   	push   %esi     
 8048c87:	53                   	push   %ebx    因为要用到这两个寄存器,被调用者保存现场
 8048c88:	8b 55 08             	mov    0x8(%ebp),%edx  ebp+8第一个参数给edx,即输入的第一个数,这里记为v1
 8048c8b:	8b 4d 0c             	mov    0xc(%ebp),%ecx ebp+12第二个参数给ecx,记为x1
 8048c8e:	8b 75 10             	mov    0x10(%ebp),%esi ebp+16第三个参数给esi,记为x2
 8048c91:	89 f0                	mov    %esi,%eax   eax = x2(值传给eax,这里用=表示)
 8048c93:	29 c8                	sub    %ecx,%eax   eax = x2 – x1
 8048c95:	89 c3                	mov    %eax,%ebx   ebx = eax = x2 – x1
 8048c97:	c1 eb 1f             	shr    $0x1f,%ebx  ebx>>31 =(x2 – x1)>>31逻辑右移
 8048c9a:	01 d8                	add    %ebx,%eax   eax = (x2–x1)+(x2–x1)>>31
 8048c9c:	d1 f8                	sar    %eax         eax/=2   算数右移
 8048c9e:	8d 1c 08             	lea    (%eax,%ecx,1),%ebx ebx=eax+ecx, 即此时ebx为x1+((x2–x1)+(x2–x1)>>31)/2
 8048ca1:	39 d3                	cmp    %edx,%ebx   比较ebx和edx大小,即上式和第一个输入值比较
 8048ca3:	7e 15                	jle    8048cba <func4+0x37> ebx <= v1则跳转
 8048ca5:	83 ec 04             	sub    $0x4,%esp   以下部分不跳转,即ebx > v1
 8048ca8:	8d 43 ff             	lea    -0x1(%ebx),%eax  ebx-1传给eax
 8048cab:	50                   	push   %eax   传参,第三个参数是此次运算结果ebx-1
 8048cac:	51                   	push   %ecx   第二个参数是x1
 8048cad:	52                   	push   %edx   第一个参数仍是输入的第一个数v1
 8048cae:	e8 d0 ff ff ff       	call   8048c83 <func4>  递归调用
 8048cb3:	83 c4 10             	add    $0x10,%esp
 8048cb6:	01 d8                	add    %ebx,%eax  eax += ebx本次调用返回值为本次的运算结果ebx和递归调用函数的返回值eax的和
 8048cb8:	eb 19                	jmp    8048cd3 <func4+0x50> 执行完跳转,结束
 8048cba:	89 d8                	mov    %ebx,%eax    eax = ebx
 8048cbc:	39 d3                	cmp    %edx,%ebx    如果ebx>=v1,则跳转,因为上面判断过ebx<=v1,所以和这个地方大于等于结合起来,跳转条件是ebx=v1,递归结束
 8048cbe:	7d 13                	jge    8048cd3 <func4+0x50> ebx=v1跳转结束
 8048cc0:	83 ec 04             	sub    $0x4,%esp    以下部分不跳转,即ebx < v1
 8048cc3:	56                   	push   %esi        传参,第三个参数是x2
 8048cc4:	8d 43 01             	lea    0x1(%ebx),%eax  eax = ebx + 1
 8048cc7:	50                   	push   %eax         第二个参数是ebx + 1
 8048cc8:	52                   	push   %edx          第一个参数是V1
 8048cc9:	e8 b5 ff ff ff       	call   8048c83 <func4>
 8048cce:	83 c4 10             	add    $0x10,%esp
 8048cd1:	01 d8                	add    %ebx,%eax    eax += ebx 同上
 8048cd3:	8d 65 f8             	lea    -0x8(%ebp),%esp
 8048cd6:	5b                   	pop    %ebx
 8048cd7:	5e                   	pop    %esi
 8048cd8:	5d                   	pop    %ebp  函数调用结束,恢复现场
 8048cd9:	c3                   	ret    


08048cda <phase_4>:
 8048cda:	55                   	push   %ebp
 8048cdb:	89 e5                	mov    %esp,%ebp   开辟栈帧
 8048cdd:	83 ec 18             	sub    $0x18,%esp   分配0x18即24个字节的空间
 8048ce0:	65 a1 14 00 00 00    	mov    %gs:0x14,%eax  堆栈金丝雀
 8048ce6:	89 45 f4             	mov    %eax,-0xc(%ebp)
 8048ce9:	31 c0                	xor    %eax,%eax
 8048ceb:	8d 45 f0             	lea    -0x10(%ebp),%eax  ebp-16的值传给eax
 8048cee:	50                   	push   %eax
 8048cef:	8d 45 ec             	lea    -0x14(%ebp),%eax  ebp-20的值传给eax
 8048cf2:	50                   	push   %eax
 8048cf3:	68 f3 a1 04 08       	push   $0x804a1f3   通过gdb查出输入两个数
 8048cf8:	ff 75 08             	pushl  0x8(%ebp)    
 8048cfb:	e8 10 fb ff ff       	call   8048810 <__isoc99_sscanf@plt>过程调用,8048870为被调用过程起始点指令地址
 8048d00:	83 c4 10             	add    $0x10,%esp  esp下移,开辟16个字节的空间
 8048d03:	83 f8 02             	cmp    $0x2,%eax  判断立即数2和eax的值是否相等
 8048d06:	75 06                	jne    8048d0e <phase_4+0x34> 不等则爆炸
 8048d08:	83 7d ec 0e          	cmpl   $0xe,-0x14(%ebp)  第一个数需要小于等于20
 8048d0c:	76 05                	jbe    8048d13 <phase_4+0x39>  否则爆炸
 8048d0e:	e8 ed 03 00 00       	call   8049100 <explode_bomb> 
 8048d13:	83 ec 04             	sub    $0x4,%esp  
 8048d16:	6a 0e                	push   $0xe    函数传参,第三个参数是14
 8048d18:	6a 00                	push   $0x0    第二个参数是0
 8048d1a:	ff 75 ec             	pushl  -0x14(%ebp)  第一个参数是输入的第一个数
 8048d1d:	e8 61 ff ff ff       	call   8048c83 <func4>  函数调用
 8048d22:	83 c4 10             	add    $0x10,%esp
 8048d25:	83 f8 13             	cmp    $0x13,%eax   比较19和返回值的大小(返回值默认在eax中)
 8048d28:	75 06                	jne    8048d30 <phase_4+0x56> 不等则爆炸
 8048d2a:	83 7d f0 13          	cmpl   $0x13,-0x10(%ebp) 比较19和第二个参数的大小
 8048d2e:	74 05                	je     8048d35 <phase_4+0x5b>等于则不爆炸,可以推出第二个参数是19
 8048d30:	e8 cb 03 00 00       	call   8049100 <explode_bomb>
 8048d35:	8b 45 f4             	mov    -0xc(%ebp),%eax  
 8048d38:	65 33 05 14 00 00 00 	xor    %gs:0x14,%eax  金丝雀判断堆栈是否受损
 8048d3f:	74 05                	je     8048d46 <phase_4+0x6c>
 8048d41:	e8 4a fa ff ff       	call   8048790 <__stack_chk_fail@plt>
 8048d46:	c9                   	leave  
 8048d47:	c3                   	ret  

  • 3
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值