MIPS反汇编拆炸弹

计算机系统原理的实验,参考了我的前舍友和不知道哪位同学的博客,不过写得也太简略了并且还有一些错误,更像是单纯的记录,对手头没代码的人大概没啥意义吧。所以就把我自己做时的带注释的代码贴住来吧,也不过是记录罢了。
两位同学的博客:
MIPS - 反汇编 - 拆炸弹 - bomb(如你所见直接把标题抄过来了)
bomb二进制炸弹拆除实验(MIPS)
如果有同校学弟做实验时看到这篇博客,还是希望可以先尽量尝试独立完成,实在没办法时再来参考。如有错误,欢迎指正。

前导知识

gdb操作请看:GDB汇编调试指令合集
MIPS相关知识请看:MIPS指令集及汇编完全解析

开拆前…

本实验含有六个炸弹(和一个隐藏炸弹 ),在运行程序开头,需要输入ID(学号),在之后的拆弹过程中会使用到。每个炸弹都需要输入一行数据,包括数字或字符串。需避开一个个引爆点来通关。
阅读反汇编代码时,最好能够前后联系,理解数行/一部分代码的功能。要逐渐熟练掌握MIPS指令集操作和寄存器含义,了解数据存储的位置和方式。
有???标记的是我暂时抱有疑惑的地方,可以忽视。
本文还未完成,随缘更新。

phase_1

第一个炸弹,主要是熟悉用。炸弹会调用函数strings_not_equal来比较输入字符串与存储的字符串是否相等,不需要理解该子函数的实现,只需要明白该函数的功能即可。读寄存器$a1中保存的字符串,为“Let’s begin now!”,即为我们要输入的内容。

00400900 <main>:
  ...
  400ba4: 8fdc0010  lw  gp,16(s8)
  400ba8: 0c1007fb  jal 401fec <read_line> //读取输入
  400bac: 00000000  nop
  400bb0: 8fdc0010  lw  gp,16(s8)
  400bb4: afc20020  sw  v0,32(s8) //将读得的数据存入栈
  400bb8: 8fc40020  lw  a0,32(s8) //并放入$a0中供函数phase_1使用
  400bbc: 0c10035b  jal 400d6c <phase_1>
  ...
  
00400d6c <phase_1>:
  400d6c:	27bdffe0 	addiu	sp,sp,-32 //为当前函数开辟栈空间
  400d70:	afbf001c 	sw	ra,28(sp)
  400d74:	afbe0018 	sw	s8,24(sp)
  400d78:	03a0f021 	move	s8,sp
  400d7c:	afc40020 	sw	a0,32(s8) //将$a0的内容存入栈
  400d80:	8fc40020 	lw	a0,32(s8)
  400d84:	3c020040 	lui	v0,0x40
  400d88:	2445276c 	addiu	a1,v0,10092 //加载参数到$a1
  400d8c:	0c10073e 	jal	401cf8 <strings_not_equal> //比较字符串$a0和$a1,不相等则$v0 = 1,否则$v0 = 1
  400d90:	00000000 	nop
  400d94:	10400003 	beqz	v0,400da4 <phase_1+0x38> //若$v0 == 0则跳至0x00400da4处
  400d98:	00000000 	nop
  400d9c:	0c10087c 	jal	4021f0 <explode_bomb> //否则若$v0 == 0则爆炸
  400da0:	00000000 	nop
  400da4:	03c0e821 	move	sp,s8
  400da8:	8fbf001c 	lw	ra,28(sp)
  400dac:	8fbe0018 	lw	s8,24(sp)
  400db0:	27bd0020 	addiu	sp,sp,32
  400db4:	03e00008 	jr	ra
  400db8:	00000000 	nop

phase_2

该炸弹要求我们输入六个数字(看函数名称识功能,第1个数必须为1),之后进入循环中一个个对这些数字进行处理,将第i个数分别与学号倒数i位相乘结果与第i+1个数比较判断是否相等,意味着我们输入的六个数就是对ID后五位累乘的序列。为什么知道是ID后五位?读寄存器得到的。ID不够五位?那就相当于定义了一个变量却没有赋值,一样能解决这个炸弹。这个炸弹不理解代码强行在0x400e80处读$a0的值并反复尝试令其与$v0相等也能解决,当然不推荐就是了。

00400dbc <phase_2>:
  400dbc:	27bdffc0 	addiu	sp,sp,-64
  400dc0:	afbf003c 	sw	ra,60(sp)
  400dc4:	afbe0038 	sw	s8,56(sp)
  400dc8:	03a0f021 	move	s8,sp
  400dcc:	3c1c0042 	lui	gp,0x42
  400dd0:	279cb190 	addiu	gp,gp,-20080
  400dd4:	afbc0010 	sw	gp,16(sp)
  400dd8:	afc40040 	sw	a0,64(s8)
  400ddc:	27c2001c 	addiu	v0,s8,28
  400de0:	8fc40040 	lw	a0,64(s8)
  400de4:	00402821 	move	a1,v0
  400de8:	0c1006ea 	jal	401ba8 <read_six_numbers> //读入6个数字
  400dec:	00000000 	nop
  400df0:	8fdc0010 	lw	gp,16(s8)
  400df4:	8fc3001c 	lw	v1,28(s8) //m[$s8+28]存有读入的第一个数,将其存入$v1
  400df8:	24020001 	li	v0,1
  400dfc:	10620004 	beq	v1,v0,400e10 <phase_2+0x54> //判定$v1是否为1,不是则引爆
  400e00:	00000000 	nop
  400e04:	0c10087c 	jal	4021f0 <explode_bomb>
  400e08:	00000000 	nop
  400e0c:	8fdc0010 	lw	gp,16(s8)
  400e10:	24020001 	li	v0,1 //设定循环单次表达式$v0 = 1(i = 1)
  400e14:	afc20018 	sw	v0,24(s8) //将$v0(i)存入栈
  400e18:	10000023 	b	400ea8 <phase_2+0xec> //循环开始,跳至条件表达式
  400e1c:	00000000 	nop
  400e20:	8fc20018 	lw	v0,24(s8) //将之前存在栈中的变量i取出
  400e24:	00000000 	nop
  400e28:	2442ffff 	addiu	v0,v0,-1 //$v0自减
  400e2c:	00021080 	sll	v0,v0,0x2 //$v0 = $v0 * 4(拓到1 int长度)
  400e30:	27c30018 	addiu	v1,s8,24 //第i个数的存放位置为m[$s8 + 24 + i * 4](一个int型变量占4个字节)
  400e34:	00621021 	addu	v0,v1,v0
  400e38:	8c440004 	lw	a0,4(v0) //将第i个数的值存入$a0(所以前面自减有意义吗)
  400e3c:	2403000c 	li	v1,12
  400e40:	8fc20018 	lw	v0,24(s8) //将之前存在栈中的变量i取出
  400e44:	00000000 	nop
  400e48:	00621023 	subu	v0,v1,v0 //$v0 = $v1(12) - $v0(i)
  400e4c:	8f83806c 	lw	v1,-32660(gp) //读得输入的学号
  400e50:	00021080 	sll	v0,v0,0x2 //$v0 = $v0 * 4(拓到1 int长度)
  400e54:	00621021 	addu	v0,v1,v0 //$v0 = $v1 + $v0
  400e58:	8c420000 	lw	v0,0(v0) //将学号的倒数i位读入$v0中
  400e5c:	00000000 	nop
  400e60:	00820018 	mult	a0,v0 //$a0与$v0相乘
  400e64:	00002012 	mflo	a0 //将结果存入$a0
  400e68:	8fc20018 	lw	v0,24(s8) //将之前存在栈中的变量i取出
  400e6c:	00000000 	nop
  400e70:	00021080 	sll	v0,v0,0x2 //$v0 = $v0 * 4(拓到1 int长度)
  400e74:	27c30018 	addiu	v1,s8,24 //第i个数得存放位置为m[$s8 + 24 + i * 4](一个int型变量占4个字节)
  400e78:	00621021 	addu	v0,v1,v0 //得到第i个数的位置
  400e7c:	8c420004 	lw	v0,4(v0) //将第i + 1个数的值存入$v0
  400e80:	00000000 	nop
  400e84:	10820004 	beq	a0,v0,400e98 <phase_2+0xdc> //比较$a0(第i个数与学号的倒数i位相乘的结果)与$v0(第i + 1个数),若不相等则引爆
  400e88:	00000000 	nop
  400e8c:	0c10087c 	jal	4021f0 <explode_bomb>
  400e90:	00000000 	nop
  400e94:	8fdc0010 	lw	gp,16(s8) //末尾循环体
  400e98:	8fc20018 	lw	v0,24(s8)
  400e9c:	00000000 	nop
  400ea0:	24420001 	addiu	v0,v0,1 //i自加
  400ea4:	afc20018 	sw	v0,24(s8) //将i存入栈中
  400ea8:	8fc20018 	lw	v0,24(s8)
  400eac:	00000000 	nop
  400eb0:	28420006 	slti	v0,v0,6 //判断循环是否结束,相当于i != 6(i < 6)
  400eb4:	1440ffda 	bnez	v0,400e20 <phase_2+0x64>
  400eb8:	00000000 	nop
  400ebc:	03c0e821 	move	sp,s8
  400ec0:	8fbf003c 	lw	ra,60(sp)
  400ec4:	8fbe0038 	lw	s8,56(sp)
  400ec8:	27bd0040 	addiu	sp,sp,64
  400ecc:	03e00008 	jr	ra
  400ed0:	00000000 	nop

