CSAPP:bomblab
阅读原文时间:2023年07月09日阅读:3

BOMBLAB实验总结

CSAPP实验BOMB,很头疼,看不懂,勉强做完了。

答案是这样的:

Border relations with Canada have never been better.
1 2 4 8 16 32
2 707
7 0
9?>567
4 3 2 1 6 5

在bomb文件夹新建一个文件input.txt,再在gdb下运行如下指令:

run < input.txt

就可以不用自己输入跑实验了。

做实验时记得一定要加一句:

b explode_bomb

防止踩雷~

main函数里有这两行:

  400e32:    e8 67 06 00 00          callq  40149e <read_line>
  400e37:    48 89 c7                mov    %rax,%rdi
  400e3a:    e8 a1 00 00 00          callq  400ee0 <phase_1>

这就可以说明我们输入的数据放进了%rdi里面。再进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

第一阶段,发现需要让%eax为0,才不会执行到explode_bomb。然而这里好像没调用%eax,只好去strings_not_equal看看。

0000000000401338 <strings_not_equal>:
  401338:    41 54                   push   %r12
  40133a:    55                      push   %rbp
  40133b:    53                      push   %rbx
  40133c:    48 89 fb                mov    %rdi,%rbx
  40133f:    48 89 f5                mov    %rsi,%rbp
  401342:    e8 d4 ff ff ff          callq  40131b <string_length>
  401347:    41 89 c4                mov    %eax,%r12d
  40134a:    48 89 ef                mov    %rbp,%rdi
  40134d:    e8 c9 ff ff ff          callq  40131b <string_length>
  401352:    ba 01 00 00 00          mov    $0x1,%edx
  401357:    41 39 c4                cmp    %eax,%r12d
  40135a:    75 3f                   jne    40139b <strings_not_equal+0x63>
  40135c:    0f b6 03                movzbl (%rbx),%eax
  40135f:    84 c0                   test   %al,%al
  401361:    74 25                   je     401388 <strings_not_equal+0x50>
  401363:    3a 45 00                cmp    0x0(%rbp),%al
  401366:    74 0a                   je     401372 <strings_not_equal+0x3a>
  401368:    eb 25                   jmp    40138f <strings_not_equal+0x57>
  40136a:    3a 45 00                cmp    0x0(%rbp),%al
  40136d:    0f 1f 00                nopl   (%rax)
  401370:    75 24                   jne    401396 <strings_not_equal+0x5e>
  401372:    48 83 c3 01             add    $0x1,%rbx
  401376:    48 83 c5 01             add    $0x1,%rbp
  40137a:    0f b6 03                movzbl (%rbx),%eax
  40137d:    84 c0                   test   %al,%al
  40137f:    75 e9                   jne    40136a <strings_not_equal+0x32>
  401381:    ba 00 00 00 00          mov    $0x0,%edx
  401386:    eb 13                   jmp    40139b <strings_not_equal+0x63>
  401388:    ba 00 00 00 00          mov    $0x0,%edx
  40138d:    eb 0c                   jmp    40139b <strings_not_equal+0x63>
  40138f:    ba 01 00 00 00          mov    $0x1,%edx
  401394:    eb 05                   jmp    40139b <strings_not_equal+0x63>
  401396:    ba 01 00 00 00          mov    $0x1,%edx
  40139b:    89 d0                   mov    %edx,%eax
  40139d:    5b                      pop    %rbx
  40139e:    5d                      pop    %rbp
  40139f:    41 5c                   pop    %r12
  4013a1:    c3                      retq

还是有点疑惑,去string_length看看。

000000000040131b <string_length>:
  40131b:    80 3f 00                cmpb   $0x0,(%rdi)
  40131e:    74 12                   je     401332 <string_length+0x17>
  401320:    48 89 fa                mov    %rdi,%rdx
  401323:    48 83 c2 01             add    $0x1,%rdx
  401327:    89 d0                   mov    %edx,%eax
  401329:    29 f8                   sub    %edi,%eax
  40132b:    80 3a 00                cmpb   $0x0,(%rdx)
  40132e:    75 f3                   jne    401323 <string_length+0x8>
  401330:    f3 c3                   repz retq
  401332:    b8 00 00 00 00          mov    $0x0,%eax
  401337:    c3                      retq

