深入理解计算机系统(2)——bomblab

我在过程中用到的命令:

名字功能
gdb bomb编译文件
break +函数名设置断点
ni单步调试
si进入子函数的单步调试
i r查看每个寄存器里的值
print *(int*)+地址打印指向地址的整数值
x/s +地址打印指向地址的字符串
print+地址打印指向地址内的数(十进制形式)
x/nw+地址检测从该地址开始的n个四字节值
run sol.txt读取sol.txt文件中的内容作为输入

phase_1

0000000000400ee0 <phase_1>:
  400ee0:	48 83 ec 08          	sub    $0x8,%rsp
  400ee4:	be 00 24 40 00       	mov    $0x402400,%esi
  400ee9:	e8 4a 04 00 00       	callq  401338 <strings_not_equal>
  400eee:	85 c0                	test   %eax,%eax
  400ef0:	74 05                	je     400ef7 <phase_1+0x17>
  400ef2:	e8 43 05 00 00       	callq  40143a <explode_bomb>
  400ef7:	48 83 c4 08          	add    $0x8,%rsp
  400efb:	c3                   	retq   

思路:
test句可知,答案存储在%eax里,因此用命令:

x/s $eax

即可得出答案:

Border relations with Canada have never been better.

phase_2

0000000000400efc <phase_2>:
  400efc:	55                   	push   %rbp
  400efd:	53                   	push   %rbx
  400efe:	48 83 ec 28          	sub    $0x28,%rsp
  400f02:	48 89 e6             	mov    %rsp,%rsi
  400f05:	e8 52 05 00 00       	callq  40145c <read_six_numbers>
  400f0a:	83 3c 24 01          	cmpl   $0x1,(%rsp)//first number
  400f0e:	74 20                	je     400f30 <phase_2+0x34>
  400f10:	e8 25 05 00 00       	callq  40143a <explode_bomb>
  400f15:	eb 19                	jmp    400f30 <phase_2+0x34>
  400f17:	8b 43 fc             	mov    -0x4(%rbx),%eax//pre
  400f1a:	01 c0                	add    %eax,%eax//pre*2
  400f1c:	39 03                	cmp    %eax,(%rbx)
  400f1e:	74 05                	je     400f25 <phase_2+0x29>
  400f20:	e8 15 05 00 00       	callq  40143a <explode_bomb>
  400f25:	48 83 c3 04          	add    $0x4,%rbx//pointer to the next number
  400f29:	48 39 eb             	cmp    %rbp,%rbx//find the end
  400f2c:	75 e9                	jne    400f17 <phase_2+0x1b>
  400f2e:	eb 0c                	jmp    400f3c <phase_2+0x40>
  400f30:	48 8d 5c 24 04       	lea    0x4(%rsp),%rbx//sec
  400f35:	48 8d 6c 24 18       	lea    0x18(%rsp),%rbp//the end of input
  400f3a:	eb db                	jmp    400f17 <phase_2+0x1b>
  400f3c:	48 83 c4 28          	add    $0x28,%rsp
  400f40:	5b                   	pop    %rbx
  400f41:	5d                   	pop    %rbp
  400f42:	c3                   	retq   

思路:
首先从内置函数名<read_six_numbers>可知本题是输入六个数字。存储的首地址从%rsp开始(记住这个,因为后面还会用到这个函数)。

400f0a:	83 3c 24 01          	cmpl   $0x1,(%rsp)//first number

这一句说明第一个数一定是1,否则触发炸弹。跳转之后,将第二个数赋值给%rbx,并且将%rbp定位在输入的最后一个数之后的位置,避免越界。之后的跳转是将得到的第二个数与前一个数的两倍比较,以此类推。因此得到答案:1 2 4 8 16 32

phase_3

