目录

CS:APP Bomb lab

实验步骤

准备工作

使用tar -vxf将炸弹压缩包解压,cd 进入,可以从 bomb.c 中看出实验的用意以及程序的大致 逻辑,bomb 为可执行程序,使用 gdb 调试该程序.

1
2
3
4
(gdb) b read_line
Breakpoint 1 at 0x40155c
(gdb) b explode_bomb
Breakpoint 2 at 0x4014e4

给 read_line 函数打上断点,以便每次输入运行一关.给 explode_bomb 打上断点,以便在炸弹爆炸 前可以处理.

phase_1

获得 phase_1 汇编代码

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
(gdb) disas phase_1
Dump of assembler code for function phase_1:
   0x0000000000400e80 <+0>:	sub    $0x8,%rsp
   0x0000000000400e84 <+4>:	mov    $0x4024a0,%esi
   0x0000000000400e89 <+9>:	callq  0x40127e <strings_not_equal>
   0x0000000000400e8e <+14>:	test   %eax,%eax
   0x0000000000400e90 <+16>:	je     0x400e97 <phase_1+23>
   0x0000000000400e92 <+18>:	callq  0x4014e4 <explode_bomb>
   0x0000000000400e97 <+23>:	add    $0x8,%rsp
   0x0000000000400e9b <+27>:	retq
End of assembler dump.

可见,此题是将我们输入的字符串与地址 0x4024a0 处字符串比较,不等则爆炸.查看该字符串.

1
2
(gdb) x/s 0x4024a0
0x4024a0 <__dso_handle+344>:	 "We have to stand with our North Korean allies."

那么答案是 We have to stand with our North Korean allies.

phase_2

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
(gdb) disas phase_2
Dump of assembler code for function phase_2:
   0x0000000000400e9c <+0>:	push   %rbp
   0x0000000000400e9d <+1>:	push   %rbx
   0x0000000000400e9e <+2>:	sub    $0x28,%rsp
   0x0000000000400ea2 <+6>:	mov    %rsp,%rsi
   0x0000000000400ea5 <+9>:	callq  0x40151a <read_six_numbers>
   0x0000000000400eaa <+14>:	cmpl   $0x1,(%rsp)
   0x0000000000400eae <+18>:	je     0x400ed0 <phase_2+52>
   0x0000000000400eb0 <+20>:	callq  0x4014e4 <explode_bomb>
   0x0000000000400eb5 <+25>:	jmp    0x400ed0 <phase_2+52>
   0x0000000000400eb7 <+27>:	mov    -0x4(%rbx),%eax
   0x0000000000400eba <+30>:	add    %eax,%eax
   0x0000000000400ebc <+32>:	cmp    %eax,(%rbx)
   0x0000000000400ebe <+34>:	je     0x400ec5 <phase_2+41>
   0x0000000000400ec0 <+36>:	callq  0x4014e4 <explode_bomb>
   0x0000000000400ec5 <+41>:	add    $0x4,%rbx
   0x0000000000400ec9 <+45>:	cmp    %rbp,%rbx
   0x0000000000400ecc <+48>:	jne    0x400eb7 <phase_2+27>
   0x0000000000400ece <+50>:	jmp    0x400edc <phase_2+64>
   0x0000000000400ed0 <+52>:	lea    0x4(%rsp),%rbx
   0x0000000000400ed5 <+57>:	lea    0x18(%rsp),%rbp
   0x0000000000400eda <+62>:	jmp    0x400eb7 <phase_2+27>
   0x0000000000400edc <+64>:	add    $0x28,%rsp
---Type <return> to continue, or q <return> to quit---
   0x0000000000400ee0 <+68>:	pop    %rbx
   0x0000000000400ee1 <+69>:	pop    %rbp
   0x0000000000400ee2 <+70>:	retq
End of assembler dump.

+3 处发现在栈中开辟了 0x28 的内存区域.然后将%rsp 的值传给%rsi 作为 参数传给函数 read_six_numbers,可以看出应该使用开辟的空闲内存做 数组,记数组为 r,读取六个数字.将(%rsp)和 0x1 比较,如果不等,就会爆 炸,(%rsp)为数组首元,故 r[0]=1;跳转到+52,将 r[1]地址赋给%rbx, 将 r6 地址赋给%rbp,跳到+27,将%eax 设为%rbx 指向的前一个 数,此时为 r[0],比较 r[1]和 2*r[0]是否相等,不等则爆炸.跳转到+41,% rbx+4,比较%rbx 和%rbp,不等跳转到+27,重复,等则跳转到+64 结束,成功 .可以看出,这是一个循环比较.等价于下面的 c 语 a 言