我们发现%eax是用来存储长度的,%rdi放的是数据。顺腾摸瓜发现,分别使用了%rdi%rsi两个地方的数据。然后发现在一开头有一句代码:

  400ee4:    be 00 24 40 00          mov    $0x402400,%esi

程序在一个地方导入了一个数据,好奇去看看

x /s 0x402400
结果:Border relations with Canada have never been better.

这句话就是最终答案。

先去瞅瞅代码:

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)
  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
  400f1a:    01 c0                   add    %eax,%eax
  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
  400f29:    48 39 eb                cmp    %rbp,%rbx
  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
  400f35:    48 8d 6c 24 18          lea    0x18(%rsp),%rbp
  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就是读进去6个数咯。

000000000040145c <read_six_numbers>:
  40145c:    48 83 ec 18             sub    $0x18,%rsp
  401460:    48 89 f2                mov    %rsi,%rdx
  401463:    48 8d 4e 04             lea    0x4(%rsi),%rcx
  401467:    48 8d 46 14             lea    0x14(%rsi),%rax
  40146b:    48 89 44 24 08          mov    %rax,0x8(%rsp)
  401470:    48 8d 46 10             lea    0x10(%rsi),%rax
  401474:    48 89 04 24             mov    %rax,(%rsp)
  401478:    4c 8d 4e 0c             lea    0xc(%rsi),%r9
  40147c:    4c 8d 46 08             lea    0x8(%rsi),%r8
  401480:    be c3 25 40 00          mov    $0x4025c3,%esi
  401485:    b8 00 00 00 00          mov    $0x0,%eax
  40148a:    e8 61 f7 ff ff          callq  400bf0 <__isoc99_sscanf@plt>
  40148f:    83 f8 05                cmp    $0x5,%eax
  401492:    7f 05                   jg     401499 <read_six_numbers+0x3d>
  401494:    e8 a1 ff ff ff          callq  40143a <explode_bomb>
  401499:    48 83 c4 18             add    $0x18,%rsp
  40149d:    c3                      retq

跑到这个函数一看开头一个%18,说明栈指针移动了24个字节,一个数据4个字节,6个数字就刚好。我就懒得看代码,猜它放进了栈里存着。

然后到爆炸前查看了一下%rsp后32位,果然存了进去。

x /b32 $rsp

在看看这一段:

  400f17:    8b 43 fc                mov    -0x4(%rbx),%eax
  400f1a:    01 c0                   add    %eax,%eax
  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
  400f29:    48 39 eb                cmp    %rbp,%rbx
  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
  400f35:    48 8d 6c 24 18          lea    0x18(%rsp),%rbp
  400f3a:    eb db                   jmp    400f17 <phase_2+0x1b>

这一段,就是存了个第二个数字的数据,存了个结尾。把这个数据的前一个数据乘2,看与这个数据是否相等。相等就往前一个数据看。一直下去,直到这个数据和结尾的数据相同,就跳出循环。

所以很明显,他需要等比数列,比值是2。

由于设定了起始数据为1,那么答案就是:

1 2 4 8 16 32

丢一段代码上来:

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
  400f56:    b8 00 00 00 00          mov    $0x0,%eax
  400f5b:    e8 90 fc ff ff          callq  400bf0 <__isoc99_sscanf@plt>
  400f60:    83 f8 01                cmp    $0x1,%eax
  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)
  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)
  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
  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   

有了第一题的经验,看到了这句:

  400f51:    be cf 25 40 00          mov    $0x4025cf,%esi

就立马查看了里面放了啥,结果是:

%d %d

嗯,也就是要读两个数。

再看这句:

  400f6a:    83 7c 24 08 07          cmpl   $0x7,0x8(%rsp)
  400f6f:    77 3c                   ja     400fad <phase_3+0x6a>

第一个数要小于7。

然后这段代码:

  400f75:    ff 24 c5 70 24 40 00    jmpq   *0x402470(,%rax,8)
  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

说明,由第一个输入的数决定%eax的值。