0000000000400f43 <phase_3>:
  400f43:	48 83 ec 18          	sub    $0x18,%rsp
  400f47:	48 8d 4c 24 0c       	lea    0xc(%rsp),%rcx
  400f4c:	48 8d 54 24 08       	lea    0x8(%rsp),%rdx
  400f51:	be cf 25 40 00       	mov    $0x4025cf,%esi//the needing format string
  400f56:	b8 00 00 00 00       	mov    $0x0,%eax//the number of input int
  400f5b:	e8 90 fc ff ff       	callq  400bf0 <__isoc99_sscanf@plt>
  400f60:	83 f8 01             	cmp    $0x1,%eax//format fit?
  400f63:	7f 05                	jg     400f6a <phase_3+0x27>
  400f65:	e8 d0 04 00 00       	callq  40143a <explode_bomb>
  400f6a:	83 7c 24 08 07       	cmpl   $0x7,0x8(%rsp)//the first input<7
  400f6f:	77 3c                	ja     400fad <phase_3+0x6a>
  400f71:	8b 44 24 08          	mov    0x8(%rsp),%eax
  400f75:	ff 24 c5 70 24 40 00 	jmpq   *0x402470(,%rax,8)//jump table
  400f7c:	b8 cf 00 00 00       	mov    $0xcf,%eax
  400f81:	eb 3b                	jmp    400fbe <phase_3+0x7b>
  400f83:	b8 c3 02 00 00       	mov    $0x2c3,%eax
  400f88:	eb 34                	jmp    400fbe <phase_3+0x7b>
  400f8a:	b8 00 01 00 00       	mov    $0x100,%eax
  400f8f:	eb 2d                	jmp    400fbe <phase_3+0x7b>
  400f91:	b8 85 01 00 00       	mov    $0x185,%eax
  400f96:	eb 26                	jmp    400fbe <phase_3+0x7b>
  400f98:	b8 ce 00 00 00       	mov    $0xce,%eax
  400f9d:	eb 1f                	jmp    400fbe <phase_3+0x7b>
  400f9f:	b8 aa 02 00 00       	mov    $0x2aa,%eax
  400fa4:	eb 18                	jmp    400fbe <phase_3+0x7b>
  400fa6:	b8 47 01 00 00       	mov    $0x147,%eax
  400fab:	eb 11                	jmp    400fbe <phase_3+0x7b>
  400fad:	e8 88 04 00 00       	callq  40143a <explode_bomb>
  400fb2:	b8 00 00 00 00       	mov    $0x0,%eax
  400fb7:	eb 05                	jmp    400fbe <phase_3+0x7b>
  400fb9:	b8 37 01 00 00       	mov    $0x137,%eax
  400fbe:	3b 44 24 0c          	cmp    0xc(%rsp),%eax//if the second number is right
  400fc2:	74 05                	je     400fc9 <phase_3+0x86>
  400fc4:	e8 71 04 00 00       	callq  40143a <explode_bomb>
  400fc9:	48 83 c4 18          	add    $0x18,%rsp
  400fcd:	c3                   	retq   

思路:
这个题第一眼看上去有些不知从何入手,不过可以找到一个地址常量$0x4025cf,因此不妨先用x/s访问一下,得到字符串 “%d %d”,因此可以猜知这是scanf输入时的字符串,那么也就是要我们输入两个整数了。输入的个数存储在%eax里。

第一个输入存储在0x8(%rsp)里,由跳转得到的语句可知,第一个输入必须<7。

400f75:	ff 24 c5 70 24 40 00 	jmpq   *0x402470(,%rax,8)//jump table

这一句就是明显的跳转表格式了,通过第一个的输入查找对应的值输出即可。
我选择的是:6 682

phase_4

000000000040100c <phase_4>:
  40100c:	48 83 ec 18          	sub    $0x18,%rsp
  401010:	48 8d 4c 24 0c       	lea    0xc(%rsp),%rcx
  401015:	48 8d 54 24 08       	lea    0x8(%rsp),%rdx
  40101a:	be cf 25 40 00       	mov    $0x4025cf,%esi
  40101f:	b8 00 00 00 00       	mov    $0x0,%eax
  401024:	e8 c7 fb ff ff       	callq  400bf0 <__isoc99_sscanf@plt>
  401029:	83 f8 02             	cmp    $0x2,%eax//input two int
  40102c:	75 07                	jne    401035 <phase_4+0x29>
  40102e:	83 7c 24 08 0e       	cmpl   $0xe,0x8(%rsp)//the first number<=14
  401033:	76 05                	jbe    40103a <phase_4+0x2e>
  401035:	e8 00 04 00 00       	callq  40143a <explode_bomb>
  40103a:	ba 0e 00 00 00       	mov    $0xe,%edx
  40103f:	be 00 00 00 00       	mov    $0x0,%esi
  401044:	8b 7c 24 08          	mov    0x8(%rsp),%edi
  401048:	e8 81 ff ff ff       	callq  400fce <func4>
  40104d:	85 c0                	test   %eax,%eax//return 0
  40104f:	75 07                	jne    401058 <phase_4+0x4c>
  401051:	83 7c 24 0c 00       	cmpl   $0x0,0xc(%rsp)
  401056:	74 05                	je     40105d <phase_4+0x51>
  401058:	e8 dd 03 00 00       	callq  40143a <explode_bomb>
  40105d:	48 83 c4 18          	add    $0x18,%rsp
  401061:	c3                   	retq 