phase_3

考察分支结构(switch…case…结构)。要求输入格式为"%d %c %d"(看调用数据时的指令得到的,word/byte的区别),第一个数就是switch语句中的变量,跳至不同的case语句(0到7共八个,超出直接引爆)。除case 3外,其他数均是要求一个数与输入的第三个数相乘的结果为指定的立即数,而case 3要求相乘结果为0。读寄存器可知该数为输入ID的最后一位。另外在每个case结构的开头都将一个字符存入栈中,在switch…case…结束后与我们输入的字符比较,令两个字符相等即可。

00400ed4 <phase_3>:
  400ed4:	27bdffc8 	addiu	sp,sp,-56
  400ed8:	afbf0034 	sw	ra,52(sp)
  400edc:	afbe0030 	sw	s8,48(sp)
  400ee0:	03a0f021 	move	s8,sp
  400ee4:	3c1c0042 	lui	gp,0x42
  400ee8:	279cb190 	addiu	gp,gp,-20080
  400eec:	afbc0018 	sw	gp,24(sp)
  400ef0:	afc40038 	sw	a0,56(s8)
  400ef4:	8fc40038 	lw	a0,56(s8)
  400ef8:	3c020040 	lui	v0,0x40
  400efc:	24452780 	addiu	a1,v0,10112
  400f00:	27c3002c 	addiu	v1,s8,44
  400f04:	27c20028 	addiu	v0,s8,40
  400f08:	27c60024 	addiu	a2,s8,36
  400f0c:	afa60010 	sw	a2,16(sp)
  400f10:	00603021 	move	a2,v1
  400f14:	00403821 	move	a3,v0
  400f18:	8f828084 	lw	v0,-32636(gp)
  400f1c:	00000000 	nop
  400f20:	0040c821 	move	t9,v0
  400f24:	0320f809 	jalr	t9
  400f28:	00000000 	nop
  400f2c:	8fdc0018 	lw	gp,24(s8)
  400f30:	28420003 	slti	v0,v0,3 //判定输入的数据个数是否为3
  400f34:	10400004 	beqz	v0,400f48 <phase_3+0x74>
  400f38:	00000000 	nop
  400f3c:	0c10087c 	jal	4021f0 <explode_bomb>
  400f40:	00000000 	nop
  400f44:	8fdc0018 	lw	gp,24(s8)
  400f48:	8fc2002c 	lw	v0,44(s8) //读入输入的第一个数至$v0
  400f4c:	00000000 	nop
  400f50:	2c430008 	sltiu	v1,v0,8 //判断$v0是否小于8,是则继续,否则引爆
  400f54:	1060008e 	beqz	v1,401190 <phase_3+0x2bc>
  400f58:	00000000 	nop
  400f5c:	00021880 	sll	v1,v0,0x2 //$v1 = $v0 * 4,拓至1 int型变量长度
  400f60:	3c020040 	lui	v0,0x40
  400f64:	2442278c 	addiu	v0,v0,10124
  400f68:	00621021 	addu	v0,v1,v0
  400f6c:	8c420000 	lw	v0,0(v0) //$v0对应case语句的地址,用x $v0查看
  400f70:	00000000 	nop
  400f74:	00400008 	jr	v0 //switch语句,跳至相应的case语句
  400f78:	00000000 	nop //case 0:
  400f7c:	24020071 	li	v0,113 //q的ASCII码
  400f80:	a3c20020 	sb	v0,32(s8) //存入1byte的数据
  400f84:	8f82806c 	lw	v0,-32660(gp)
  400f88:	00000000 	nop
  400f8c:	8c43002c 	lw	v1,44(v0) //读入学号的最后一位
  400f90:	8fc20024 	lw	v0,36(s8) //读入输入数据的第三个数
  400f94:	00000000 	nop
  400f98:	00620018 	mult	v1,v0
  400f9c:	00001812 	mflo	v1 //$v1 = $v1 * $v0
  400fa0:	24020309 	li	v0,777 //判断是否为777(=3*=7*111),是则break,否则引爆
  400fa4:	10620081 	beq	v1,v0,4011ac <phase_3+0x2d8>
  400fa8:	00000000 	nop
  400fac:	0c10087c 	jal	4021f0 <explode_bomb>
  400fb0:	00000000 	nop
  400fb4:	8fdc0018 	lw	gp,24(s8)
  400fb8:	1000008f 	b	4011f8 <phase_3+0x324>
  400fbc:	00000000 	nop //case 1:
  400fc0:	24020062 	li	v0,98 //b的ASCII码
  400fc4:	a3c20020 	sb	v0,32(s8) //存入1byte的数据
  400fc8:	8f82806c 	lw	v0,-32660(gp)
  400fcc:	00000000 	nop
  400fd0:	8c43002c 	lw	v1,44(v0) //读入学号的最后一位
  400fd4:	8fc20024 	lw	v0,36(s8) //读入输入数据的第三个数
  400fd8:	00000000 	nop
  400fdc:	00620018 	mult	v1,v0
  400fe0:	00001812 	mflo	v1 //$v1 = $v1 * $v0
  400fe4:	240200d6 	li	v0,214 //判断是否为214(=2*107),是则break,否则引爆
  400fe8:	10620073 	beq	v1,v0,4011b8 <phase_3+0x2e4>
  400fec:	00000000 	nop
  400ff0:	0c10087c 	jal	4021f0 <explode_bomb>
  400ff4:	00000000 	nop
  400ff8:	8fdc0018 	lw	gp,24(s8)
  400ffc:	1000007e 	b	4011f8 <phase_3+0x324>
  401000:	00000000 	nop //case 2:
  401004:	24020062 	li	v0,98 //b的ASCII码
  401008:	a3c20020 	sb	v0,32(s8) //存入1byte的数据
  40100c:	8f82806c 	lw	v0,-32660(gp)
  401010:	00000000 	nop
  401014:	8c43002c 	lw	v1,44(v0) //读入学号的最后一位
  401018:	8fc20024 	lw	v0,36(s8) //读入输入数据的第三个数
  40101c:	00000000 	nop
  401020:	00620018 	mult	v1,v0
  401024:	00001812 	mflo	v1 //$v1 = $v1 * $v0
  401028:	240202f3 	li	v0,755 //判断是否为755(=5*151),是则break,否则引爆
  40102c:	10620065 	beq	v1,v0,4011c4 <phase_3+0x2f0>
  401030:	00000000 	nop
  401034:	0c10087c 	jal	4021f0 <explode_bomb>
  401038:	00000000 	nop
  40103c:	8fdc0018 	lw	gp,24(s8)
  401040:	1000006d 	b	4011f8 <phase_3+0x324>
  401044:	00000000 	nop //case 3:
  401048:	2402006b 	li	v0,107 //k的ASCII码
  40104c:	a3c20020 	sb	v0,32(s8) //存入1byte的数据
  401050:	8f82806c 	lw	v0,-32660(gp)
  401054:	00000000 	nop
  401058:	8c43002c 	lw	v1,44(v0) //读入学号的最后一位
  40105c:	8fc20024 	lw	v0,36(s8) //读入输入数据的第三个数
  401060:	00000000 	nop
  401064:	00620018 	mult	v1,v0
  401068:	00001012 	mflo	v0 //$v0 = $v1 * $v0
  40106c:	10400058 	beqz	v0,4011d0 <phase_3+0x2fc> //判断$v0是否等于0,是则break,否则引爆
  401070:	00000000 	nop
  401074:	0c10087c 	jal	4021f0 <explode_bomb>
  401078:	00000000 	nop
  40107c:	8fdc0018 	lw	gp,24(s8)
  401080:	1000005d 	b	4011f8 <phase_3+0x324>
  401084:	00000000 	nop //case 4:
  401088:	2402006f 	li	v0,111 //o的ASCII码
  40108c:	a3c20020 	sb	v0,32(s8) //存入1byte的数据
  401090:	8f82806c 	lw	v0,-32660(gp)
  401094:	00000000 	nop
  401098:	8c43002c 	lw	v1,44(v0) //读入学号的最后一位
  40109c:	8fc20024 	lw	v0,36(s8) //读入输入数据的第三个数
  4010a0:	00000000 	nop
  4010a4:	00620018 	mult	v1,v0
  4010a8:	00001812 	mflo	v1 //$v1 = $v1 * $v0
  4010ac:	240200e4 	li	v0,228 //判断是否为228(=2*114=4*57),是则break,否则引爆 ???
  4010b0:	1062004a 	beq	v1,v0,4011dc <phase_3+0x308>
  4010b4:	00000000 	nop
  4010b8:	0c10087c 	jal	4021f0 <explode_bomb>
  4010bc:	00000000 	nop
  4010c0:	8fdc0018 	lw	gp,24(s8)
  4010c4:	1000004c 	b	4011f8 <phase_3+0x324>
  4010c8:	00000000 	nop //case 5:
  4010cc:	24020074 	li	v0,116 //t的ASCII码
  4010d0:	a3c20020 	sb	v0,32(s8) //存入1byte的数据
  4010d4:	8f82806c 	lw	v0,-32660(gp)
  4010d8:	00000000 	nop
  4010dc:	8c43002c 	lw	v1,44(v0) //读入学号的最后一位
  4010e0:	8fc20024 	lw	v0,36(s8) //读入输入数据的第三个数
  4010e4:	00000000 	nop
  4010e8:	00620018 	mult	v1,v0
  4010ec:	00001812 	mflo	v1 //$v1 = $v1 * $v0
  4010f0:	24020201 	li	v0,513 //判断是否为513(=3*171=9*57),是则break,否则引爆
  4010f4:	1062003c 	beq	v1,v0,4011e8 <phase_3+0x314>
  4010f8:	00000000 	nop
  4010fc:	0c10087c 	jal	4021f0 <explode_bomb>
  401100:	00000000 	nop
  401104:	8fdc0018 	lw	gp,24(s8)
  401108:	1000003b 	b	4011f8 <phase_3+0x324>
  40110c:	00000000 	nop //case 6:
  401110:	24020076 	li	v0,118 //v的ASCII码
  401114:	a3c20020 	sb	v0,32(s8) //存入1byte的数据
  401118:	8f82806c 	lw	v0,-32660(gp)
  40111c:	00000000 	nop
  401120:	8c43002c 	lw	v1,44(v0) //读入学号的最后一位
  401124:	8fc20024 	lw	v0,36(s8) //读入输入数据的第三个数
  401128:	00000000 	nop
  40112c:	00620018 	mult	v1,v0
  401130:	00001812 	mflo	v1 //$v1 = $v1 * $v0
  401134:	2402030c 	li	v0,780 //判断是否为780(=2*390=3*260=4*195=5*156=6*130),是则break,否则引爆
  401138:	10620004 	beq	v1,v0,40114c <phase_3+0x278>
  40113c:	00000000 	nop
  401140:	0c10087c 	jal	4021f0 <explode_bomb>
  401144:	00000000 	nop //case 7:
  401148:	8fdc0018 	lw	gp,24(s8) ???
  40114c:	24020062 	li	v0,98 //b的ASCII码
  401150:	a3c20020 	sb	v0,32(s8) //存入1byte的数据
  401154:	8f82806c 	lw	v0,-32660(gp)
  401158:	00000000 	nop
  40115c:	8c43002c 	lw	v1,44(v0) //读入学号的最后一位
  401160:	8fc20024 	lw	v0,36(s8) //读入输入数据的第三个数
  401164:	00000000 	nop
  401168:	00620018 	mult	v1,v0
  40116c:	00001812 	mflo	v1 //$v1 = $v1 * $v0
  401170:	24020338 	li	v0,824 //判断是否为824(=2*412=4*206),是则break,否则引爆
  401174:	1062001f 	beq	v1,v0,4011f4 <phase_3+0x320>
  401178:	00000000 	nop
  40117c:	0c10087c 	jal	4021f0 <explode_bomb>
  401180:	00000000 	nop
  401184:	8fdc0018 	lw	gp,24(s8)
  401188:	1000001b 	b	4011f8 <phase_3+0x324>
  40118c:	00000000 	nop
  401190:	24020078 	li	v0,120
  401194:	a3c20020 	sb	v0,32(s8)
  401198:	0c10087c 	jal	4021f0 <explode_bomb>
  40119c:	00000000 	nop
  4011a0:	8fdc0018 	lw	gp,24(s8)
  4011a4:	10000014 	b	4011f8 <phase_3+0x324>
  4011a8:	00000000 	nop
  4011ac:	00000000 	nop
  4011b0:	10000011 	b	4011f8 <phase_3+0x324>
  4011b4:	00000000 	nop
  4011b8:	00000000 	nop
  4011bc:	1000000e 	b	4011f8 <phase_3+0x324>
  4011c0:	00000000 	nop
  4011c4:	00000000 	nop
  4011c8:	1000000b 	b	4011f8 <phase_3+0x324>
  4011cc:	00000000 	nop
  4011d0:	00000000 	nop
  4011d4:	10000008 	b	4011f8 <phase_3+0x324>
  4011d8:	00000000 	nop
  4011dc:	00000000 	nop
  4011e0:	10000005 	b	4011f8 <phase_3+0x324>
  4011e4:	00000000 	nop
  4011e8:	00000000 	nop
  4011ec:	10000002 	b	4011f8 <phase_3+0x324>
  4011f0:	00000000 	nop
  4011f4:	00000000 	nop
  4011f8:	83c20028 	lb	v0,40(s8) //输入的第二个字符数据
  4011fc:	83c30020 	lb	v1,32(s8) //将case语句中存的字符取出
  401200:	00000000 	nop
  401204:	10620004 	beq	v1,v0,401218 <phase_3+0x344> //比较,不相等则引爆
  401208:	00000000 	nop
  40120c:	0c10087c 	jal	4021f0 <explode_bomb>
  401210:	00000000 	nop
  401214:	8fdc0018 	lw	gp,24(s8)
  401218:	03c0e821 	move	sp,s8
  40121c:	8fbf0034 	lw	ra,52(sp)
  401220:	8fbe0030 	lw	s8,48(sp)
  401224:	27bd0038 	addiu	sp,sp,56
  401228:	03e00008 	jr	ra
  40122c:	00000000 	nop