再看这段:

  400fbe:    3b 44 24 0c             cmp    0xc(%rsp),%eax
  400fc2:    74 05                   je     400fc9 <phase_3+0x86>

也就是说第二个数跟第一个数的输入之后选择出来的%eax要相同。

然后我们有7个选择,我们选2,也就是:

2 707

贴一下代码:

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
  40102c:    75 07                   jne    401035 <phase_4+0x29>
  40102e:    83 7c 24 08 0e          cmpl   $0xe,0x8(%rsp)
  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
  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

前半段输入数字和phase_3是一样的,读进去两个数。

看段代码:

  40102e:    83 7c 24 08 0e          cmpl   $0xe,0x8(%rsp)
  401033:    76 05                   jbe    40103a <phase_4+0x2e>
  401035:    e8 00 04 00 00          callq  40143a <explode_bomb>

这就是暗示我们,第一个输入的数字要小于等于14。

  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>

看到这里,我们去func4看看。

0000000000400fce <func4>:
  400fce:    48 83 ec 08             sub    $0x8,%rsp   # 栈指针移动
  400fd2:    89 d0                   mov    %edx,%eax    # %edx 移动到 %eax (0xe)
  400fd4:    29 f0                   sub    %esi,%eax    # %eax 减一个 %esi (0)
  400fd6:    89 c1                   mov    %eax,%ecx    # %eax 移动到 %ecx (0xe)
  400fd8:    c1 e9 1f                shr    $0x1f,%ecx  # %ecx 逻辑右移31位 (0)
  400fdb:    01 c8                   add    %ecx,%eax    # %ecx 加到 %eax (0xe)
  400fdd:    d1 f8                   sar    %eax         # %eax 算数右移1位 (0x7)
  400fdf:    8d 0c 30                lea    (%rax,%rsi,1),%ecx
  # %rax = 0x7, %rsi = 0, %ecx = 0x7
  400fe2:    39 f9                   cmp    %edi,%ecx    #
  400fe4:    7e 0c                   jle    400ff2 <func4+0x24>
  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
  400ff7:    39 f9                   cmp    %edi,%ecx
  400ff9:    7d 0c                   jge    401007 <func4+0x39>
  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

我发现,在这段程序里,我只需要让%edi大于等于且小于等于%ecx即可。也就是说只要%edi == %ecx就能直接跳过炸弹且跳出函数,让%eax为0。很简单就能算出来%ecx0x7

再看这段:

  401051:    83 7c 24 0c 00          cmpl   $0x0,0xc(%rsp)
  401056:    74 05                   je     40105d <phase_4+0x51>

也就是说,第二个数以一定要是0,才可以不踩下面的炸弹。

答案就是:

7 0

做到这的时候被教授嘲讽了好难受呀QAQ……

嗯,不管了,先贴代码:

0000000000401062 <phase_5>:
  401062:    53                      push   %rbx
  401063:    48 83 ec 20             sub    $0x20,%rsp
  401067:    48 89 fb                mov    %rdi,%rbx
  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
  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
  40108f:    88 0c 24                mov    %cl,(%rsp)
  401092:    48 8b 14 24             mov    (%rsp),%rdx
  401096:    83 e2 0f                and    $0xf,%edx
  401099:    0f b6 92 b0 24 40 00    movzbl 0x4024b0(%rdx),%edx
  4010a0:    88 54 04 10             mov    %dl,0x10(%rsp,%rax,1)
  4010a4:    48 83 c0 01             add    $0x1,%rax
  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
  4010b8:    48 8d 7c 24 10          lea    0x10(%rsp),%rdi
  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   

咱们输入的东西存进了%rdi。然后这一段:

  40107a:    e8 9c 02 00 00          callq  40131b <string_length>
  40107f:    83 f8 06                cmp    $0x6,%eax
  401082:    74 4e                   je     4010d2 <phase_5+0x70>

很明显告诉我们,要输入6个数字。