思路:
这题依旧使用了sscanf函数,因此同phase_的思路就可以很快的找出本题也是输入两个参数,且第一个参数存储在0x8(%rsp)里。

 40102e:	83 7c 24 08 0e       	cmpl   $0xe,0x8(%rsp)//the first number<=14

本句写出了第一个参数的范围。那么第一个参数确定了之后,第二个参数怎么确定呢?由题目可知,第一个参数传入了寄存器%edi中,作为func4的参数参与计算,func4(x,0)且func4的返回值%eax必须为0,且由:

 401051:	83 7c 24 0c 00       	cmpl   $0x0,0xc(%rsp)

知第二个输入的数也要为0。
那么func4的内容是什么呢?

0000000000400fce <func4>:
  400fce:	48 83 ec 08          	sub    $0x8,%rsp
  400fd2:	89 d0                	mov    %edx,%eax
  400fd4:	29 f0                	sub    %esi,%eax
  400fd6:	89 c1                	mov    %eax,%ecx
  400fd8:	c1 e9 1f             	shr    $0x1f,%ecx
  400fdb:	01 c8                	add    %ecx,%eax
  400fdd:	d1 f8                	sar    %eax
  400fdf:	8d 0c 30             	lea    (%rax,%rsi,1),%ecx//get answer
  400fe2:	39 f9                	cmp    %edi,%ecx//<=7 first para
  400fe4:	7e 0c                	jle    400ff2 <func4+0x24>//key
  400fe6:	8d 51 ff             	lea    -0x1(%rcx),%edx
  400fe9:	e8 e0 ff ff ff       	callq  400fce <func4>
  400fee:	01 c0                	add    %eax,%eax
  400ff0:	eb 15                	jmp    401007 <func4+0x39>
  400ff2:	b8 00 00 00 00       	mov    $0x0,%eax//right way
  400ff7:	39 f9                	cmp    %edi,%ecx
  400ff9:	7d 0c                	jge    401007 <func4+0x39>//>=7
  400ffb:	8d 71 01             	lea    0x1(%rcx),%esi
  400ffe:	e8 cb ff ff ff       	callq  400fce <func4>
  401003:	8d 44 00 01          	lea    0x1(%rax,%rax,1),%eax
  401007:	48 83 c4 08          	add    $0x8,%rsp
  40100b:	c3                   	retq  

从内部结构可以看出这是一个递归函数,我们要找出使返回值为0的输入值,情况当然是越简单越好。
前面的运算:

400fce:	48 83 ec 08          	sub    $0x8,%rsp
400fd2:	89 d0                	mov    %edx,%eax
400fd4:	29 f0                	sub    %esi,%eax
400fd6:	89 c1                	mov    %eax,%ecx
400fd8:	c1 e9 1f             	shr    $0x1f,%ecx
400fdb:	01 c8                	add    %ecx,%eax
400fdd:	d1 f8                	sar    %eax
400fdf:	8d 0c 30             	lea    (%rax,%rsi,1),%ecx//get answer

令人眼花缭乱,不过庆幸的是,似乎与我们输入的值没什么关系,于是我们使用si命令直接进入func4内部,再用print $ecx命令打印出%ecx看看,得到的结果是7。
那么进行第一个比较

400fe2:	39 f9                	cmp    %edi,%ecx//<=7 first para

第一个参数<=7则将eax赋值为0,岂不美哉!于是赶紧向下看,下面还有一个比较

 400ff7:	39 f9                	cmp    %edi,%ecx
 400ff9:	7d 0c                	jge    401007 <func4+0x39>//>=7

综合来看,就是第一个参数=7时就没有复杂递归了,直接返回值为0并退出执行。
故,本题的一个答案为7 0。

phase_5