1
2
3
4
for(int *b = &r[1]; b != &r[6]; b++)
{
    if(*b != 2 * (*(b - 1)))
        call explode_bomb;

故答案应该为 1 2 4 8 16 32.

phase_3

1
2
3
4
   0x0000000000400ef1 <+14>:	mov    $0x4027cd,%esi
   0x0000000000400ef6 <+19>:	mov    $0x0,%eax
   0x0000000000400efb <+24>:	callq  0x400ba0 <__isoc99_sscanf@plt>
   0x0000000000400f00 <+29>:	cmp    $0x1,%eax

查看 0x4027cd,

1
2
(gdb) x/s 0x4027cd
0x4027cd:	 "%d %d"

可知,应该是读入了两个整数.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
   0x0000000000400f15 <+50>:	jmpq   *0x402500(,%rax,8)
   0x0000000000400f1c <+57>:	mov    $0x0,%eax
   0x0000000000400f21 <+62>:	jmp    0x400f28 <phase_3+69>
   0x0000000000400f23 <+64>:	mov    $0x19c,%eax
   0x0000000000400f28 <+69>:	sub    $0xcd,%eax
   0x0000000000400f2d <+74>:	jmp    0x400f34 <phase_3+81>
   0x0000000000400f2f <+76>:	mov    $0x0,%eax
   0x0000000000400f34 <+81>:	add    $0x29b,%eax
   0x0000000000400f39 <+86>:	jmp    0x400f40 <phase_3+93>
   0x0000000000400f3b <+88>:	mov    $0x0,%eax
---Type <return> to continue, or q <return> to quit---
   0x0000000000400f40 <+93>:	sub    $0x36f,%eax
   0x0000000000400f45 <+98>:	jmp    0x400f4c <phase_3+105>
   0x0000000000400f47 <+100>:	mov    $0x0,%eax
   0x0000000000400f4c <+105>:	add    $0x36f,%eax
   0x0000000000400f51 <+110>:	jmp    0x400f58 <phase_3+117>
   0x0000000000400f53 <+112>:	mov    $0x0,%eax
   0x0000000000400f58 <+117>:	sub    $0x36f,%eax
   0x0000000000400f5d <+122>:	jmp    0x400f64 <phase_3+129>
   0x0000000000400f5f <+124>:	mov    $0x0,%eax
   0x0000000000400f64 <+129>:	add    $0x36f,%eax
   0x0000000000400f69 <+134>:	jmp    0x400f70 <phase_3+141>
   0x0000000000400f6b <+136>:	mov    $0x0,%eax
   0x0000000000400f70 <+141>:	sub    $0x36f,%eax
   0x0000000000400f75 <+146>:	jmp    0x400f81 <phase_3+158>
   0x0000000000400f77 <+148>:	callq  0x4014e4 <explode_bomb>
   0x0000000000400f7c <+153>:	mov    $0x0,%eax
   0x0000000000400f81 <+158>:	cmpl   $0x5,0xc(%rsp)
   0x0000000000400f86 <+163>:	jg     0x400f8e <phase_3+171>
   0x0000000000400f88 <+165>:	cmp    0x8(%rsp),%eax
   0x0000000000400f8c <+169>:	je     0x400f93 <phase_3+176>
   0x0000000000400f8e <+171>:	callq  0x4014e4 <explode_bomb>

由这段汇编代码可知,这是一段 switch 语句,使用输入的第一个值作为 key, 经过对应跳转位置的操作后应与第二个数相等.

1
2
(gdb) p/x *(0x402500 + 32)
$1 = 0x400f47

那么第一个数为 0 时,跳转到 0x400f23 处,那么第二个数应该为此处的 0x0, 故一组答案为 4 0;

phase_4

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
(gdb) disas phase_4
Dump of assembler code for function phase_4:
   0x0000000000400fd0 <+0>:	sub    $0x18,%rsp
   0x0000000000400fd4 <+4>:	lea    0xc(%rsp),%rcx
   0x0000000000400fd9 <+9>:	lea    0x8(%rsp),%rdx
   0x0000000000400fde <+14>:	mov    $0x4027cd,%esi
   0x0000000000400fe3 <+19>:	mov    $0x0,%eax
   0x0000000000400fe8 <+24>:	callq  0x400ba0 <__isoc99_sscanf@plt>
   0x0000000000400fed <+29>:	cmp    $0x2,%eax
   0x0000000000400ff0 <+32>:	jne    0x400ffe <phase_4+46>
   0x0000000000400ff2 <+34>:	mov    0xc(%rsp),%eax
   0x0000000000400ff6 <+38>:	sub    $0x2,%eax
   0x0000000000400ff9 <+41>:	cmp    $0x2,%eax
   0x0000000000400ffc <+44>:	jbe    0x401003 <phase_4+51>
   0x0000000000400ffe <+46>:	callq  0x4014e4 <explode_bomb>
   0x0000000000401003 <+51>:	mov    0xc(%rsp),%esi
   0x0000000000401007 <+55>:	mov    $0x9,%edi
   0x000000000040100c <+60>:	callq  0x400f98 <func4>
   0x0000000000401011 <+65>:	cmp    0x8(%rsp),%eax
   0x0000000000401015 <+69>:	je     0x40101c <phase_4+76>
   0x0000000000401017 <+71>:	callq  0x4014e4 <explode_bomb>
   0x000000000040101c <+76>:	add    $0x18,%rsp
   0x0000000000401020 <+80>:	retq
End of assembler dump.

由代码易知,phase_4 读入了两个数,第二个数在 2-4 之间,然后将第二个数作为 func4 的第二个参数,func4 第一个参数为 9,输入的第一个数必须和 func4 返回值相等.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
(gdb) disas func4
Dump of assembler code for function func4:
   0x0000000000400f98 <+0>:	push   %r12
   0x0000000000400f9a <+2>:	push   %rbp
   0x0000000000400f9b <+3>:	push   %rbx
   0x0000000000400f9c <+4>:	mov    %edi,%ebx
   0x0000000000400f9e <+6>:	test   %edi,%edi
   0x0000000000400fa0 <+8>:	jle    0x400fc6 <func4+46>
   0x0000000000400fa2 <+10>:	mov    %esi,%ebp
   0x0000000000400fa4 <+12>:	mov    %esi,%eax
   0x0000000000400fa6 <+14>:	cmp    $0x1,%edi
   0x0000000000400fa9 <+17>:	je     0x400fcb <func4+51>
   0x0000000000400fab <+19>:	lea    -0x1(%rdi),%edi
   0x0000000000400fae <+22>:	callq  0x400f98 <func4>
   0x0000000000400fb3 <+27>:	lea    (%rax,%rbp,1),%r12d
   0x0000000000400fb7 <+31>:	lea    -0x2(%rbx),%edi
   0x0000000000400fba <+34>:	mov    %ebp,%esi
   0x0000000000400fbc <+36>:	callq  0x400f98 <func4>
   0x0000000000400fc1 <+41>:	add    %r12d,%eax
   0x0000000000400fc4 <+44>:	jmp    0x400fcb <func4+51>
   0x0000000000400fc6 <+46>:	mov    $0x0,%eax
   0x0000000000400fcb <+51>:	pop    %rbx
   0x0000000000400fcc <+52>:	pop    %rbp
   0x0000000000400fcd <+53>:	pop    %r12
   0x0000000000400fcf <+55>:	retq
End of assembler dump.

此函数等价于下面的 c 代码

1
2
3
4
5
6
7
8
9

int func4(int a, int b)
{
    if(a <= 0)
        return 0;
    if(a == 1)
        return b;
    return b + func4(a - 1, b) + func4(n - 2, b);
}

穷举 2-4 的值即可得到答案,取答案为 176 2

phase_5

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
(gdb) disas phase_5
Dump of assembler code for function phase_5:
   0x0000000000401021 <+0>:	push   %rbx
   0x0000000000401022 <+1>:	mov    %rdi,%rbx
   0x0000000000401025 <+4>:	callq  0x401261 <string_length>
   0x000000000040102a <+9>:	cmp    $0x6,%eax
   0x000000000040102d <+12>:	je     0x401034 <phase_5+19>
   0x000000000040102f <+14>:	callq  0x4014e4 <explode_bomb>
   0x0000000000401034 <+19>:	mov    $0x0,%eax
   0x0000000000401039 <+24>:	mov    $0x0,%edx
   0x000000000040103e <+29>:	movzbl (%rbx,%rax,1),%ecx
   0x0000000000401042 <+33>:	and    $0xf,%ecx
   0x0000000000401045 <+36>:	add    0x402540(,%rcx,4),%edx
   0x000000000040104c <+43>:	add    $0x1,%rax
   0x0000000000401050 <+47>:	cmp    $0x6,%rax
   0x0000000000401054 <+51>:	jne    0x40103e <phase_5+29>
   0x0000000000401056 <+53>:	cmp    $0x27,%edx
   0x0000000000401059 <+56>:	je     0x401060 <phase_5+63>
   0x000000000040105b <+58>:	callq  0x4014e4 <explode_bomb>
   0x0000000000401060 <+63>:	pop    %rbx
   0x0000000000401061 <+64>:	retq
End of assembler dump.

由汇编代码可知,需要输入一个长度为 6 的字符串.令该字符串为 input,+36 处出现的 数组为 array,则该汇编等价于下面代码.

1
2
for(int i = 0; i < 6; i++)
    sum += array[ input[i] & 0xf ];

意为遍历输入字符串,取该字符串低 4 位作为 array 下标,取出 array 值相加. 查看 array 的值

1
2
3
(gdb) p/x *0x402540@16
$2 = {0x2, 0xa, 0x6, 0x1, 0xc, 0x10, 0x9, 0x3, 0x4, 0x7, 0xe, 0x5, 0xb, 0x8,
  0xf, 0xd}

题目要求 sum = 0x27,故从 array 中选出 6 个和为 0x27 的数,通过这 6 个数的下标找出对应字符. 答案应为 01347L;

phase_6

因为课程未对后续两关作要求,故不做特别详细的解答.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
(gdb) disas phase_6
Dump of assembler code for function phase_6:
   0x0000000000401062 <+0>:	push   %r13
   0x0000000000401064 <+2>:	push   %r12
   0x0000000000401066 <+4>:	push   %rbp
   0x0000000000401067 <+5>:	push   %rbx
   0x0000000000401068 <+6>:	sub    $0x58,%rsp
   0x000000000040106c <+10>:	lea    0x30(%rsp),%rsi
   0x0000000000401071 <+15>:	callq  0x40151a <read_six_numbers>
   0x0000000000401076 <+20>:	lea    0x30(%rsp),%r13
   0x000000000040107b <+25>:	mov    $0x0,%r12d
   0x0000000000401081 <+31>:	mov    %r13,%rbp
   0x0000000000401084 <+34>:	mov    0x0(%r13),%eax
   0x0000000000401088 <+38>:	sub    $0x1,%eax
   0x000000000040108b <+41>:	cmp    $0x5,%eax
   0x000000000040108e <+44>:	jbe    0x401095 <phase_6+51>
   0x0000000000401090 <+46>:	callq  0x4014e4 <explode_bomb>
   0x0000000000401095 <+51>:	add    $0x1,%r12d
   0x0000000000401099 <+55>:	cmp    $0x6,%r12d
   0x000000000040109d <+59>:	jne    0x4010a6 <phase_6+68>
   0x000000000040109f <+61>:	mov    $0x0,%esi
   0x00000000004010a4 <+66>:	jmp    0x4010e8 <phase_6+134>
   0x00000000004010a6 <+68>:	mov    %r12d,%ebx
   0x00000000004010a9 <+71>:	movslq %ebx,%rax
---Type <return> to continue, or q <return> to quit---
   0x00000000004010ac <+74>:	mov    0x30(%rsp,%rax,4),%eax
   0x00000000004010b0 <+78>:	cmp    %eax,0x0(%rbp)
   0x00000000004010b3 <+81>:	jne    0x4010ba <phase_6+88>
   0x00000000004010b5 <+83>:	callq  0x4014e4 <explode_bomb>
   0x00000000004010ba <+88>:	add    $0x1,%ebx
   0x00000000004010bd <+91>:	cmp    $0x5,%ebx
   0x00000000004010c0 <+94>:	jle    0x4010a9 <phase_6+71>
   0x00000000004010c2 <+96>:	add    $0x4,%r13
   0x00000000004010c6 <+100>:	jmp    0x401081 <phase_6+31>
   0x00000000004010c8 <+102>:	mov    0x8(%rdx),%rdx
   0x00000000004010cc <+106>:	add    $0x1,%eax
   0x00000000004010cf <+109>:	cmp    %ecx,%eax
   0x00000000004010d1 <+111>:	jne    0x4010c8 <phase_6+102>
   0x00000000004010d3 <+113>:	jmp    0x4010da <phase_6+120>
   0x00000000004010d5 <+115>:	mov    $0x603410,%edx
   0x00000000004010da <+120>:	mov    %rdx,(%rsp,%rsi,2)
   0x00000000004010de <+124>:	add    $0x4,%rsi
   0x00000000004010e2 <+128>:	cmp    $0x18,%rsi
   0x00000000004010e6 <+132>:	je     0x4010fd <phase_6+155>
   0x00000000004010e8 <+134>:	mov    0x30(%rsp,%rsi,1),%ecx
   0x00000000004010ec <+138>:	cmp    $0x1,%ecx
   0x00000000004010ef <+141>:	jle    0x4010d5 <phase_6+115>
   0x00000000004010f1 <+143>:	mov    $0x1,%eax
---Type <return> to continue, or q <return> to quit---
   0x00000000004010f6 <+148>:	mov    $0x603410,%edx
   0x00000000004010fb <+153>:	jmp    0x4010c8 <phase_6+102>
   0x00000000004010fd <+155>:	mov    (%rsp),%rbx
   0x0000000000401101 <+159>:	lea    0x8(%rsp),%rax
   0x0000000000401106 <+164>:	lea    0x30(%rsp),%rsi
   0x000000000040110b <+169>:	mov    %rbx,%rcx
   0x000000000040110e <+172>:	mov    (%rax),%rdx
   0x0000000000401111 <+175>:	mov    %rdx,0x8(%rcx)
   0x0000000000401115 <+179>:	add    $0x8,%rax
   0x0000000000401119 <+183>:	cmp    %rsi,%rax
   0x000000000040111c <+186>:	je     0x401123 <phase_6+193>
   0x000000000040111e <+188>:	mov    %rdx,%rcx
   0x0000000000401121 <+191>:	jmp    0x40110e <phase_6+172>
   0x0000000000401123 <+193>:	movq   $0x0,0x8(%rdx)
   0x000000000040112b <+201>:	mov    $0x5,%ebp
   0x0000000000401130 <+206>:	mov    0x8(%rbx),%rax
   0x0000000000401134 <+210>:	mov    (%rax),%eax
   0x0000000000401136 <+212>:	cmp    %eax,(%rbx)
   0x0000000000401138 <+214>:	jge    0x40113f <phase_6+221>
   0x000000000040113a <+216>:	callq  0x4014e4 <explode_bomb>
   0x000000000040113f <+221>:	mov    0x8(%rbx),%rbx
   0x0000000000401143 <+225>:	sub    $0x1,%ebp
   0x0000000000401146 <+228>:	jne    0x401130 <phase_6+206>
---Type <return> to continue, or q <return> to quit---
   0x0000000000401148 <+230>:	add    $0x58,%rsp
   0x000000000040114c <+234>:	pop    %rbx
   0x000000000040114d <+235>:	pop    %rbp
   0x000000000040114e <+236>:	pop    %r12
   0x0000000000401150 <+238>:	pop    %r13
   0x0000000000401152 <+240>:	retq
End of assembler dump.

汇编代码很长.其意为输入 6 个互不相等的数,介于 1-6.按这 6 个数的值从位于地址 0x603410 的链表中选出对应位置的 节点指针,组成一个数组.按选出的顺序将这六个节点组成新的链表,然后检查这个链表是否为降序. 查看链表的值.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
(gdb) p/x *(0x603410)
$3 = 0x1cf
(gdb) p/x *(0x603410 + 8)
$4 = 0x603420
(gdb) p/x *(0x603420)
$5 = 0x188
(gdb) p/x *(0x603420 + 8)
$6 = 0x603430
(gdb) p/x *(0x603430)
$7 = 0x1d1
(gdb) p/x *(0x603430 + 8)
$8 = 0x603440
(gdb) p/x *(0x603440)
$9 = 0x174
(gdb) p/x *(0x603440 + 8)
$10 = 0x603450
(gdb) p/x *(0x603450)
$11 = 0x220
(gdb) p/x *(0x603450 + 8)
$12 = 0x603460
(gdb) p/x *(0x603460 + 8)
$13 = 0x0

故答案应为 6 5 3 1 2 4;

secret_phase

正常通过前 6 关是无法触发 secret_phase 的,查看汇编发现,在 phase_4 答案之后输入 DrEvil 即可进入 secret_phase.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
(gdb) disas secret_phase
Dump of assembler code for function secret_phase:
   0x0000000000401191 <+0>:	push   %rbx
   0x0000000000401192 <+1>:	callq  0x40155c <read_line>
   0x0000000000401197 <+6>:	mov    $0xa,%edx
   0x000000000040119c <+11>:	mov    $0x0,%esi
   0x00000000004011a1 <+16>:	mov    %rax,%rdi
   0x00000000004011a4 <+19>:	callq  0x400b80 <strtol@plt>
   0x00000000004011a9 <+24>:	mov    %rax,%rbx
   0x00000000004011ac <+27>:	lea    -0x1(%rax),%eax
   0x00000000004011af <+30>:	cmp    $0x3e8,%eax
   0x00000000004011b4 <+35>:	jbe    0x4011bb <secret_phase+42>
   0x00000000004011b6 <+37>:	callq  0x4014e4 <explode_bomb>
   0x00000000004011bb <+42>:	mov    %ebx,%esi
   0x00000000004011bd <+44>:	mov    $0x603230,%edi
   0x00000000004011c2 <+49>:	callq  0x401153 <fun7>
   0x00000000004011c7 <+54>:	cmp    $0x4,%eax
   0x00000000004011ca <+57>:	je     0x4011d1 <secret_phase+64>
   0x00000000004011cc <+59>:	callq  0x4014e4 <explode_bomb>
   0x00000000004011d1 <+64>:	mov    $0x4024d0,%edi
   0x00000000004011d6 <+69>:	callq  0x400ac0 <puts@plt>
   0x00000000004011db <+74>:	callq  0x401682 <phase_defused>
   0x00000000004011e0 <+79>:	pop    %rbx
   0x00000000004011e1 <+80>:	retq
---Type <return> to continue, or q <return> to quit---
End of assembler dump.
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
(gdb) disas fun7
Dump of assembler code for function fun7:
   0x0000000000401153 <+0>:	sub    $0x8,%rsp
   0x0000000000401157 <+4>:	test   %rdi,%rdi
   0x000000000040115a <+7>:	je     0x401187 <fun7+52>
   0x000000000040115c <+9>:	mov    (%rdi),%edx
   0x000000000040115e <+11>:	cmp    %esi,%edx
   0x0000000000401160 <+13>:	jle    0x40116f <fun7+28>
   0x0000000000401162 <+15>:	mov    0x8(%rdi),%rdi
   0x0000000000401166 <+19>:	callq  0x401153 <fun7>
   0x000000000040116b <+24>:	add    %eax,%eax
   0x000000000040116d <+26>:	jmp    0x40118c <fun7+57>
   0x000000000040116f <+28>:	mov    $0x0,%eax
   0x0000000000401174 <+33>:	cmp    %esi,%edx
   0x0000000000401176 <+35>:	je     0x40118c <fun7+57>
   0x0000000000401178 <+37>:	mov    0x10(%rdi),%rdi
   0x000000000040117c <+41>:	callq  0x401153 <fun7>
   0x0000000000401181 <+46>:	lea    0x1(%rax,%rax,1),%eax
   0x0000000000401185 <+50>:	jmp    0x40118c <fun7+57>
   0x0000000000401187 <+52>:	mov    $0xffffffff,%eax
   0x000000000040118c <+57>:	add    $0x8,%rsp
   0x0000000000401190 <+61>:	retq
End of assembler dump.

此题题意为在一个题目中构建好的平衡二叉树中从根节点开始查找一个输入的数. 由节点向左为 0,由节点向右为 1,查找路径序的 0-1 列从右向左构成一个二进制数,该 二进制数的十进制值必须等于题目中提供的数,其为 4,那么所需查找路径序列为 100, 根据二叉树结构,应该查找 7,故答案为 7.

运行截图

/CSAPP-Bomb-lab/ret1.png