【发布时间】:2018-02-23 03:53:12
【问题描述】:
这是我组装的第一个月,我的任务是解决臭名昭著的炸弹实验室。我今天取得了一些重大进展,但对于我的生活,我无法弄清楚第 4 阶段到底发生了什么。我可以说它需要两个整数的输入(我相信第二个应该是35?)但我无法弄清楚它调用的递归函数的某些部分。我已经尽我所能评论了每一行。
这是第四阶段的组装:
000000000040103f <phase_4>:
40103f: 48 83 ec 18 sub $0x18,%rsp //INPUT 2 INTEGERS //ANSWER =
401043: 48 8d 4c 24 08 lea 0x8(%rsp),%rcx
401048: 48 8d 54 24 0c lea 0xc(%rsp),%rdx
40104d: be 0d 28 40 00 mov $0x40280d,%esi //This is our numbers, they get put into %esi
401052: b8 00 00 00 00 mov $0x0,%eax //%eax = 0
401057: e8 d4 fb ff ff callq 400c30 <__isoc99_sscanf@plt> //scan in the input
40105c: 83 f8 02 cmp $0x2,%eax //make sure there are two integers
40105f: 75 07 jne 401068 <phase_4+0x29> //if there are not 2 integers, jump to bomb
401061: 83 7c 24 0c 0e cmpl $0xe,0xc(%rsp) // 0xc(%rsp) == 12? (x/s $rsp gives "h\342\377\377\377\177")
401066: 76 05 jbe 40106d <phase_4+0x2e> //jump past the detonation
401068: e8 17 05 00 00 callq 401584 <explode_bomb> //BOOM
40106d: ba 0e 00 00 00 mov $0xe,%edx //%edx = 0xe (14)
401072: be 00 00 00 00 mov $0x0,%esi //%esi = 0
401077: 8b 7c 24 0c mov 0xc(%rsp),%edi //%edi = 0xc(%rsp)
40107b: e8 8c ff ff ff callq 40100c <func4> //call fun4
401080: 83 f8 23 cmp $0x23,%eax //%eax == 35?
401083: 75 07 jne 40108c <phase_4+0x4d> //if %eax != 35, jump to detonation
401085: 83 7c 24 08 23 cmpl $0x23,0x8(%rsp) //0x8(%rsp) == 35?
40108a: 74 05 je 401091 <phase_4+0x52> //if so, jump past the detonation
40108c: e8 f3 04 00 00 callq 401584 <explode_bomb> //BOOM
401091: 48 83 c4 18 add $0x18,%rsp //%rsp = 18
401095: c3 retq //phase 4 disarmed
这是 func4 的程序集,这是一个执行一些恶作剧的递归数学函数:
000000000040100c <func4>:
40100c: 53 push %rbx
40100d: 89 d0 mov %edx,%eax //%eax = %edx
40100f: 29 f0 sub %esi,%eax //%eax -= %esi
401011: 89 c3 mov %eax,%ebx //%ebx = eax
401013: c1 eb 1f shr $0x1f,%ebx //shift %ebx right by 0x1f (31)
401016: 01 d8 add %ebx,%eax //%eax += %ebx
401018: d1 f8 sar %eax //shift %eax right by 1
40101a: 8d 1c 30 lea (%rax,%rsi,1),%ebx //???
40101d: 39 fb cmp %edi,%ebx //compare %edi and %ebx
40101f: 7e 0c jle 40102d <func4+0x21> //if %edi < %ebx, jump to 40102d
401021: 8d 53 ff lea -0x1(%rbx),%edx //???
401024: e8 e3 ff ff ff callq 40100c <func4> //RECURSE
401029: 01 d8 add %ebx,%eax //%eax += %ebx
40102b: eb 10 jmp 40103d <func4+0x31> //jump to 40103d (done)
40102d: 89 d8 mov %ebx,%eax //%eax = %ebx
40102f: 39 fb cmp %edi,%ebx //compare %edi and %ebx
401031: 7d 0a jge 40103d <func4+0x31> //if %edi > %ebx, jump to 40103d (done)
401033: 8d 73 01 lea 0x1(%rbx),%esi //???
401036: e8 d1 ff ff ff callq 40100c <func4> //RECURSE
40103b: 01 d8 add %ebx,%eax //%eax += %ebx
40103d: 5b pop %rbx //done.
40103e: c3 retq
我看到了这里发生的事情的要点(递归函数中的一堆数学。)但我真的不明白 lea 命令是什么(例如 lea (%rax,%rsi,1),%ebx ) 在这种情况下正在做。我知道它被称为“加载有效地址”以及它的作用一般,但不知道它在这里的作用。
【问题讨论】:
-
使用基础、索引和比例计算并将其放置在 EBX 中。所以它是 EBX = RAX+RSI*1。基本上将 RAX 添加到 RSI 并将其存储到 EBX。 LEA 仅表示加载有效地址。 LEA 不访问内存,它只是为了帮助计算内存地址而设计的,但本质上它可以出于任何目的进行简单的数学类型操作。
-
您可以通过查看instruction set reference了解说明的作用
-
好吧,酷。那么 0x1(%rbx),%esi 意味着 %esi = 1 * %rbx,那么呢?
-
lea 0x1(%rbx),%esi将是 ESI=1+RBX。它是位移(基础,索引,比例)。计算是位移+基数+索引*比例)。