0000000000401062 <phase_5>:
  401062:	53                   	push   %rbx
  401063:	48 83 ec 20          	sub    $0x20,%rsp
  401067:	48 89 fb             	mov    %rdi,%rbx//the input string
  40106a:	64 48 8b 04 25 28 00 	mov    %fs:0x28,%rax
  401071:	00 00 
  401073:	48 89 44 24 18       	mov    %rax,0x18(%rsp)
  401078:	31 c0                	xor    %eax,%eax
  40107a:	e8 9c 02 00 00       	callq  40131b <string_length>
  40107f:	83 f8 06             	cmp    $0x6,%eax//len=6
  401082:	74 4e                	je     4010d2 <phase_5+0x70>
  401084:	e8 b1 03 00 00       	callq  40143a <explode_bomb>
  401089:	eb 47                	jmp    4010d2 <phase_5+0x70>
  40108b:	0f b6 0c 03          	movzbl (%rbx,%rax,1),%ecx//first ascll
  40108f:	88 0c 24             	mov    %cl,(%rsp)
  401092:	48 8b 14 24          	mov    (%rsp),%rdx//ascll
  401096:	83 e2 0f             	and    $0xf,%edx//lower four bits
  401099:	0f b6 92 b0 24 40 00 	movzbl 0x4024b0(%rdx),%edx
  4010a0:	88 54 04 10          	mov    %dl,0x10(%rsp,%rax,1)//create a new string
  4010a4:	48 83 c0 01          	add    $0x1,%rax//itrator
  4010a8:	48 83 f8 06          	cmp    $0x6,%rax
  4010ac:	75 dd                	jne    40108b <phase_5+0x29>
  4010ae:	c6 44 24 16 00       	movb   $0x0,0x16(%rsp)
  4010b3:	be 5e 24 40 00       	mov    $0x40245e,%esi//maduiersnfotvbylSo you think you can stop the bomb with ctrl-c, do you?
  4010b8:	48 8d 7c 24 10       	lea    0x10(%rsp),%rdi//flyers in %rsi
  4010bd:	e8 76 02 00 00       	callq  401338 <strings_not_equal>
  4010c2:	85 c0                	test   %eax,%eax
  4010c4:	74 13                	je     4010d9 <phase_5+0x77>
  4010c6:	e8 6f 03 00 00       	callq  40143a <explode_bomb>
  4010cb:	0f 1f 44 00 00       	nopl   0x0(%rax,%rax,1)
  4010d0:	eb 07                	jmp    4010d9 <phase_5+0x77>
  4010d2:	b8 00 00 00 00       	mov    $0x0,%eax
  4010d7:	eb b2                	jmp    40108b <phase_5+0x29>
  4010d9:	48 8b 44 24 18       	mov    0x18(%rsp),%rax
  4010de:	64 48 33 04 25 28 00 	xor    %fs:0x28,%rax
  4010e5:	00 00 
  4010e7:	74 05                	je     4010ee <phase_5+0x8c>
  4010e9:	e8 42 fa ff ff       	callq  400b30 <__stack_chk_fail@plt>
  4010ee:	48 83 c4 20          	add    $0x20,%rsp
  4010f2:	5b                   	pop    %rbx
  4010f3:	c3                   	retq  

思路:
首先找到输入<string_length>,得到输入需要是长度为6的字符串。输入字符串保存在%rbx里。

 40108b:	0f b6 0c 03          	movzbl (%rbx,%rax,1),%ecx//first ascll

这句话是对输入字符串的遍历。

40108f:	88 0c 24             	mov    %cl,(%rsp)
401092:	48 8b 14 24          	mov    (%rsp),%rdx//ascll
401096:	83 e2 0f             	and    $0xf,%edx//lower four bits

这一串操作是取了被选中字母acsll码的后四位,那么选后四位干嘛呢,其实是作为数组下标访问题中提供的字符串常量$0x40245e,内容为:maduiersnfotvbylSo you think you can stop the bomb with ctrl-c, do you?,那么自己构造一传符合要求的字符串就好了。
我的答案为:ionefg

phase_6