phase_4

该炸弹使用了if…else…语句和递归结构,学号最后一位的奇偶分别进入判断fun4(x)是否与8和13相等,很容易联想到斐波那契数列。而调用的fun4也是计算f(x)=f(x-1)+f(x-2),正是斐波那契数列的递归解法。那么输入的数字x就是函数fun4的参数。注意fun4定义f(0)=f(1)=1,与通常的斐波那契数列不同,所以答案为5或6。

00401230 <func4>:
  401230: 27bdffd8  addiu sp,sp,-40
  401234: afbf0024  sw  ra,36(sp)
  401238: afbe0020  sw  s8,32(sp)
  40123c: afb0001c  sw  s0,28(sp)
  401240: 03a0f021  move  s8,sp
  401244: afc40028  sw  a0,40(s8)
  401248: 8fc20028  lw  v0,40(s8)
  40124c: 00000000  nop
  401250: 28420002  slti  v0,v0,2 //判断$v0是否小于2,是则$v0 = 1
  401254: 14400011  bnez  v0,40129c <func4+0x6c> //$v0 != 0则return 1
  401258: 00000000  nop
  40125c: 8fc20028  lw  v0,40(s8)
  401260: 00000000  nop
  401264: 2442ffff  addiu v0,v0,-1
  401268: 00402021  move  a0,v0
  40126c: 0c10048c  jal 401230 <func4> //递归引用自身f(x - 1)
  401270: 00000000  nop
  401274: 00408021  move  s0,v0 //将f(x - 1)的结果存入$s0
  401278: 8fc20028  lw  v0,40(s8)
  40127c: 00000000  nop
  401280: 2442fffe  addiu v0,v0,-2
  401284: 00402021  move  a0,v0
  401288: 0c10048c  jal 401230 <func4> //递归引用自身f(x - 2)
  40128c: 00000000  nop
  401290: 02021021  addu  v0,s0,v0 //$v0 = f(x - 1) + f(x - 2),返回$v0
  401294: 10000002  b 4012a0 <func4+0x70>
  401298: 00000000  nop
  40129c: 24020001  li  v0,1 //return 1
  4012a0: 03c0e821  move  sp,s8
  4012a4: 8fbf0024  lw  ra,36(sp)
  4012a8: 8fbe0020  lw  s8,32(sp)
  4012ac: 8fb0001c  lw  s0,28(sp)
  4012b0: 27bd0028  addiu sp,sp,40
  4012b4: 03e00008  jr  ra
  4012b8: 00000000  nop

