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