00000000004010f4 <phase_6>:
  4010f4:	41 56                	push   %r14
  4010f6:	41 55                	push   %r13
  4010f8:	41 54                	push   %r12
  4010fa:	55                   	push   %rbp
  4010fb:	53                   	push   %rbx
  4010fc:	48 83 ec 50          	sub    $0x50,%rsp
  401100:	49 89 e5             	mov    %rsp,%r13
  401103:	48 89 e6             	mov    %rsp,%rsi
  401106:	e8 51 03 00 00       	callq  40145c <read_six_numbers>
  40110b:	49 89 e6             	mov    %rsp,%r14
  40110e:	41 bc 00 00 00 00    	mov    $0x0,%r12d
  401114:	4c 89 ed             	mov    %r13,%rbp
  401117:	41 8b 45 00          	mov    0x0(%r13),%eax//a[0]
  40111b:	83 e8 01             	sub    $0x1,%eax
  40111e:	83 f8 05             	cmp    $0x5,%eax//a[0]<=6
  401121:	76 05                	jbe    401128 <phase_6+0x34>
  401123:	e8 12 03 00 00       	callq  40143a <explode_bomb>
  401128:	41 83 c4 01          	add    $0x1,%r12d//ini:1
  40112c:	41 83 fc 06          	cmp    $0x6,%r12d
  401130:	74 21                	je     401153 <phase_6+0x5f>
  401132:	44 89 e3             	mov    %r12d,%ebx//counter
  401135:	48 63 c3             	movslq %ebx,%rax//counter copy
  401138:	8b 04 84             	mov    (%rsp,%rax,4),%eax//a[i]:start from a[1]
  40113b:	39 45 00             	cmp    %eax,0x0(%rbp)//compare with a[0]
  40113e:	75 05                	jne    401145 <phase_6+0x51>
  401140:	e8 f5 02 00 00       	callq  40143a <explode_bomb>
  401145:	83 c3 01             	add    $0x1,%ebx
  401148:	83 fb 05             	cmp    $0x5,%ebx
  40114b:	7e e8                	jle    401135 <phase_6+0x41>
  40114d:	49 83 c5 04          	add    $0x4,%r13//next element
  401151:	eb c1                	jmp    401114 <phase_6+0x20>
  401153:	48 8d 74 24 18       	lea    0x18(%rsp),%rsi//last
  401158:	4c 89 f0             	mov    %r14,%rax//a[0]
  40115b:	b9 07 00 00 00       	mov    $0x7,%ecx
  401160:	89 ca                	mov    %ecx,%edx
  401162:	2b 10                	sub    (%rax),%edx//7-a[0]
  401164:	89 10                	mov    %edx,(%rax)//a[0]-=7
  401166:	48 83 c0 04          	add    $0x4,%rax//a[i++]
  40116a:	48 39 f0             	cmp    %rsi,%rax//not the last ele
  40116d:	75 f1                	jne    401160 <phase_6+0x6c>
  40116f:	be 00 00 00 00       	mov    $0x0,%esi
  401174:	eb 21                	jmp    401197 <phase_6+0xa3>
  401176:	48 8b 52 08          	mov    0x8(%rdx),%rdx
  40117a:	83 c0 01             	add    $0x1,%eax
  40117d:	39 c8                	cmp    %ecx,%eax
  40117f:	75 f5                	jne    401176 <phase_6+0x82>
  401181:	eb 05                	jmp    401188 <phase_6+0x94>
  401183:	ba d0 32 60 00       	mov    $0x6032d0,%edx
  401188:	48 89 54 74 20       	mov    %rdx,0x20(%rsp,%rsi,2)
  40118d:	48 83 c6 04          	add    $0x4,%rsi
  401191:	48 83 fe 18          	cmp    $0x18,%rsi
  401195:	74 14                	je     4011ab <phase_6+0xb7>
  401197:	8b 0c 34             	mov    (%rsp,%rsi,1),%ecx
  40119a:	83 f9 01             	cmp    $0x1,%ecx
  40119d:	7e e4                	jle    401183 <phase_6+0x8f>
  40119f:	b8 01 00 00 00       	mov    $0x1,%eax
  4011a4:	ba d0 32 60 00       	mov    $0x6032d0,%edx//the address of a list
  4011a9:	eb cb                	jmp    401176 <phase_6+0x82>
  4011ab:	48 8b 5c 24 20       	mov    0x20(%rsp),%rbx
  4011b0:	48 8d 44 24 28       	lea    0x28(%rsp),%rax
  4011b5:	48 8d 74 24 50       	lea    0x50(%rsp),%rsi
  4011ba:	48 89 d9             	mov    %rbx,%rcx
  4011bd:	48 8b 10             	mov    (%rax),%rdx
  4011c0:	48 89 51 08          	mov    %rdx,0x8(%rcx)
  4011c4:	48 83 c0 08          	add    $0x8,%rax
  4011c8:	48 39 f0             	cmp    %rsi,%rax
  4011cb:	74 05                	je     4011d2 <phase_6+0xde>
  4011cd:	48 89 d1             	mov    %rdx,%rcx
  4011d0:	eb eb                	jmp    4011bd <phase_6+0xc9>
  4011d2:	48 c7 42 08 00 00 00 	movq   $0x0,0x8(%rdx)
  4011d9:	00 
  4011da:	bd 05 00 00 00       	mov    $0x5,%ebp
  4011df:	48 8b 43 08          	mov    0x8(%rbx),%rax
  4011e3:	8b 00                	mov    (%rax),%eax
  4011e5:	39 03                	cmp    %eax,(%rbx)
  4011e7:	7d 05                	jge    4011ee <phase_6+0xfa>
  4011e9:	e8 4c 02 00 00       	callq  40143a <explode_bomb>
  4011ee:	48 8b 5b 08          	mov    0x8(%rbx),%rbx
  4011f2:	83 ed 01             	sub    $0x1,%ebp
  4011f5:	75 e8                	jne    4011df <phase_6+0xeb>
  4011f7:	48 83 c4 50          	add    $0x50,%rsp
  4011fb:	5b                   	pop    %rbx
  4011fc:	5d                   	pop    %rbp
  4011fd:	41 5c                	pop    %r12
  4011ff:	41 5d                	pop    %r13
  401201:	41 5e                	pop    %r14
  401203:	c3                   	retq 