004012bc <phase_4>:
  4012bc:	27bdffd8 	addiu	sp,sp,-40
  4012c0:	afbf0024 	sw	ra,36(sp)
  4012c4:	afbe0020 	sw	s8,32(sp)
  4012c8:	03a0f021 	move	s8,sp
  4012cc:	3c1c0042 	lui	gp,0x42
  4012d0:	279cb190 	addiu	gp,gp,-20080
  4012d4:	afbc0010 	sw	gp,16(sp)
  4012d8:	afc40028 	sw	a0,40(s8)
  4012dc:	8fc30028 	lw	v1,40(s8)
  4012e0:	3c020040 	lui	v0,0x40
  4012e4:	244227ac 	addiu	v0,v0,10156
  4012e8:	00602021 	move	a0,v1
  4012ec:	00402821 	move	a1,v0
  4012f0:	27c20018 	addiu	v0,s8,24
  4012f4:	00403021 	move	a2,v0
  4012f8:	8f828084 	lw	v0,-32636(gp)
  4012fc:	00000000 	nop
  401300:	0040c821 	move	t9,v0
  401304:	0320f809 	jalr	t9
  401308:	00000000 	nop
  40130c:	8fdc0010 	lw	gp,16(s8)
  401310:	00401821 	move	v1,v0
  401314:	24020001 	li	v0,1
  401318:	14620005 	bne	v1,v0,401330 <phase_4+0x74> //$v0 != 1则引爆
  40131c:	00000000 	nop
  401320:	8fc20018 	lw	v0,24(s8)
  401324:	00000000 	nop
  401328:	1c400005 	bgtz	v0,401340 <phase_4+0x84>
  40132c:	00000000 	nop
  401330:	0c10087c 	jal	4021f0 <explode_bomb>
  401334:	00000000 	nop
  401338:	8fdc0010 	lw	gp,16(s8)
  40133c:	00000000 	nop
  401340:	8f82806c 	lw	v0,-32660(gp)
  401344:	00000000 	nop
  401348:	8c42002c 	lw	v0,44(v0) //令$v0等于学号的最后一位
  40134c:	00000000 	nop
  401350:	30420001 	andi	v0,v0,0x1 //判定奇偶
  401354:	304200ff 	andi	v0,v0,0xff
  401358:	10400010 	beqz	v0,40139c <phase_4+0xe0> //if...else...结构,奇数(1)继续,偶数(0)跳转
  40135c:	00000000 	nop
  401360:	8fc20018 	lw	v0,24(s8) //令$v0等于输入的第一个数
  401364:	00000000 	nop
  401368:	00402021 	move	a0,v0 //传入参数
  40136c:	0c10048c 	jal	401230 <func4> //计算f(x)
  401370:	00000000 	nop
  401374:	8fdc0010 	lw	gp,16(s8)
  401378:	00401821 	move	v1,v0
  40137c:	24020008 	li	v0,8
  401380:	10620013 	beq	v1,v0,4013d0 <phase_4+0x114> //f(x) = $v1 != 8则引爆,则x = 5
  401384:	00000000 	nop
  401388:	0c10087c 	jal	4021f0 <explode_bomb>
  40138c:	00000000 	nop
  401390:	8fdc0010 	lw	gp,16(s8)
  401394:	1000000e 	b	4013d0 <phase_4+0x114>
  401398:	00000000 	nop
  40139c:	8fc20018 	lw	v0,24(s8)
  4013a0:	00000000 	nop
  4013a4:	00402021 	move	a0,v0 //传入参数
  4013a8:	0c10048c 	jal	401230 <func4> //计算f(x)
  4013ac:	00000000 	nop
  4013b0:	8fdc0010 	lw	gp,16(s8)
  4013b4:	00401821 	move	v1,v0
  4013b8:	2402000d 	li	v0,13
  4013bc:	10620004 	beq	v1,v0,4013d0 <phase_4+0x114> //f(x) = $v1 != 13则引爆,则x = 6
  4013c0:	00000000 	nop
  4013c4:	0c10087c 	jal	4021f0 <explode_bomb>
  4013c8:	00000000 	nop
  4013cc:	8fdc0010 	lw	gp,16(s8)
  4013d0:	03c0e821 	move	sp,s8
  4013d4:	8fbf0024 	lw	ra,36(sp)
  4013d8:	8fbe0020 	lw	s8,32(sp)
  4013dc:	27bd0028 	addiu	sp,sp,40
  4013e0:	03e00008 	jr	ra
  4013e4:	00000000 	nop

phase_5

输入字符串,要求其长度为6。进入循环中对每个字符进行处理,获取其二进制数的后四位(即ASCII码的b3b2b1b0),一一对应程序存储的长度为16的字符串S=“isrveawhobpnutfg”,即S[b3b2b1b0],炸弹要求这个映射获得的字符串为"giants",那么输入的字符串就可以是opekma,应当也可以是其他可以映射的字符串(大概没有限制?上机验证一下就知道了)

004013e8 <phase_5>:
  4013e8:	27bdffb8 	addiu	sp,sp,-72
  4013ec:	afbf0044 	sw	ra,68(sp)
  4013f0:	afbe0040 	sw	s8,64(sp)
  4013f4:	03a0f021 	move	s8,sp
  4013f8:	afc40048 	sw	a0,72(s8) //$a0为输入的字符串,将其存入栈中
  4013fc:	8fc40048 	lw	a0,72(s8)
  401400:	0c10071e 	jal	401c78 <string_length>
  401404:	00000000 	nop
  401408:	00401821 	move	v1,v0
  40140c:	24020006 	li	v0,6
  401410:	10620003 	beq	v1,v0,401420 <phase_5+0x38> //输入字符串长度$v1 != 6则引爆
  401414:	00000000 	nop
  401418:	0c10087c 	jal	4021f0 <explode_bomb>
  40141c:	00000000 	nop
  401420:	afc00018 	sw	zero,24(s8) //i = 0
  401424:	10000020 	b	4014a8 <phase_5+0xc0>
  401428:	00000000 	nop
  40142c:	8fc20018 	lw	v0,24(s8) //读得i
  401430:	8fc30018 	lw	v1,24(s8) //读得i
  401434:	8fc40048 	lw	a0,72(s8) //从栈中取出输入的字符串(从0开始编号)
  401438:	00000000 	nop
  40143c:	00831821 	addu	v1,a0,v1
  401440:	80630000 	lb	v1,0(v1) //读取输入字符串的第i个字符
  401444:	00000000 	nop
  401448:	306300ff 	andi	v1,v1,0xff
  40144c:	3063000f 	andi	v1,v1,0xf //取字符转化为二进制数(1byte=8bit)的后四位
  401450:	00021080 	sll	v0,v0,0x2 //将i拓至1 int型变量长度
  401454:	27c40018 	addiu	a0,s8,24 //读得i的地址
  401458:	00821021 	addu	v0,a0,v0
  40145c:	ac43000c 	sw	v1,12(v0) //将字符后四位存入m[$s8 + 36 + i * 4]
  401460:	8fc40018 	lw	a0,24(s8) //读得i
  401464:	8fc20018 	lw	v0,24(s8) //读得i
  401468:	00000000 	nop
  40146c:	00021080 	sll	v0,v0,0x2 //将i拓至1 int型变量长度
  401470:	27c30018 	addiu	v1,s8,24 //读得i的地址
  401474:	00621021 	addu	v0,v1,v0
  401478:	8c43000c 	lw	v1,12(v0) //读得字符后四位,存入$v1中
  40147c:	3c020041 	lui	v0,0x41
  401480:	244230ec 	addiu	v0,v0,12524 //获取存储的字符串S(从0开始编号)的位置 $v0 = isrveawhobpnutfg
  401484:	00621021 	addu	v0,v1,v0 //得到第$v1个字符的内存地址
  401488:	80430000 	lb	v1,0(v0) //得到第$v1(输入字符串的第i个字符的后四位,即ASCII码的b3b2b1b0)个字符
  40148c:	27c20018 	addiu	v0,s8,24
  401490:	00441021 	addu	v0,v0,a0
  401494:	a0430004 	sb	v1,4(v0) //将获得的字符存入m[$s8 + 28 + i]
  401498:	8fc20018 	lw	v0,24(s8) //读得i
  40149c:	00000000 	nop
  4014a0:	24420001 	addiu	v0,v0,1 //i++
  4014a4:	afc20018 	sw	v0,24(s8)
  4014a8:	8fc20018 	lw	v0,24(s8)
  4014ac:	00000000 	nop
  4014b0:	28420006 	slti	v0,v0,6 //$v0 = ($v0 < 6 ? 1 : 0),为1再循环一次,即i < 6
  4014b4:	1440ffdd 	bnez	v0,40142c <phase_5+0x44>
  4014b8:	00000000 	nop
  4014bc:	a3c00022 	sb	zero,34(s8) //将字符串尾设为'\0'
  4014c0:	27c2001c 	addiu	v0,s8,28
  4014c4:	00402021 	move	a0,v0 //从内存中获取依靠映射从存储的字符串S中得到的字符串
  4014c8:	3c020040 	lui	v0,0x40
  4014cc:	244527b0 	addiu	a1,v0,10160 //从内存中获取用来比较的字符串
  4014d0:	0c10073e 	jal	401cf8 <strings_not_equal> //比较$a0,$a1
  4014d4:	00000000 	nop
  4014d8:	10400003 	beqz	v0,4014e8 <phase_5+0x100>
  4014dc:	00000000 	nop
  4014e0:	0c10087c 	jal	4021f0 <explode_bomb>
  4014e4:	00000000 	nop
  4014e8:	03c0e821 	move	sp,s8
  4014ec:	8fbf0044 	lw	ra,68(sp)
  4014f0:	8fbe0040 	lw	s8,64(sp)
  4014f4:	27bd0048 	addiu	sp,sp,72
  4014f8:	03e00008 	jr	ra
  4014fc:	00000000 	nop