这段代码:

  40108b:    0f b6 0c 03             movzbl (%rbx,%rax,1),%ecx
  40108f:    88 0c 24                mov    %cl,(%rsp)
  401092:    48 8b 14 24             mov    (%rsp),%rdx
  401096:    83 e2 0f                and    $0xf,%edx
  401099:    0f b6 92 b0 24 40 00    movzbl 0x4024b0(%rdx),%edx
  4010a0:    88 54 04 10             mov    %dl,0x10(%rsp,%rax,1)
  4010a4:    48 83 c0 01             add    $0x1,%rax
  4010a8:    48 83 f8 06             cmp    $0x6,%rax
  4010ac:    75 dd                   jne    40108b <phase_5+0x29>

就很明显啦,要循环6次把数据放进栈里。

注意这里:

  401096:    83 e2 0f                and    $0xf,%edx
  401099:    0f b6 92 b0 24 40 00    movzbl 0x4024b0(%rdx),%edx
  4010a0:    88 54 04 10             mov    %dl,0x10(%rsp,%rax,1)

这里的意思是,只看后四位的数据,在0x4024b0中找这个数据对应的位置的字母,再放进栈中。

于是你跑到这个位置去看数据,就会发现那句金句:

(之前我就是直接复制flyers到里面去,然后奇怪了半天……)

这里还是没懂对吧,往下看到这:

  4010ae:    c6 44 24 16 00          movb   $0x0,0x16(%rsp)
  4010b3:    be 5e 24 40 00          mov    $0x40245e,%esi
  4010b8:    48 8d 7c 24 10          lea    0x10(%rsp),%rdi
  4010bd:    e8 76 02 00 00          callq  401338 <strings_not_equal>

想起来之前做的实验,我猜你赶紧回去看0x40245e存了个什么样的字符串。反正你会得到一个flyers的字符串。

要让栈里的数据和这个字符串相同哦~也就是说要根据上面那个数组的数据,对着这个字符串确定索引。

最终你的答案应该就是:

9?>567