本题的代码非常复杂了,首先指出本题中含有链表的结构体。从<read_six_numbers>中依然可以轻易看出是要输入六个数。并且第一个数在(%rsp)
接下来的这句,通过之前的练习,可以看出这是一个遍历数组的句子。(不包括0号元素),第一次循环时,每个元素与a[0]比较是否相等,若相等则炸弹爆炸。

401138:	8b 04 84             	mov    (%rsp,%rax,4),%eax
40113b:	39 45 00             	cmp    %eax,0x0(%rbp)//compare with a[0]

%ebx相当于数组下标,继续循环。

401145:	83 c3 01             	add    $0x1,%ebx
401148:	83 fb 05             	cmp    $0x5,%ebx

当下标1-5执行完毕后,会按如下执行:

40114d:	49 83 c5 04          	add    $0x4,%r13//next element
//跳转
401114:	4c 89 ed             	mov    %r13,%rbp
401117:	41 8b 45 00          	mov    0x0(%r13),%eax//a[0]-a[5]
40111b:	83 e8 01             	sub    $0x1,%eax
40111e:	83 f8 05             	cmp    $0x5,%eax//a[0]<=6

可见这次变成了先验证a[1]<=6,再将每个数与a[1]比较是否相等。
从而可以得到,数组由<=6且互不相等的6个数组成。

401153:	48 8d 74 24 18       	lea    0x18(%rsp),%rsi//last
401158:	4c 89 f0             	mov    %r14,%rax//a[0]
40115b:	b9 07 00 00 00       	mov    $0x7,%ecx
401160:	89 ca                	mov    %ecx,%edx
401162:	2b 10                	sub    (%rax),%edx//7-a[i]
401164:	89 10                	mov    %edx,(%rax)//a[i]=7-a[i]
401166:	48 83 c0 04          	add    $0x4,%rax//a[i++]
40116a:	48 39 f0             	cmp    %rsi,%rax//not the last ele
40116d:	75 f1                	jne    401160 <phase_6+0x6c>

接下来这又是一组循坏,目的是将a[i]=7-a[i]。
紧接着执行的是:

401197:	8b 0c 34             	mov    (%rsp,%rsi,1),%ecx
40119a:	83 f9 01             	cmp    $0x1,%ecx
40119d:	7e e4                	jle    401183 <phase_6+0x8f>

又是一个数组遍历,遍历的目的是什么呢?那么看跳转之后访问的代码段,找到一个常数地址$0x6032d0,以下循环便是关于这个地址的。