phase_6

b* 0x4016e0
r
//node[] = {0fd, 2d5, 12d, 3e5, 0d4, 1b0}
x $v1 //node[i]
c
x $v1
c
x $v1
c
x $v1
c
x $v1
c
x $v1
c



00401500 <phase_6>:
  401500:	27bdffa0 	addiu	sp,sp,-96
  401504:	afbf005c 	sw	ra,92(sp)
  401508:	afbe0058 	sw	s8,88(sp)
  40150c:	03a0f021 	move	s8,sp
  401510:	3c1c0042 	lui	gp,0x42
  401514:	279cb190 	addiu	gp,gp,-20080
  401518:	afbc0010 	sw	gp,16(sp)
  40151c:	afc40060 	sw	a0,96(s8)
  401520:	3c020041 	lui	v0,0x41
  401524:	24423130 	addiu	v0,v0,12592
  401528:	afc20020 	sw	v0,32(s8)
  40152c:	27c20024 	addiu	v0,s8,36
  401530:	8fc40060 	lw	a0,96(s8)
  401534:	00402821 	move	a1,v0
  401538:	0c1006ea 	jal	401ba8 <read_six_numbers> # 输入六个数字
  40153c:	00000000 	nop  # 第一层循环的初始条件设定
  401540:	8fdc0010 	lw	gp,16(s8)
  401544:	afc0001c 	sw	zero,28(s8) # i = 0
  401548:	1000003c 	b	40163c <phase_6+0x13c> # 跳至0x40163c处条件判断处
  40154c:	00000000 	nop # 第一层循环中间循环体开始
  401550:	8fc2001c 	lw	v0,28(s8) # 获取i
  401554:	00000000 	nop
  401558:	00021080 	sll	v0,v0,0x2 #拓至1int长度
  40155c:	27c30018 	addiu	v1,s8,24
  401560:	00621021 	addu	v0,v1,v0
  401564:	8c42000c 	lw	v0,12(v0) # 得到输入的第i个数
  401568:	00000000 	nop
  40156c:	28420007 	slti	v0,v0,7 # 判断第i个数是否小于7
  401570:	1040000a 	beqz	v0,40159c <phase_6+0x9c> # 否则引爆
  401574:	00000000 	nop
  401578:	8fc2001c 	lw	v0,28(s8)
  40157c:	00000000 	nop
  401580:	00021080 	sll	v0,v0,0x2
  401584:	27c30018 	addiu	v1,s8,24
  401588:	00621021 	addu	v0,v1,v0
  40158c:	8c42000c 	lw	v0,12(v0)
  401590:	00000000 	nop
  401594:	1c400004 	bgtz	v0,4015a8 <phase_6+0xa8> # 判断第i个数是否大于0,否则引爆
  401598:	00000000 	nop
  40159c:	0c10087c 	jal	4021f0 <explode_bomb>
  4015a0:	00000000 	nop
  4015a4:	8fdc0010 	lw	gp,16(s8)
  4015a8:	8fc2001c 	lw	v0,28(s8)
  4015ac:	00000000 	nop # 第二层循环的初始条件设定
  4015b0:	24420001 	addiu	v0,v0,1 # j  = i + 1
  4015b4:	afc20018 	sw	v0,24(s8) # 将j存至m[$s8 + 24]处
  4015b8:	10000017 	b	401618 <phase_6+0x118> # 跳至0x401618条件判断处
  4015bc:	00000000 	nop # 第二层循环中间循环体开始
  4015c0:	8fc2001c 	lw	v0,28(s8) # 获取i
  4015c4:	00000000 	nop
  4015c8:	00021080 	sll	v0,v0,0x2
  4015cc:	27c30018 	addiu	v1,s8,24
  4015d0:	00621021 	addu	v0,v1,v0
  4015d4:	8c43000c 	lw	v1,12(v0) # 获取第i个数
  4015d8:	8fc20018 	lw	v0,24(s8) # 获取j
  4015dc:	00000000 	nop
  4015e0:	00021080 	sll	v0,v0,0x2
  4015e4:	27c40018 	addiu	a0,s8,24
  4015e8:	00821021 	addu	v0,a0,v0
  4015ec:	8c42000c 	lw	v0,12(v0) # 获取第j个数
  4015f0:	00000000 	nop
  4015f4:	14620004 	bne	v1,v0,401608 <phase_6+0x108> #判断第i个数和第j个数是否不相等,否则爆炸
  4015f8:	00000000 	nop
  4015fc:	0c10087c 	jal	4021f0 <explode_bomb>
  401600:	00000000 	nop
  401604:	8fdc0010 	lw	gp,16(s8)
  401608:	8fc20018 	lw	v0,24(s8)
  40160c:	00000000 	nop # 第二层循环末尾循环体
  401610:	24420001 	addiu	v0,v0,1 # j++
  401614:	afc20018 	sw	v0,24(s8)
  401618:	8fc20018 	lw	v0,24(s8) # 第二层循环条件判断处
  40161c:	00000000 	nop
  401620:	28420006 	slti	v0,v0,6 # 当j < 6时,继续循环
  401624:	1440ffe6 	bnez	v0,4015c0 <phase_6+0xc0>
  401628:	00000000 	nop
  40162c:	8fc2001c 	lw	v0,28(s8) # 获取i
  401630:	00000000 	nop # 第一层循环末尾循环体
  401634:	24420001 	addiu	v0,v0,1 # i++
  401638:	afc2001c 	sw	v0,28(s8)
  40163c:	8fc2001c 	lw	v0,28(s8) # 第一层循环条件判断处
  401640:	00000000 	nop
  401644:	28420006 	slti	v0,v0,6 # 当i < 6 时,继续循环
  401648:	1440ffc1 	bnez	v0,401550 <phase_6+0x50>
  40164c:	00000000 	nop # 第一层循环的初始条件 
  401650:	afc0001c 	sw	zero,28(s8) # i = 0
  401654:	10000028 	b	4016f8 <phase_6+0x1f8> # 跳至条件判断处
  401658:	00000000 	nop # 第二层循环的初始条件
  40165c:	3c020041 	lui	v0,0x41
  401660:	24423130 	addiu	v0,v0,12592 # 令$v0等于&firstnode = 0x413130
  401664:	afc20020 	sw	v0,32(s8) # m[$s8 + 32] = &firstnode
  401668:	24020001 	li	v0,1 # j = 1
  40166c:	afc20018 	sw	v0,24(s8)
  401670:	1000000a 	b	40169c <phase_6+0x19c> # 跳至条件判断处
  401674:	00000000 	nop
  401678:	8fc20020 	lw	v0,32(s8) # 取得&node
  40167c:	00000000 	nop
  401680:	8c420008 	lw	v0,8(v0) #  $v0 = m[$v0 + 8]
  401684:	00000000 	nop
  401688:	afc20020 	sw	v0,32(s8) # node = node->next
  40168c:	8fc20018 	lw	v0,24(s8) # 取得j
  401690:	00000000 	nop
  401694:	24420001 	addiu	v0,v0,1 # j++
  401698:	afc20018 	sw	v0,24(s8)
  40169c:	8fc2001c 	lw	v0,28(s8) # 取得i
  4016a0:	00000000 	nop
  4016a4:	00021080 	sll	v0,v0,0x2
  4016a8:	27c30018 	addiu	v1,s8,24
  4016ac:	00621021 	addu	v0,v1,v0
  4016b0:	8c43000c 	lw	v1,12(v0) # 取得输入的第i个数
  4016b4:	8fc20018 	lw	v0,24(s8)
  4016b8:	00000000 	nop
  4016bc:	0043102a 	slt	v0,v0,v1 # 判断j是否小于输入的第i个数,是则循环继续
  4016c0:	1440ffed 	bnez	v0,401678 <phase_6+0x178>
  4016c4:	00000000 	nop
  4016c8:	8fc2001c 	lw	v0,28(s8) # 取得i
  4016cc:	00000000 	nop
  4016d0:	00021080 	sll	v0,v0,0x2
  4016d4:	27c30018 	addiu	v1,s8,24
  4016d8:	00621021 	addu	v0,v1,v0
  4016dc:	8fc30020 	lw	v1,32(s8) # 将node = [链表的第j/【输入的第i个数】个取出
  4016e0:	00000000 	nop
  4016e4:	ac430024 	sw	v1,36(v0) # 存入数组res的res[i]中
  4016e8:	8fc2001c 	lw	v0,28(s8)
  4016ec:	00000000 	nop
  4016f0:	24420001 	addiu	v0,v0,1
  4016f4:	afc2001c 	sw	v0,28(s8)
  4016f8:	8fc2001c 	lw	v0,28(s8) # 条件判断处
  4016fc:	00000000 	nop
  401700:	28420006 	slti	v0,v0,6 # i < 6 则循环继续
  401704:	1440ffd5 	bnez	v0,40165c <phase_6+0x15c>
  401708:	00000000 	nop
  40170c:	8fc2003c 	lw	v0,60(s8)
  401710:	00000000 	nop
  401714:	afc20020 	sw	v0,32(s8) # node = firstnode ???
  401718:	24020001 	li	v0,1
  40171c:	afc2001c 	sw	v0,28(s8) # i = 1
  401720:	10000016 	b	40177c <phase_6+0x27c>
  401724:	00000000 	nop # 循环开始
  401728:	8fc2001c 	lw	v0,28(s8) # 取得i
  40172c:	00000000 	nop
  401730:	00021080 	sll	v0,v0,0x2
  401734:	27c30018 	addiu	v1,s8,24
  401738:	00621021 	addu	v0,v1,v0
  40173c:	8c430024 	lw	v1,36(v0) # 取得res[i]
  401740:	8fc20020 	lw	v0,32(s8) # 取得node
  401744:	00000000 	nop
  401748:	ac430008 	sw	v1,8(v0) # node->next = res[i]
  40174c:	8fc2001c 	lw	v0,28(s8) # 取得i
  401750:	00000000 	nop
  401754:	00021080 	sll	v0,v0,0x2
  401758:	27c30018 	addiu	v1,s8,24
  40175c:	00621021 	addu	v0,v1,v0
  401760:	8c420024 	lw	v0,36(v0) # 取得res[i]
  401764:	00000000 	nop
  401768:	afc20020 	sw	v0,32(s8) # node = res[i]
  40176c:	8fc2001c 	lw	v0,28(s8) # 末尾循环体起始,取得i
  401770:	00000000 	nop
  401774:	24420001 	addiu	v0,v0,1 # i++
  401778:	afc2001c 	sw	v0,28(s8) # 存入内存中
  40177c:	8fc2001c 	lw	v0,28(s8) # 条件判断起始
  401780:	00000000 	nop
  401784:	28420006 	slti	v0,v0,6 # 判断i < 6,是则循环继续
  401788:	1440ffe7 	bnez	v0,401728 <phase_6+0x228>
  40178c:	00000000 	nop
  401790:	8fc20020 	lw	v0,32(s8)
  401794:	00000000 	nop
  401798:	ac400008 	sw	zero,8(v0) # node->next = null
  40179c:	8fc2003c 	lw	v0,60(s8)
  4017a0:	00000000 	nop
  4017a4:	afc20020 	sw	v0,32(s8) # node = firstnode
  4017a8:	afc0001c 	sw	zero,28(s8) # i = 0
  4017ac:	10000032 	b	401878 <phase_6+0x378>
  4017b0:	00000000 	nop
  4017b4:	8f82806c 	lw	v0,-32660(gp)
  4017b8:	00000000 	nop
  4017bc:	8c42002c 	lw	v0,44(v0)
  4017c0:	00000000 	nop
  4017c4:	30420001 	andi	v0,v0,0x1
  4017c8:	304200ff 	andi	v0,v0,0xff
  4017cc:	10400012 	beqz	v0,401818 <phase_6+0x318> # if...else语句,判断奇偶
  4017d0:	00000000 	nop
  4017d4:	8fc20020 	lw	v0,32(s8)
  4017d8:	00000000 	nop
  4017dc:	8c430000 	lw	v1,0(v0)
  4017e0:	8fc20020 	lw	v0,32(s8)
  4017e4:	00000000 	nop
  4017e8:	8c420008 	lw	v0,8(v0)
  4017ec:	00000000 	nop
  4017f0:	8c420000 	lw	v0,0(v0)
  4017f4:	00000000 	nop
  4017f8:	0062102a 	slt	v0,v1,v0 # 比较重排后链表前后两个数的大小,升序则爆炸
  4017fc:	10400015 	beqz	v0,401854 <phase_6+0x354>
  401800:	00000000 	nop
  401804:	0c10087c 	jal	4021f0 <explode_bomb>
  401808:	00000000 	nop
  40180c:	8fdc0010 	lw	gp,16(s8)
  401810:	10000010 	b	401854 <phase_6+0x354>
  401814:	00000000 	nop
  401818:	8fc20020 	lw	v0,32(s8)
  40181c:	00000000 	nop
  401820:	8c430000 	lw	v1,0(v0)
  401824:	8fc20020 	lw	v0,32(s8)
  401828:	00000000 	nop
  40182c:	8c420008 	lw	v0,8(v0)
  401830:	00000000 	nop
  401834:	8c420000 	lw	v0,0(v0)
  401838:	00000000 	nop
  40183c:	0043102a 	slt	v0,v0,v1 # 比较重排后链表前后两个数的大小,降序则爆炸
  401840:	10400004 	beqz	v0,401854 <phase_6+0x354>
  401844:	00000000 	nop
  401848:	0c10087c 	jal	4021f0 <explode_bomb>
  40184c:	00000000 	nop
  401850:	8fdc0010 	lw	gp,16(s8)
  401854:	8fc20020 	lw	v0,32(s8)
  401858:	00000000 	nop
  40185c:	8c420008 	lw	v0,8(v0)
  401860:	00000000 	nop
  401864:	afc20020 	sw	v0,32(s8)
  401868:	8fc2001c 	lw	v0,28(s8)
  40186c:	00000000 	nop
  401870:	24420001 	addiu	v0,v0,1 # i++
  401874:	afc2001c 	sw	v0,28(s8)
  401878:	8fc2001c 	lw	v0,28(s8)
  40187c:	00000000 	nop
  401880:	28420005 	slti	v0,v0,5 # i < 5
  401884:	1440ffcb 	bnez	v0,4017b4 <phase_6+0x2b4>
  401888:	00000000 	nop
  40188c:	03c0e821 	move	sp,s8
  401890:	8fbf005c 	lw	ra,92(sp)
  401894:	8fbe0058 	lw	s8,88(sp)
  401898:	27bd0060 	addiu	sp,sp,96
  40189c:	03e00008 	jr	ra
  4018a0:	00000000 	nop

