CSAPP Bomb phase_6:链表指针结构

 

查询0x804c13c得出这是一个链表

综合分析:

  1. 首先这个函数是有六个东西(从后面得知,这是六个结构体组成的链表)
  2. 接着遇到了一个双层循环,判断是否在1到6之间,若不是则爆炸,从后面得知,这是链表节点的编号。同时用两层循环实现6个数中两两比较,若相等就爆炸,得出这六个数是互不相同的。
  3. 接着就是另一个循环,循环中有一个地址,通过对地址的查询,可以看出这是六个结构体组成的链表。这个循环也是双层的,通过把节点的值(即第一个成员)作为循环次数,在链表头的基础上每次循环都加8,这样如果值大的话,得到的结果也大,这是节点值大小的反映。这样我们就相当于对于节点进行排列,这个顺序是从小到大的,然后就依次压入栈中保存。
  4. 通过下一个模块,让节点按照大小顺序重新连接,最后一个的next指向0
  5. 最后是一个验证,如果每两个节点,前面的不小于等于后面的就爆炸,即对得到的顺序是否是升序排列做一个检查

测试结果:

08048dc6 <phase_6>:
 8048dc6:	55                   	push   %ebp
 8048dc7:	89 e5                	mov    %esp,%ebp 
 8048dc9:	56                   	push   %esi
 8048dca:	53                   	push   %ebx    被调用者保存现场
 8048dcb:	83 ec 48             	sub    $0x48,%esp  开辟空间
 8048dce:	65 a1 14 00 00 00    	mov    %gs:0x14,%eax  堆栈金丝雀
 8048dd4:	89 45 f4             	mov    %eax,-0xc(%ebp)
 8048dd7:	31 c0                	xor    %eax,%eax    
 8048dd9:	8d 45 c4             	lea    -0x3c(%ebp),%eax 
 8048ddc:	50                   	push   %eax    eax压栈
 8048ddd:	ff 75 08             	pushl  0x8(%ebp)
 8048de0:	e8 43 03 00 00       	call   8049128 <read_six_numbers>读取六个数
 8048de5:	83 c4 10             	add    $0x10,%esp   开辟空间

 8048de8:	be 00 00 00 00       	mov    $0x0,%esi  esi赋初值为0,通过后面得知这是计数作用,相当于i=0
 8048ded:	8b 44 b5 c4          	mov    -0x3c(%ebp,%esi,4),%eax 通过esi的值寻址,将存储的数给eax  
 8048df1:	83 e8 01             	sub    $0x1,%eax  该数值减一
 8048df4:	83 f8 05             	cmp    $0x5,%eax  与5进行比较
 8048df7:	76 05                	jbe    8048dfe <phase_6+0x38> 减完后的数小于等于5则继续,否则爆炸,即该数需要<=6
 8048df9:	e8 02 03 00 00       	call   8049100 <explode_bomb>
 8048dfe:	83 c6 01             	add    $0x1,%esi esi+=1, 即i++
 8048e01:	83 fe 06             	cmp    $0x6,%esi 与6比较
 8048e04:	74 33                	je     8048e39 <phase_6+0x73>等于6时跳转,即i<6,在这里控制外层循环的结束
 8048e06:	89 f3                	mov    %esi,%ebx ebx相当于j,控制内层循环,这里ebx=esi,即j = i
 8048e08:	8b 44 9d c4          	mov    -0x3c(%ebp,%ebx,4),%eax 通过ebx控制偏移找到存储的一个数             内层循环
 8048e0c:	39 44 b5 c0          	cmp    %eax,-0x40(%ebp,%esi,4)此数与下一个数比较
 8048e10:	75 05                	jne    8048e17 <phase_6+0x51> 不相等继续执行
 8048e12:	e8 e9 02 00 00       	call   8049100 <explode_bomb> 相等就爆炸
 8048e17:	83 c3 01             	add    $0x1,%ebx j++
 8048e1a:	83 fb 05             	cmp    $0x5,%ebx  j<=5
 8048e1d:	7e e9                	jle    8048e08 <phase_6+0x42> 跳转到上面内层循环
 8048e1f:	eb cc                	jmp    8048ded <phase_6+0x27> 跳转到外层循环


 8048e21:	8b 52 08             	mov    0x8(%edx),%edx edx即这个数的值加8
 8048e24:	83 c0 01             	add    $0x1,%eax  eax++,eax控制该循环
 8048e27:	39 c8                	cmp    %ecx,%eax 比较ecx和eax是否相等
 8048e29:	75 f6                	jne    8048e21 <phase_6+0x5b> 不等则循环,这个小循环是由结构体中数值的大小决定循环次数,如果数越大,那么edx的之最后加出来就越大,这样可以反映每个节点的值的大小情况

 8048e2b:	89 54 b5 dc          	mov    %edx,-0x24(%ebp,%esi,4) 将edx的值存入栈中,不过存入的就是该节点值的大小的反映(不是原值),按顺序压入的
 8048e2f:	83 c3 01             	add    $0x1,%ebx ebx++
 8048e32:	83 fb 06             	cmp    $0x6,%ebx ebx控制循环,即循环6次
 8048e35:	75 07                	jne    8048e3e <phase_6+0x78> 不等则循环
 8048e37:	eb 1c                	jmp    8048e55 <phase_6+0x8f> 结束该一大部分

 8048e39:	bb 00 00 00 00       	mov    $0x0,%ebx  ebx=0 
 8048e3e:	89 de                	mov    %ebx,%esi  esi=sbi
 8048e40:	8b 4c 9d c4          	mov    -0x3c(%ebp,%ebx,4),%ecx 结构体中的值给ecx
 8048e44:	b8 01 00 00 00       	mov    $0x1,%eax   eax=1
 8048e49:	ba 3c c1 04 08       	mov    $0x804c13c,%edx  查出这是一个链表,这步将链表的头给edx
 8048e4e:	83 f9 01             	cmp    $0x1,%ecx  ecx与1比较
 8048e51:	7f ce                	jg     8048e21 <phase_6+0x5b> ecx大于1,跳转
 8048e53:	eb d6                	jmp    8048e2b <phase_6+0x65> ecx小于等于1,跳转


 8048e55:	8b 5d dc             	mov    -0x24(%ebp),%ebx ebx等于上面存入的第一个节点,即n[0]
 8048e58:	8d 45 dc             	lea    -0x24(%ebp),%eax eax=&n[0]
 8048e5b:	8d 75 f0             	lea    -0x10(%ebp),%esi esi=&n[6]
 8048e5e:	89 d9                	mov    %ebx,%ecx  ecx=ebx=n[0]
 8048e60:	8b 50 04             	mov    0x4(%eax),%edx edx=eax+4
 8048e63:	89 51 08             	mov    %edx,0x8(%ecx) edx的值放入ecx的下一个
 8048e66:	83 c0 04             	add    $0x4,%eax eax+4
 8048e69:	89 d1                	mov    %edx,%ecx ecx=edx
 8048e6b:	39 f0                	cmp    %esi,%eax 如果到了最后一个,就退出
 8048e6d:	75 f1                	jne    8048e60 <phase_6+0x9a>
 8048e6f:	c7 42 08 00 00 00 00 	movl   $0x0,0x8(%edx) 

 8048e76:	be 05 00 00 00       	mov    $0x5,%esi esi置为5,控制循环6次
 8048e7b:	8b 43 08             	mov    0x8(%ebx),%eax ebx存的是地址,eax=ebx下一个节点的指针
 8048e7e:	8b 00                	mov    (%eax),%eax 结构体中的值保存入eax中
 8048e80:	39 03                	cmp    %eax,(%ebx) ebx和eax比较,即前面一个和后面一个比较
 8048e82:	7e 05                	jle    8048e89 <phase_6+0xc3> 第一个小于等于第二个就不爆炸,说明前面的要小于等于后面的,即升序排列
 8048e84:	e8 77 02 00 00       	call   8049100 <explode_bomb>
 8048e89:	8b 5b 08             	mov    0x8(%ebx),%ebx ebx变成后面一个节点的地址
 8048e8c:	83 ee 01             	sub    $0x1,%esi  esi-1
 8048e8f:	75 ea                	jne    8048e7b <phase_6+0xb5> 判断esi的ZF标志位,即,esi不为0时跳转
 8048e91:	8b 45 f4             	mov    -0xc(%ebp),%eax
 8048e94:	65 33 05 14 00 00 00 	xor    %gs:0x14,%eax
 8048e9b:	74 05                	je     8048ea2 <phase_6+0xdc>
 8048e9d:	e8 ee f8 ff ff       	call   8048790 <__stack_chk_fail@plt>
 8048ea2:	8d 65 f8             	lea    -0x8(%ebp),%esp
 8048ea5:	5b                   	pop    %ebx
 8048ea6:	5e                   	pop    %esi
 8048ea7:	5d                   	pop    %ebp
 8048ea8:	c3                   	ret

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值