401183:	ba d0 32 60 00       	mov    $0x6032d0,%edx
401188:	48 89 54 74 20       	mov    %rdx,0x20(%rsp,%rsi,2)
40118d:	48 83 c6 04          	add    $0x4,%rsi//访问下一个元素
401191:	48 83 fe 18          	cmp    $0x18,%rsi//看是否完成遍历
401195:	74 14                	je     4011ab <phase_6+0xb7>//跳出循环句
401197:	8b 0c 34             	mov    (%rsp,%rsi,1),%ecx
40119a:	83 f9 01             	cmp    $0x1,%ecx
40119d:	7e e4                	jle    401183 <phase_6+0x8f>

这一串执行完毕后,大家应该已经有点晕了,这是在干什么呢?我们可以先访问一下地址$0x6032d0:
可以得到链表中的结点,每个结点占4字(以4字节为一字),链表中每个部分的组成很好猜,我就不多解释。
在这里插入图片描述

插入科普:
在这里插入图片描述

说完了局部,整体放大来看:这一段其实是将链表按输入数组中的值对应排到某个位置上。(0x20(%rsp,%rsi,2))
在这里插入图片描述

40116f:	be 00 00 00 00       	mov    $0x0,%esi
401174:	eb 21                	jmp    401197 <phase_6+0xa3>
//下个结点地址
401176:	48 8b 52 08          	mov    0x8(%rdx),%rdx
40117a:	83 c0 01             	add    $0x1,%eax
40117d:	39 c8                	cmp    %ecx,%eax
40117f:	75 f5                	jne    401176 <phase_6+0x82>
401181:	eb 05                	jmp    401188 <phase_6+0x94>
401183:	ba d0 32 60 00       	mov    $0x6032d0,%edx
401188:	48 89 54 74 20       	mov    %rdx,0x20(%rsp,%rsi,2)
40118d:	48 83 c6 04          	add    $0x4,%rsi
401191:	48 83 fe 18          	cmp    $0x18,%rsi
//最后的跳出
401195:	74 14                	je     4011ab <phase_6+0xb7>
//数组遍历
401197:	8b 0c 34             	mov    (%rsp,%rsi,1),%ecx
40119a:	83 f9 01             	cmp    $0x1,%ecx
40119d:	7e e4                	jle    401183 <phase_6+0x8f>
40119f:	b8 01 00 00 00       	mov    $0x1,%eax
4011a4:	ba d0 32 60 00       	mov    $0x6032d0,%edx//the address of a list
4011a9:	eb cb                	jmp    401176 <phase_6+0x82>

之后,便跳转到这一段,按降序重建链表

  //链表首地址
  4011ab:	48 8b 5c 24 20       	mov    0x20(%rsp),%rbx
  //链表下一个节点地址
  4011b0:	48 8d 44 24 28       	lea    0x28(%rsp),%rax
  //链表尾
  4011b5:	48 8d 74 24 50       	lea    0x50(%rsp),%rsi
  4011ba:	48 89 d9             	mov    %rbx,%rcx
  4011bd:	48 8b 10             	mov    (%rax),%rdx
  4011c0:	48 89 51 08          	mov    %rdx,0x8(%rcx)
  4011c4:	48 83 c0 08          	add    $0x8,%rax
  4011c8:	48 39 f0             	cmp    %rsi,%rax
  4011cb:	74 05                	je     4011d2 <phase_6+0xde>
  4011cd:	48 89 d1             	mov    %rdx,%rcx
  4011d0:	eb eb                	jmp    4011bd <phase_6+0xc9>
  //尾指针为空
  4011d2:	48 c7 42 08 00 00 00 	movq   $0x0,0x8(%rdx)
  4011d9:	00 

这一段是最后的测试部分,测试是否确实降序,若不是则引爆炸弹

  4011da:	bd 05 00 00 00       	mov    $0x5,%ebp//跳出条件
  4011df:	48 8b 43 08          	mov    0x8(%rbx),%rax
  4011e3:	8b 00                	mov    (%rax),%eax
  //和上一个元素值相比较
  4011e5:	39 03                	cmp    %eax,(%rbx)
  4011e7:	7d 05                	jge    4011ee <phase_6+0xfa>
  4011e9:	e8 4c 02 00 00       	callq  40143a <explode_bomb>
  4011ee:	48 8b 5b 08          	mov    0x8(%rbx),%rbx
  4011f2:	83 ed 01             	sub    $0x1,%ebp
  4011f5:	75 e8                	jne    4011df <phase_6+0xeb>

按照降序排列后,顺序是3 4 5 6 1 2,但还要翻转一下,于是为4 3 2 1 6 5。

运行结果:
在这里插入图片描述

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值