phase_secret

在炸弹四输入5 austinpowers即可进入隐藏炸弹。这个炸弹就是一个普通的二叉搜索树,输入数值x,执行find(x),返回得到根节点到值为x的节点的路径。炸弹要求返回值为7=111B,即根节点的右儿子节点的右儿子节点的右儿子节点,该节点值为1001。因此输入1001即可。

00402264 <phase_defused>:
  402264:	27bdff88 	addiu	sp,sp,-120
  402268:	afbf0074 	sw	ra,116(sp)
  40226c:	afbe0070 	sw	s8,112(sp)
  402270:	03a0f021 	move	s8,sp
  402274:	3c1c0042 	lui	gp,0x42
  402278:	279cb190 	addiu	gp,gp,-20080
  40227c:	afbc0010 	sw	gp,16(sp)
  402280:	3c020041 	lui	v0,0x41
  402284:	8c433240 	lw	v1,12864(v0)
  402288:	24020006 	li	v0,6
  40228c:	14620039 	bne	v1,v0,402374 <phase_defused+0x110>
  402290:	00000000 	nop
  402294:	8f828058 	lw	v0,-32680(gp)
  402298:	00000000 	nop
  40229c:	244400f0 	addiu	a0,v0,240
  4022a0:	3c020040 	lui	v0,0x40
  4022a4:	244328a8 	addiu	v1,v0,10408 # "%d %s" !!!
  4022a8:	27c20068 	addiu	v0,s8,104
  4022ac:	00602821 	move	a1,v1
  4022b0:	00403021 	move	a2,v0
  4022b4:	27c20018 	addiu	v0,s8,24
  4022b8:	00403821 	move	a3,v0
  4022bc:	8f828084 	lw	v0,-32636(gp)
  4022c0:	00000000 	nop
  4022c4:	0040c821 	move	t9,v0
  4022c8:	0320f809 	jalr	t9 # 调用库中函数sscanf !!!
  4022cc:	00000000 	nop
  4022d0:	8fdc0010 	lw	gp,16(s8)
  4022d4:	00401821 	move	v1,v0
  4022d8:	24020002 	li	v0,2 # 判断sscanf读得的有效数据个数是否为2
  4022dc:	1462001d 	bne	v1,v0,402354 <phase_defused+0xf0>
  4022e0:	00000000 	nop
  4022e4:	27c20018 	addiu	v0,s8,24
  4022e8:	00402021 	move	a0,v0 # $a0中存储着输入的字符
  4022ec:	3c020040 	lui	v0,0x40
  4022f0:	244528b0 	addiu	a1,v0,10416 # $a1中存储着"austinpowers"
  4022f4:	0c10073e 	jal	401cf8 <strings_not_equal> # 判断是否相等
  4022f8:	00000000 	nop
  4022fc:	8fdc0010 	lw	gp,16(s8)
  402300:	14400014 	bnez	v0,402354 <phase_defused+0xf0>
  402304:	00000000 	nop
  402308:	3c020040 	lui	v0,0x40
  40230c:	244428c0 	addiu	a0,v0,10432
  402310:	8f828038 	lw	v0,-32712(gp)
  402314:	00000000 	nop
  402318:	0040c821 	move	t9,v0
  40231c:	0320f809 	jalr	t9
  402320:	00000000 	nop
  402324:	8fdc0010 	lw	gp,16(s8)
  402328:	3c020040 	lui	v0,0x40
  40232c:	244428e8 	addiu	a0,v0,10472
  402330:	8f828038 	lw	v0,-32712(gp)
  402334:	00000000 	nop
  402338:	0040c821 	move	t9,v0
  40233c:	0320f809 	jalr	t9
  402340:	00000000 	nop
  402344:	8fdc0010 	lw	gp,16(s8)
  402348:	0c100664 	jal	401990 <secret_phase> # 跳转至secret_phase
  40234c:	00000000 	nop
  402350:	8fdc0010 	lw	gp,16(s8)
  402354:	3c020040 	lui	v0,0x40
  402358:	24442920 	addiu	a0,v0,10528
  40235c:	8f828038 	lw	v0,-32712(gp)
  402360:	00000000 	nop
  402364:	0040c821 	move	t9,v0
  402368:	0320f809 	jalr	t9
  40236c:	00000000 	nop
  402370:	8fdc0010 	lw	gp,16(s8)
  402374:	03c0e821 	move	sp,s8
  402378:	8fbf0074 	lw	ra,116(sp)
  40237c:	8fbe0070 	lw	s8,112(sp)
  402380:	27bd0078 	addiu	sp,sp,120
  402384:	03e00008 	jr	ra
  402388:	00000000 	nop
  40238c:	00000000 	nop