这个部分真的是极其复杂……

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            # r13存储栈指针
  401103:    48 89 e6                mov    %rsp,%rsi            # rsi存储栈指针
  401106:    e8 51 03 00 00          callq  40145c <read_six_numbers># 读入6个数进栈中
  40110b:    49 89 e6                mov    %rsp,%r14            # r14存储栈指针
  40110e:    41 bc 00 00 00 00       mov    $0x0,%r12d          # r12存储0
  401114:    4c 89 ed                mov    %r13,%rbp            # rbp存储r13栈指针的当前的位置
  401117:    41 8b 45 00             mov    0x0(%r13),%eax       # 当前指针位置放置的数据放进eax
  40111b:    83 e8 01                sub    $0x1,%eax           # eax的数据减1
  40111e:    83 f8 05                cmp    $0x5,%eax
  401121:    76 05                   jbe    401128 <phase_6+0x34># eax要小于6,否则引爆炸弹
  401123:    e8 12 03 00 00          callq  40143a <explode_bomb># 输入数据总数要1-6之间
  401128:    41 83 c4 01             add    $0x1,%r12d          # r12 = 1, 2,3,4,5,6
  40112c:    41 83 fc 06             cmp    $0x6,%r12d
  401130:    74 21                   je     401153 <phase_6+0x5f># 当r12为6时跳出循环
  401132:    44 89 e3                mov    %r12d,%ebx           # 将r12的数据放进ebx
  401135:    48 63 c3                movslq %ebx,%rax            # ebx的数据放进rax
  401138:    8b 04 84                mov    (%rsp,%rax,4),%eax   # 将栈中的6个数分别放进eax
  40113b:    39 45 00                cmp    %eax,0x0(%rbp)
  40113e:    75 05                   jne    401145 <phase_6+0x51># 剩余5个数要都不跟第一个数当前栈指针的数相同才能不踩炸弹
  401140:    e8 f5 02 00 00          callq  40143a <explode_bomb># 6个数要各不相同,且取值为1-6
  401145:    83 c3 01                add    $0x1,%ebx           # ebx加1
  401148:    83 fb 05                cmp    $0x5,%ebx
  40114b:    7e e8                   jle    401135 <phase_6+0x41># 跳回循环起点,只要没做满6次
  40114d:    49 83 c5 04             add    $0x4,%r13           # r13栈指针指向下一个数
  401151:    eb c1                   jmp    401114 <phase_6+0x20># 跳回循环起点
  401153:    48 8d 74 24 18          lea    0x18(%rsp),%rsi      # 将栈指针中6个数据后的指针存在rsi
  401158:    4c 89 f0                mov    %r14,%rax            # r14的栈指针存到rax里
  40115b:    b9 07 00 00 00          mov    $0x7,%ecx           # ecx存进一个值为7
  401160:    89 ca                   mov    %ecx,%edx            # ecx的值放进edx,值为7
  401162:    2b 10                   sub    (%rax),%edx          # 将rax指针中存放的数,变成7-x,放进edx
  401164:    89 10                   mov    %edx,(%rax)          # 将栈指针指向的值更新为7-x
  401166:    48 83 c0 04             add    $0x4,%rax           # rax指针移动到下一个数据
  40116a:    48 39 f0                cmp    %rsi,%rax
  40116d:    75 f1                   jne    401160 <phase_6+0x6c># 循环更新所有的数
  40116f:    be 00 00 00 00          mov    $0x0,%esi           # esi存储0
  401174:    eb 21                   jmp    401197 <phase_6+0xa3># 跳转,163
  401176:    48 8b 52 08             mov    0x8(%rdx),%rdx       # rdx链表指向下一位
  40117a:    83 c0 01                add    $0x1,%eax           # eax+1
  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      # edx 存放链表的起点
  401188:    48 89 54 74 20          mov    %rdx,0x20(%rsp,%rsi,2)   # 在栈+32的位置放置地址
  40118d:    48 83 c6 04             add    $0x4,%rsi           # rsi+4
  401191:    48 83 fe 18             cmp    $0x18,%rsi
  401195:    74 14                   je     4011ab <phase_6+0xb7># 要进行6次后才到下一阶段
  401197:    8b 0c 34                mov    (%rsp,%rsi,1),%ecx   # 栈指针指向的第一个数存储进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           # eax中存1
  4011a4:    ba d0 32 60 00          mov    $0x6032d0,%edx      # edx存链表起点
  4011a9:    eb cb                   jmp    401176 <phase_6+0x82># 数字要找到对应的点放
  4011ab:    48 8b 5c 24 20          mov    0x20(%rsp),%rbx      # 将链表起点的指针放到rbx
  4011b0:    48 8d 44 24 28          lea    0x28(%rsp),%rax      # 将第二个点的指针放进rax
  4011b5:    48 8d 74 24 50          lea    0x50(%rsp),%rsi      # 将最后一个点指针放进rsi
  4011ba:    48 89 d9                mov    %rbx,%rcx            # 将rbx指针放进rcx
  4011bd:    48 8b 10                mov    (%rax),%rdx          # 将rax存放的节点值放进rdx
  4011c0:    48 89 51 08             mov    %rdx,0x8(%rcx)       # 将rdx存到rcx后继
  4011c4:    48 83 c0 08             add    $0x8,%rax           # rax向下个节点运动
  4011c8:    48 39 f0                cmp    %rsi,%rax
  4011cb:    74 05                   je     4011d2 <phase_6+0xde># 做6次,把链表更新好
  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)      # 将rdx后继置null
  4011d9:    00
  4011da:    bd 05 00 00 00          mov    $0x5,%ebp           # 5进ebp
  4011df:    48 8b 43 08             mov    0x8(%rbx),%rax       # 链表起点第二个放进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

不一边看一边写注释是真的看不懂……

上面的注释也写的差不多了,这段代码主要是分几部分:

  1. 读入6个数,且6个数必须是在1-6之间各不相同的数,否则爆炸。
  2. 将所有的数都更新成与7的模。
  3. 按照输入顺序,将$0x6032d0中的链表存进栈中,要求链表的结点值要和输入的数字顺序相同。
  4. 将链表重新连接起来。
  5. 要求链表中每个节点的值的后半部分要从大到小排列。

然后可以反推了,根据这个链表的后半部分,可以得到序列:

3 4 5 6 1 2

由于要取模,所以需要输入的序列是:

4 3 2 1 6 5

好像我现在才知道有这个阶段,先去看看~

手机扫一扫

移动阅读更方便

阿里云服务器
腾讯云服务器
七牛云服务器