Phase 6
解题思路
1 2 3 4 5 6 7 8
| 8048db4: 56 push %esi 8048db5: 53 push %ebx 8048db6: 83 ec 44 sub $0x44,%esp 8048db9: 8d 44 24 10 lea 0x10(%esp),%eax 8048dbd: 89 44 24 04 mov %eax,0x4(%esp) 8048dc1: 8b 44 24 50 mov 0x50(%esp),%eax 8048dc5: 89 04 24 mov %eax,(%esp) 8048dc8: e8 4f 03 00 00 call 804911c <read_six_numbers>
|
前面部分和之前几题都一样,初始化栈操作。到8048dc8处,调用了<read_six_numbers>函数,推断此题需要输入六个数字。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| 8048dcd: be 00 00 00 00 mov $0x0,%esi 8048dd2: 8b 44 b4 10 mov 0x10(%esp,%esi,4),%eax 8048dd6: 83 e8 01 sub $0x1,%eax 8048dd9: 83 f8 05 cmp $0x5,%eax 8048ddc: 76 05 jbe 8048de3 <phase_6+0x2f> 8048dde: e8 12 03 00 00 call 80490f5 <explode_bomb> 8048de3: 83 c6 01 add $0x1,%esi 8048de6: 83 fe 06 cmp $0x6,%esi 8048de9: 75 07 jne 8048df2 <phase_6+0x3e> 8048deb: bb 00 00 00 00 mov $0x0,%ebx 8048df0: eb 38 jmp 8048e2a <phase_6+0x76> 8048df2: 89 f3 mov %esi,%ebx 8048df4: 8b 44 9c 10 mov 0x10(%esp,%ebx,4),%eax 8048df8: 39 44 b4 0c cmp %eax,0xc(%esp,%esi,4) 8048dfc: 75 05 jne 8048e03 <phase_6+0x4f> 8048dfe: e8 f2 02 00 00 call 80490f5 <explode_bomb> 8048e03: 83 c3 01 add $0x1,%ebx 8048e06: 83 fb 05 cmp $0x5,%ebx 8048e09: 7e e9 jle 8048df4 <phase_6+0x40> 8048e0b: eb c5 jmp 8048dd2 <phase_6+0x1e>
|
对%esi赋值0,分析完后面可以看出%esi是一个计数器,接下来进入一个循环,从8048dd2到8048e0b的内容是第一个循环,目的是循环读取输入的数字,要求小于等于6,并且任意两个数字不相同。第一个循环结束后从8048df0跳入8048e2a,将计数器清零。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| 8048e0d: 8b 52 08 mov 0x8(%edx),%edx 8048e10: 83 c0 01 add $0x1,%eax 8048e13: 39 c8 cmp %ecx,%eax 8048e15: 75 f6 jne 8048e0d <phase_6+0x59> 8048e17: eb 05 jmp 8048e1e <phase_6+0x6a> 8048e19: ba 3c c1 04 08 mov $0x804c13c,%edx 8048e1e: 89 54 b4 28 mov %edx,0x28(%esp,%esi,4) 8048e22: 83 c3 01 add $0x1,%ebx 8048e25: 83 fb 06 cmp $0x6,%ebx 8048e28: 74 17 je 8048e41 <phase_6+0x8d> 8048e2a: 89 de mov %ebx,%esi 8048e2c: 8b 4c 9c 10 mov 0x10(%esp,%ebx,4),%ecx 8048e30: 83 f9 01 cmp $0x1,%ecx 8048e33: 7e e4 jle 8048e19 <phase_6+0x65> 8048e35: b8 01 00 00 00 mov $0x1,%eax 8048e3a: ba 3c c1 04 08 mov $0x804c13c,%edx 8048e3f: eb cc jmp 8048e0d <phase_6+0x59>
|
在8048e2c处令%ecx=10+%esp+%ebx*4,判断%ecx≦1,不管成不成立,我发现都进行了一个取地址操作,%edx=$0x804c13c,%edx获取完地址值后,继续分析,发现第二个循环目的是将%edx+8位置的值放入esp中,如此循环6次。那就查看一下0x804c13c的内容,再查看0x804c13c+8的值。发现一个是16进制数,一个是另一个地址。顺着给出的另一个地址再次进行查看,+8查看······手动输入,最后一个位置给出0x0,说明结束了。
如此一番查看得到一个线性表,结构是(0xd5,1)->(0x6c,2)->(0x10c,3)->(0x392,4)->(0xf4,5)->(0x307,6)
后面跟着的数字是节点名称。
1 2 3 4 5 6 7 8 9 10 11 12
| 8048e41: 8b 5c 24 28 mov 0x28(%esp),%ebx 8048e45: 8d 44 24 2c lea 0x2c(%esp),%eax 8048e49: 8d 74 24 40 lea 0x40(%esp),%esi 8048e4d: 89 d9 mov %ebx,%ecx 8048e4f: 8b 10 mov (%eax),%edx 8048e51: 89 51 08 mov %edx,0x8(%ecx) 8048e54: 83 c0 04 add $0x4,%eax 8048e57: 39 f0 cmp %esi,%eax 8048e59: 74 04 je 8048e5f <phase_6+0xab> 8048e5b: 89 d1 mov %edx,%ecx 8048e5d: eb f0 jmp 8048e4f <phase_6+0x9b> 8048e5f: c7 42 08 00 00 00 00 movl $0x0,0x8(%edx)
|
这段代码刚好验证之前的推测,取值放值。
1 2 3 4 5 6 7 8 9
| 8048e66: be 05 00 00 00 mov $0x5,%esi 8048e6b: 8b 43 08 mov 0x8(%ebx),%eax 8048e6e: 8b 00 mov (%eax),%eax 8048e70: 39 03 cmp %eax,(%ebx) 8048e72: 7e 05 jle 8048e79 <phase_6+0xc5> 8048e74: e8 7c 02 00 00 call 80490f5 <explode_bomb> 8048e79: 8b 5b 08 mov 0x8(%ebx),%ebx 8048e7c: 83 ee 01 sub $0x1,%esi 8048e7f: 75 ea jne 8048e6b <phase_6+0xb7>
|
这段循环就是将结构体数据域的值按从小到大顺序排列,那我们的输入就应该是排列顺序的节点名称值顺序,进行输入得到
总结
今天用到的汇编指令在之前的几题中都出现过,没有新的内容。虽然没有新的,但这些指令加在一块看起来十分复杂,代码量巨大,逐行分析费了不少时间。在此题中学习了有关线性表的知识,学习到线性表在汇编语言中的表示形式。