004018a4 <fun7>:
  4018a4: 27bdffe0  addiu sp,sp,-32
  4018a8: afbf001c  sw  ra,28(sp)
  4018ac: afbe0018  sw  s8,24(sp)
  4018b0: 03a0f021  move  s8,sp
  4018b4: afc40020  sw  a0,32(s8)
  4018b8: afc50024  sw  a1,36(s8)
  4018bc: 8fc20020  lw  v0,32(s8)
  4018c0: 00000000  nop
  4018c4: 14400004  bnez  v0,4018d8 <fun7+0x34> # $v0($a0)不为0则继续,为0则函数结束
  4018c8: 00000000  nop
  4018cc: 2402ffff  li  v0,-1 # 设返回值为-1,即没有找到该值
  4018d0: 10000029  b 401978 <fun7+0xd4>
  4018d4: 00000000  nop
  4018d8: 8fc20020  lw  v0,32(s8) # 取出$a0中的值
  4018dc: 00000000  nop
  4018e0: 8c430000  lw  v1,0(v0) # $v1 = m[$a0]
  4018e4: 8fc20024  lw  v0,36(s8) # $v0 = $a1
  4018e8: 00000000  nop
  4018ec: 0043102a  slt v0,v0,v1 # $v0 >= $v1时函数跳转
  4018f0: 1040000c  beqz  v0,401924 <fun7+0x80>
  4018f4: 00000000  nop
  4018f8: 8fc20020  lw  v0,32(s8)
  4018fc: 00000000  nop
  401900: 8c420004  lw  v0,4(v0) # 令fun7第一个参数为节点的左儿子的地址
  401904: 00000000  nop
  401908: 00402021  move  a0,v0
  40190c: 8fc50024  lw  a1,36(s8) #第二个参数不变
  401910: 0c100629  jal 4018a4 <fun7>
  401914: 00000000  nop
  401918: 00021040  sll v0,v0,0x1 # $v0左移一位
  40191c: 10000016  b 401978 <fun7+0xd4>
  401920: 00000000  nop
  401924: 8fc20020  lw  v0,32(s8)
  401928: 00000000  nop
  40192c: 8c430000  lw  v1,0(v0)
  401930: 8fc20024  lw  v0,36(s8)
  401934: 00000000  nop
  401938: 0062102a  slt v0,v1,v0 # $v1 >= $v0时函数跳转,即$v0 == $v1时找到节点,函数返回0
  40193c: 1040000d  beqz  v0,401974 <fun7+0xd0>
  401940: 00000000  nop
  401944: 8fc20020  lw  v0,32(s8)
  401948: 00000000  nop
  40194c: 8c420008  lw  v0,8(v0) # 令fun7第一个参数为节点的右儿子的地址
  401950: 00000000  nop
  401954: 00402021  move  a0,v0
  401958: 8fc50024  lw  a1,36(s8) # 第二个参数不变
  40195c: 0c100629  jal 4018a4 <fun7>
  401960: 00000000  nop
  401964: 00021040  sll v0,v0,0x1 # $v0左移一位
  401968: 24420001  addiu v0,v0,1 # $v0末位补1
  40196c: 10000002  b 401978 <fun7+0xd4>
  401970: 00000000  nop
  401974: 00001021  move  v0,zero
  401978: 03c0e821  move  sp,s8
  40197c: 8fbf001c  lw  ra,28(sp)
  401980: 8fbe0018  lw  s8,24(sp)
  401984: 27bd0020  addiu sp,sp,32
  401988: 03e00008  jr  ra
  40198c: 00000000  nop

00401990 <secret_phase>:
  401990:	27bdffd8 	addiu	sp,sp,-40
  401994:	afbf0024 	sw	ra,36(sp)
  401998:	afbe0020 	sw	s8,32(sp)
  40199c:	03a0f021 	move	s8,sp
  4019a0:	3c1c0042 	lui	gp,0x42
  4019a4:	279cb190 	addiu	gp,gp,-20080
  4019a8:	afbc0010 	sw	gp,16(sp)
  4019ac:	0c1007fb 	jal	401fec <read_line> # 输入
  4019b0:	00000000 	nop
  4019b4:	8fdc0010 	lw	gp,16(s8)
  4019b8:	afc2001c 	sw	v0,28(s8)
  4019bc:	8fc2001c 	lw	v0,28(s8)
  4019c0:	00000000 	nop
  4019c4:	00402021 	move	a0,v0
  4019c8:	00002821 	move	a1,zero
  4019cc:	2406000a 	li	a2,10
  4019d0:	8f828070 	lw	v0,-32656(gp)
  4019d4:	00000000 	nop
  4019d8:	0040c821 	move	t9,v0
  4019dc:	0320f809 	jalr	t9
  4019e0:	00000000 	nop
  4019e4:	8fdc0010 	lw	gp,16(s8)
  4019e8:	afc20018 	sw	v0,24(s8)
  4019ec:	8fc20018 	lw	v0,24(s8)
  4019f0:	00000000 	nop
  4019f4:	2442ffff 	addiu	v0,v0,-1 # $v0--
  4019f8:	2c4203e9 	sltiu	v0,v0,1001 # 判断[输入的值-1]($v0)是否小于1001,是则继续,否则引爆
  4019fc:	14400004 	bnez	v0,401a10 <secret_phase+0x80>
  401a00:	00000000 	nop
  401a04:	0c10087c 	jal	4021f0 <explode_bomb>
  401a08:	00000000 	nop
  401a0c:	8fdc0010 	lw	gp,16(s8)
  401a10:	3c020041 	lui	v0,0x41
  401a14:	24443184 	addiu	a0,v0,12676 # fun7的第一个参数0x413814 m[0x413814] = 0x24 = 36
  401a18:	8fc50018 	lw	a1,24(s8) # fun7的第二个参数,即输入的数
  401a1c:	0c100629 	jal	4018a4 <fun7> # 进入fun7
  401a20:	00000000 	nop
  401a24:	8fdc0010 	lw	gp,16(s8)
  401a28:	00401821 	move	v1,v0
  401a2c:	24020007 	li	v0,7
  401a30:	10620004 	beq	v1,v0,401a44 <secret_phase+0xb4> # fun7返回值为7 = 111B时才不会引爆
  401a34:	00000000 	nop
  401a38:	0c10087c 	jal	4021f0 <explode_bomb>
  401a3c:	00000000 	nop
  401a40:	8fdc0010 	lw	gp,16(s8)
  401a44:	3c020040 	lui	v0,0x40
  401a48:	244427b8 	addiu	a0,v0,10168
  401a4c:	8f828038 	lw	v0,-32712(gp)
  401a50:	00000000 	nop
  401a54:	0040c821 	move	t9,v0
  401a58:	0320f809 	jalr	t9
  401a5c:	00000000 	nop
  401a60:	8fdc0010 	lw	gp,16(s8)
  401a64:	0c100899 	jal	402264 <phase_defused>
  401a68:	00000000 	nop
  401a6c:	8fdc0010 	lw	gp,16(s8)
  401a70:	03c0e821 	move	sp,s8
  401a74:	8fbf0024 	lw	ra,36(sp)
  401a78:	8fbe0020 	lw	s8,32(sp)
  401a7c:	27bd0028 	addiu	sp,sp,40
  401a80:	03e00008 	jr	ra
  401a84:	00000000 	nop


总结

每个阶段对应的C++代码

只给出关键部分。简洁明了,一看就懂,理解炸弹大概流程用。

//输入ID
int ID;
cin>>ID;

phase_1

//input
string str;
cin>>str;

//phase_1
string ans = "Let's begin now!";
if (str == ans) return ;
else explode_bomb();

phase_2

//input
int a[6];
for (int i = 0;i < 6;i++)
	cin>>a[i];
	
//phase_2
if (a[0] != 1) explode_bomb();
for (int i = 0;i < 6;i++)
	if (a[i] * ((ID >> i) & 1) != a[i + 1])
		explode_bomb();

phase_3

//input
int a[2];
char c
cin>>a[0]>>c>>a[1];
//phase_3
char c0;
int b;
switch(a[0]) {
	case 0:c0 = 'q';b = 777;if ((ID & 1) * a[1] != b) explode_bomb();break;
	case 1:c0 = 'b';b = 214;if ((ID & 1) * a[1] != b) explode_bomb();break;
	case 2:c0 = 'b';b = 755;if ((ID & 1) * a[1] != b) explode_bomb();break;
	case 3:c0 = 'k';if ((ID & 1) * a[1] != 0) explode_bomb();break;
	case 4:c0 = 'o';b = 228;if ((ID & 1) * a[1] != b) explode_bomb();break;
	case 5:c0 = 't';b = 513;if ((ID & 1) * a[1] != b) explode_bomb();break;
	case 6:c0 = 'v';b = 780;if ((ID & 1) * a[1] != b) explode_bomb();break;
	case 7:c0 = 'b';b = 824;if ((ID & 1) * a[1] != b) explode_bomb();break;
	default: explode_bomb();
}
if (c != c0) explode_bomb();

phase_4

//input
int x;
cin>>x;
//fun4
int fun4(int x) {
	if (x < 2) return 1;
	return f(x - 1) + f(x - 2);
}
//phase_4
if (ID & 1) {
	if (fun4(x) != 8) explode_bomb();
}
else {
	if (fun4(x) != 13) explode_bomb();
}

phase_5

//input
char str[6];
cin>>str;
//phase_5
char res[6];
char S[16] = "isrveawhobpnutfg";
char ans[6] = "giants";
for (int i = 0;i < 6;i++) {
	int pos = str[i] & 15;//15D = FH = 1111B
	res[i] = S[pos];
}
for (int i = 0;i < 6;i++)
	if (res[i] != ans[i])
		explode_bomb();

phase_6

//input
int a[6];
for (int i = 0;i < 6;i++)
	cin>>a[i];
//phase_6
for (int i = 0;i < 6;i++) {
	if (!(i > 0 && i < 7) explode_bomb();
	for (int j = i + 1;j < 6;j++)
		if (a[i] == a[j]) explode_bomb();
}
chain c = {0x0fd, 0x2d5, 0x12d, 0x3e5, 0x0d4, 0x1b0};
chainNode res[6];
for (int i = 0;i < 6;i++) {
	chainNode *node = c.firstNode;
	for (int j = 1;j < a[i];j++)
		node = node->next;
	res[i] = node;
}
chainNode *node = c.firstNode;
for (int i = 1;i < 6;i++) {
	node->next = res[i];
	node = res[i];
}
node->next = null;
if (ID & 1) {
	node = c.firstNode;
	for (int i = 1;i < 6;i++)
		if (node->element < node->next->element)
			explode_bomb();
}
else {
	node = c.firstNode;
	for (int i = 1;i < 6;i++)
		if (node->element > node->next->element)
			explode_bomb();
}
  • 26
    点赞
  • 114
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
反汇编带符号表的32位/64位ELF目标文件,CPU类型:ARM PowerPC MIPS X86 操作菜单选择:文件解析 Alx+P ELF文件解析 Alt+E 另有文本比较等杂项功能。V1.26.00相对上一版本,增强EXE反汇编,增加dbx老邮件解析、二维码功能,;V1.25.07相对上一版本,增加二进制反汇编、IQ数据解析功能,完善MIPS反汇编,修复小BUG;V1.25.05相对上一版本,增加内存数据按数据类型解析功能;V1.25.04相对上一版本,完善X86反汇编,修复小BUG;V1.25.02相对上一版本,COREDUMP统计、匹配目标文件等相关功能优化,修复小BUG;V1.25.00相对上一版本,相关功能支持动态库文件,查询代码支持无符号目标文件+有符号目标文件,COREDUMP统计、与问题单关联、目标文件/CORE文件/问题单同步;V1.24.02相对上一版本,针对进程主动捕捉异常的信息定制处理进一步完善COREDUMP文件解析与应用,增强软件管理;V1.24.01相对上一版本,进一步完善COREDUMP文件解析与应用,提供部分ARM Thumb指令反汇编;V1.24.00相对上一版本,进一步完善COREDUMP文件解析与应用,提供堆栈调用关系分析;V1.23.03相对上一版本,提供32位X86反汇编;V1.23.02相对上一版本,提供源代码行查询指令地址,OBJ/COREDUMP文件解析,sprintf函数参数特定检查,完善文件拖放操作,修复小BUG;V1.23.01相对上一版本,提供ELF文件指令修改,修复ARM MLS指令反汇编错误等BUG;V1.23.00相对上一版本,提供程序地址对应源代码行查询,修复MIPS调试信息错误;V1.22相对上一版本,修复MIPS小端字节序反汇编错误,网上最新版本提示;V1.21相对上一版本,菜单调整,完善64位ELF文件解析,解析调试信息;另部分增强功能的菜单操作设有密码,如有兴趣欢迎咨询。欢迎大家反馈相关软件使用过程中的问题!
反汇编Linux/Windows OS运行的32位/64位程序/动态库文件,CPU类型:ARM PowerPC MIPS X86 操作菜单选择:文件解析 Alx+P ELF文件解析 Alt+E 另有CORE文件解调用栈、文本比较等功能。V2.0.3相对上一版本,完善ARM64、X8664、PPC64反汇编、ko反汇编,完善反汇编文本文件比较、IQ数据解析,修复小BUG;V2.0.2相对上一版本,完善ARM64、X8664反汇编、ARM64位core文件调用栈,完善文本文件比较、增加高亮、查找功能,修复小BUG;V2.0.0相对上一版本,完善ARM64反汇编、ARM64位core文件调用栈,完善C++符号名字解析,支持工具运行在英文版OS;V1.26.01相对上一版本,增加ARM64反汇编、64位core文件解析;V1.26.00相对上一版本,增强EXE反汇编,增加dbx老邮件解析、二维码功能;V1.25.07相对上一版本,增加二进制反汇编、IQ数据解析功能,完善MIPS反汇编,修复小BUG;V1.25.05相对上一版本,增加内存数据按数据类型解析功能;V1.25.04相对上一版本,完善X86反汇编,修复小BUG;V1.25.02相对上一版本,COREDUMP统计、匹配目标文件等相关功能优化,修复小BUG;V1.25.00相对上一版本,相关功能支持动态库文件,查询代码支持无符号目标文件+有符号目标文件,COREDUMP统计、与问题单关联、目标文件/CORE文件/问题单同步;V1.24.02相对上一版本,针对进程主动捕捉异常的信息定制处理进一步完善COREDUMP文件解析与应用,增强软件管理;V1.24.01相对上一版本,进一步完善COREDUMP文件解析与应用,提供部分ARM Thumb指令反汇编;V1.24.00相对上一版本,进一步完善COREDUMP文件解析与应用,提供堆栈调用关系分析;V1.23.03相对上一版本,提供32位X86反汇编;V1.23.02相对上一版本,提供源代码行查询指令地址,OBJ/COREDUMP文件解析,sprintf函数参数特定检查,完善文件拖放操作,修复小BUG;V1.23.01相对上一版本,提供ELF文件指令修改,修复ARM MLS指令反汇编错误等BUG;V1.23.00相对上一版本,提供程序地址对应源代码行查询,修复MIPS调试信息错误;V1.22相对上一版本,修复MIPS小端字节序反汇编错误,网上最新版本提示;V1.21相对上一版本,菜单调整,完善64位ELF文件解析,解析调试信息;另部分增强功能的菜单操作设有密码,如有兴趣欢迎咨询。欢迎大家反馈相关软件使用过程中的问题!

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值