《深入理解计算机系统》Lab2-Bomblab

前言

这篇文章主要记录了我做bomblab的过程,希望能给你一些灵感


一.实验基本内容与要求

本次实验为熟悉汇编程序及其调试方法的实验。
实验内容包含2个文件:bomb(可执行文件)和bomb.c(c源文件)。
实验主题内容为:
程序运行在linux环境中。程序运行中有6个关卡(6个phase),每个phase需要用户在终端上输入特定的字符或者数字才能通关,否则会引爆炸弹!那么如何才能知道输入什么内容呢?这需要你使用gdb工具反汇编出汇编代码,结合c语言文件找到每个关卡的入口函数。然后分析汇编代码,找到在每个phase程序段中,引导程序跳转到“explode_bomb”程序段的地方,并分析其成功跳转的条件,以此为突破口寻找应该在命令行输入何种字符通关。

实验需要用到gdb工具,可到网上查找gdb使用方法和参数。

二.准备工作

1.打开bomb.c文件

发现main函数依次调用了phase_1~phase_6六个函数,但函数的具体代码被隐藏。可以知道从命令行输入的内容必须和phase函数里面的一样,否则炸弹爆炸。

2.反汇编可执行文件bomb

objdump -d bomb > bomb.asm

这样就可以再bomb.asm文件里面看到整个文件(主要是phase函数)的汇编代码啦

3.执行bomb文件

随意输入123,提示爆炸,表示输入错误。接下来就深入各个phase函数去看看怎么拆炸弹吧
在这里插入图片描述

三.拆解炸弹

(1)phase_1

1.汇编代码

在这里插入图片描述

2.汇编分析
   0x08048b93 <+3>:		movl   $0x804a204,0x4(%esp)  //将地址$0x804a204里面的值传到了esp+4处,疑似参数准备
   0x08048b9b <+11>:	mov    0x20(%esp),%eax
   0x08048b9f <+15>:	mov    %eax,(%esp)  //参数准备:将esp+20里面的值放到栈顶
   0x08048ba2 <+18>:	call   0x80490ca <strings_not_equal> //调用函数,大概可以推测功能是判断字符串是否相等
   0x08048ba7 <+23>:	test   %eax,%eax //判断函数返回值是否为0,并设置标志位zf
   0x08048ba9 <+25>:	je     0x8048bb0 <phase_1+32> //zf=0则跳转,越过调用爆炸函数
   0x08048bab <+27>:	call   0x80491d5 <explode_bomb>
   0x08048bb0 <+32>:	add    $0x1c,%esp

补充:
在这里插入图片描述

3.调试

进入函数strings_not_equal看看情况
在这里插入图片描述

可以看到phase_1函数给strings_not_equal函数传了两个参数。
在这里插入图片描述

故可以确定0x804a204里面的值就是参数
在这里插入图片描述

查看,疑似发现第一关密码:And they have no disregard for human life.
在这里插入图片描述

4.运行测试

在这里插入图片描述
通过第一关啦!

(2)phase_2

1.汇编代码

在这里插入图片描述

2.汇编分析
 8048bb9:	8d 44 24 18          	lea    0x18(%esp),%eax
 8048bbd:	89 44 24 04          	mov    %eax,0x4(%esp)
 8048bc1:	8b 44 24 40          	mov    0x40(%esp),%eax //参数准备
 8048bc5:	89 04 24             	mov    %eax,(%esp)  //参数准备
 8048bc8:	e8 2f 06 00 00       	call   80491fc <read_six_numbers> //调用函数,猜测这关要求输入6个数
3.调试

进入read_six_numbers看看
在这里插入图片描述

结合函数名以及与5相比较,可以推测这个函数的作用是判断输入数字个数是否为6,即输入应该是6个数字
在这里插入图片描述

再继续分析调用完read_six_numbers后的汇编代码

4.继续phase_2汇编分析
 8048bcd:	83 7c 24 18 01       	cmpl   $0x1,0x18(%esp) //比较1和esp+24(第一个数)
 8048bd2:	74 1e                	je     8048bf2 <phase_2+0x3e> //相等则跳转到1
 8048bd4:	e8 fc 05 00 00       	call   80491d5 <explode_bomb> //不相等则爆炸
 8048bd9:	eb 17                	jmp    8048bf2 <phase_2+0x3e>
 //跳转2:8048bdb:	8b 43 fc          mov    -0x4(%ebx),%eax //eax=ebx-4
 8048bde:	01 c0                	add    %eax,%eax  //eax=eax+eax 翻倍
 8048be0:	39 03                	cmp    %eax,(%ebx) //比较
 8048be2:	74 05                	je     8048be9 <phase_2+0x35>//相等则跳转到3
 8048be4:	e8 ec 05 00 00       	call   80491d5 <explode_bomb>//否则爆炸
 //跳转3:8048be9:	83 c3 04          add    $0x4,%ebx //ebx=ebx+4
 8048bec:	39 f3                	cmp    %esi,%ebx  //比较esi和ebx
 8048bee:	75 eb                	jne    8048bdb <phase_2+0x27> //不相等则跳转到2
 8048bf0:	eb 0a                	jmp    8048bfc <phase_2+0x48> //无条件结束
 //跳转1::8048bf2:	8d 5c 24 1c   lea    0x1c(%esp),%ebx //ebx=esp+28
 8048bf6:	8d 74 24 30          	lea    0x30(%esp),%esi //esi=esp+48
 8048bfa:	eb df                	jmp    8048bdb <phase_2+0x27> //跳转到2,执行循环
 8048bfc:	83 c4 34             	add    $0x34,%esp

转换为伪代码

if(esp+24==1) 
{
 ebx=esp+28;
 esi=esp+48;
}

 8048bcd
eax=ebx-4=esp+24;
eax=2*eax //翻倍
if(eax==ebx)
{
ebx=ebx+4=esp+28+4; //下一位
if(esi!=ebx) goto  8048bcd; //(48-28)/4=5 循环5次
else 结束
}
else 爆炸

一开始就和1想比较,相等才继续执行,说明输入的第一个数字是1

分析后面的过程可以知道,这个循环执行了五次,每次把前面的数翻了一倍,如果后一个数不等于前一个数的两倍则爆炸

故第二关的密码是:1 2 4 8 16 32

5.测试运行

在这里插入图片描述

顺利通过!

(3)phase_3

1.汇编代码

在这里插入图片描述

在这里插入图片描述

2.汇编分析
 08048c02 <phase_3>:
 8048c02:	83 ec 3c             	sub    $0x3c,%esp
 8048c05:	8d 44 24 2c          	lea    0x2c(%esp),%eax
 8048c09:	89 44 24 10          	mov    %eax,0x10(%esp) //esp+10=esp+2c
 8048c0d:	8d 44 24 27          	lea    0x27(%esp),%eax
 8048c11:	89 44 24 0c          	mov    %eax,0xc(%esp) //esp+c=esp+27
 8048c15:	8d 44 24 28          	lea    0x28(%esp),%eax
 8048c19:	89 44 24 08          	mov    %eax,0x8(%esp)  //esp+8=esp+28
 8048c1d:	c7 44 24 04 56 a2 04 	movl   $0x804a256,0x4(%esp) //esp+4=0x804a256里存的值
 8048c24:	08 
 8048c25:	8b 44 24 40          	mov    0x40(%esp),%eax 
 8048c29:	89 04 24             	mov    %eax,(%esp)  //esp=esp+40
 8048c2c:	e8 2f fc ff ff       	call   8048860 <__isoc99_sscanf@plt>
 8048c31:	83 f8 02             	cmp    $0x2,%eax
 8048c34:	7f 05                	jg     8048c3b <phase_3+0x39> //函数返回值>2则跳转到1
 8048c36:	e8 9a 05 00 00       	call   80491d5 <explode_bomb>//否则爆炸
 
 

在这里插入图片描述

可以确定输入为:整数+字符+整数

再看isoc99_sscanf@plt函数返回值需要大于2才不会引发爆炸,故推测isoc99_sscanf@plt函数的功能就是判断输入字符/数字个数是否符合要求

 跳转1:8048c3b:	83 7c 24 28 07       	cmpl   $0x7,0x28(%esp)
 8048c40:	0f 87 fc 00 00 00    	ja     8048d42 <phase_3+0x140> //esp+28>7,则跳转到2爆炸
 8048c46:	8b 44 24 28          	mov    0x28(%esp),%eax
 8048c4a:	ff 24 85 60 a2 04 08 	jmp    *0x804a260(,%eax,4)//switch语句 
 跳转表 *0x804a260 + 4 * %eax   *0x804a260 = 0x0804c51 
   

由cmpl $0x7,0x28(%esp) 可知输入的i的一个数要小于7,由ja可知这是一个无符号数,故第一个数的范围是[0,7].

在这里插入图片描述

读取0x804a260里面的内容,可知当eax=0时就是跳转到了下一行继续执行。 对应汇编指令为mov $0x69,所以第二个ascll码为0x69,即字符’i’ . 下一条汇编语句为cmpl $0x358,0x2c(%esp),所以第三个数为0x358,即856

故答案应该为:0 i 856

 8048c51:	b8 69 00 00 00       	mov    $0x69,%eax
 8048c56:	81 7c 24 2c 58 03 00 	cmpl   $0x358,0x2c(%esp) 
 8048c5d:	00 
 8048c5e:	0f 84 e8 00 00 00    	je     8048d4c <phase_3+0x14a> //esp+2c=0x358,则跳转到3
 8048c64:	e8 6c 05 00 00       	call   80491d5 <explode_bomb>
...
 跳转3:8048d4c:	3a 44 24 27          	cmp    0x27(%esp),%al 
 8048d50:	74 05                	je     8048d57 <phase_3+0x155> //al=esp+27 则结束
 8048d52:	e8 7e 04 00 00       	call   80491d5 <explode_bomb>
 8048d57:	83 c4 3c             	add    $0x3c,%esp
 8048d5a:	c3                   	ret  
5.测试运行

在这里插入图片描述

(4)phase_4

1.汇编代码

在这里插入图片描述

2.汇编分析
08048da5 <phase_4>:
 8048da5:	83 ec 2c             	sub    $0x2c,%esp
 8048da8:	8d 44 24 18          	lea    0x18(%esp),%eax
 8048dac:	89 44 24 0c          	mov    %eax,0xc(%esp) //esp+c=esp+18(输入2)
 8048db0:	8d 44 24 1c          	lea    0x1c(%esp),%eax
 8048db4:	89 44 24 08          	mov    %eax,0x8(%esp) //esp+8=esp+1c(输入1)
 8048db8:	c7 44 24 04 cf a3 04 	movl   $0x804a3cf,0x4(%esp) //esp+4=0x804a3cf的值
 8048dbf:	08 
 8048dc0:	8b 44 24 30          	mov    0x30(%esp),%eax
 8048dc4:	89 04 24             	mov    %eax,(%esp) //esp=esp+30
 8048dc7:	e8 94 fa ff ff       	call   8048860 <__isoc99_sscanf@plt> //和上一题相同 函数作用是判断输入个数
 8048dcc:	83 f8 02             	cmp    $0x2,%eax 
 8048dcf:	75 0c                	jne    8048ddd <phase_4+0x38>//返回值!=2则跳转到1 爆炸
 8048dd1:	8b 44 24 18          	mov    0x18(%esp),%eax //eax=esp+18(输入2)
 8048dd5:	83 e8 02             	sub    $0x2,%eax  //eax=eax-2
 8048dd8:	83 f8 02             	cmp    $0x2,%eax
 8048ddb:	76 05                	jbe    8048de2 <phase_4+0x3d>//eax<=2则跳转到2,否则爆炸
 //跳转1:8048ddd:	e8 f3 03 00 00    call   80491d5 <explode_bomb>
 //跳转2:8048de2:	8b 44 24 18       mov    0x18(%esp),%eax //eax=esp+18
 8048de6:	89 44 24 04          	mov    %eax,0x4(%esp) //esp+4=esp+18(输入2)
 8048dea:	c7 04 24 07 00 00 00 	movl   $0x7,(%esp) //esp=7
 8048df1:	e8 65 ff ff ff       	call   8048d5b <func4> //func4(7,输入2)
 8048df6:	3b 44 24 1c          	cmp    0x1c(%esp),%eax /比较返回值和esp+1c(输入1)
 8048dfa:	74 05                	je     8048e01 <phase_4+0x5c> //相等则结束
 8048dfc:	e8 d4 03 00 00       	call   80491d5 <explode_bomb>
 8048e01:	83 c4 2c             	add    $0x2c,%esp
 8048e04:	c3                   	ret    


3.调试

在这里插入图片描述
在这里插入图片描述

可知,输入为两个整数

在这里插入图片描述

输入2-2<=2,故输入2<=4,又因为使用jbe,说明是无符号数,故输入2>=2.故输入2的范围是[2,3,4]

在这里插入图片描述

深入func4看看情况
在这里插入图片描述

在这里插入图片描述

在这里插入图片描述
可以知道 edi=0,esi=0

(gdb) disas func4
Dump of assembler code for function func4:
   0x08048d5b <+0>:	push   %edi
   0x08048d5c <+1>:	push   %esi
   0x08048d5d <+2>:	push   %ebx
   0x08048d5e <+3>:	sub    $0x10,%esp
   0x08048d61 <+6>:	mov    0x20(%esp),%ebx //ebx=7
   0x08048d65 <+10>:	mov    0x24(%esp),%esi //esi=输入2=3
   0x08048d69 <+14>:	test   %ebx,%ebx  //判断ebx是否为0,并设置标志位zf,返回0
   0x08048d6b <+16>:	jle    0x8048d99 <func4+62> //ebx为0 则跳转到1
   0x08048d6d <+18>:	mov    %esi,%eax //eax=esi=3
   0x08048d6f <+20>:	cmp    $0x1,%ebx 
   0x08048d72 <+23>:	je     0x8048d9e <func4+67>//ebx=1则跳转到2 函数返回esi(第二个输入)
   0x08048d74 <+25>:	mov    %esi,0x4(%esp) esp+4=esi=输入2=3
   0x08048d78 <+29>:	lea    -0x1(%ebx),%eax eax=6
   0x08048d7b <+32>:	mov    %eax,(%esp) esp=6
   0x08048d7e <+35>:	call   0x8048d5b <func4> //递归调用func(6,3)=60
   0x08048d83 <+40>:	lea    (%eax,%esi,1),%edi //edi=eax+esi=63
   0x08048d86 <+43>:	mov    %esi,0x4(%esp) //esp+4=esi
   0x08048d8a <+47>:	sub    $0x2,%ebx //ebx=ebx-2=5
   0x08048d8d <+50>:	mov    %ebx,(%esp) esp=5
   0x08048d90 <+53>:	call   0x8048d5b <func4>  //func4(5,3)=36
   0x08048d95 <+58>:	add    %edi,%eax //eax=eax+edi=99
   0x08048d97 <+60>:	jmp    0x8048d9e <func4+67>
   跳转1:0x08048d99 <+62>:	mov    $0x0,%eax //设置返回值为0
   跳转2:0x08048d9e <+67>:	add    $0x10,%esp //结束
   0x08048da1 <+70>:	pop    %ebx
   0x08048da2 <+71>:	pop    %esi
   0x08048da3 <+72>:	pop    %edi
   0x08048da4 <+73>:	ret    

ps:上面//后的具体数值都是单步调试查看寄存器和内存地址所得

转换位伪代码

func4(int a,int b)
{
	if(a==0) return 0;
	if(a==1) return b;
	a=a-2;
	return func4(a-1,7)+func(a-2,esi);
}

phase_4中调用:func4(7,第二个输入)
在这里插入图片描述

在这里插入图片描述

当第二个输入为3时,返回值为99,故其中一个答案为:99 3(还有另外两个答案 x 2,x 4)

5.测试运行

在这里插入图片描述

(5)phase_5

1.汇编代码

在这里插入图片描述

2.汇编分析
   Dump of assembler code for function phase_5:
   0x08048e05 <+0>:	    sub    $0x2c,%esp
   0x08048e08 <+3>:	    lea    0x1c(%esp),%eax
   0x08048e0c <+7>:	    mov    %eax,0xc(%esp) //esp+c=esp+1c
   0x08048e10 <+11>:	lea    0x18(%esp),%eax
   0x08048e14 <+15>:	mov    %eax,0x8(%esp)  //esp+8=esp+18
   0x08048e18 <+19>:	movl   $0x804a3cf,0x4(%esp)  //esp+4=0x804a3cf的值
   0x08048e20 <+27>:	mov    0x30(%esp),%eax  
   0x08048e24 <+31>:	mov    %eax,(%esp)  //esp=esp+30(输入)
   0x08048e27 <+34>:	call   0x8048860 <__isoc99_sscanf@plt> //判断输入数字个数
   0x08048e2c <+39>:	cmp    $0x1,%eax
   0x08048e2f <+42>:	jg     0x8048e36 <phase_5+49>
   0x08048e31 <+44>:	call   0x80491d5 <explode_bomb>
   0x08048e36 <+49>:	mov    0x18(%esp),%eax //eax=esp+18(输入1)
   0x08048e3a <+53>:	and    $0xf,%eax  //eax&11111111 只保留后4位二进制数值
   0x08048e3d <+56>:	mov    %eax,0x18(%esp) //esp+18=eax=清除后的结果
   0x08048e41 <+60>:	cmp    $0xf,%eax
   0x08048e44 <+63>:	je     0x8048e70 <phase_5+107> //eax=f(全1)则跳转到1爆炸
   0x08048e46 <+65>:	mov    $0x0,%ecx //ecx=0
   0x08048e4b <+70>:	mov    $0x0,%edx //edx=0
   //跳转2:0x08048e50 <+75>:	add    $0x1,%edx  //edx=edx+1;
   0x08048e53 <+78>:	mov    0x804a280(,%eax,4),%eax //eax=804a280+4*eax里的值
   0x08048e5a <+85>:	add    %eax,%ecx //ecx=ecx+eax;
   0x08048e5c <+87>:	cmp    $0xf,%eax 
   0x08048e5f <+90>:	jne    0x8048e50 <phase_5+75> //eax!=f则跳转到2 while循环
   0x08048e61 <+92>:	mov    %eax,0x18(%esp) //esp+18=f
   0x08048e65 <+96>:	cmp    $0xf,%edx
   0x08048e68 <+99>:	jne    0x8048e70 <phase_5+107> //edx!=f则跳转到1爆炸
   0x08048e6a <+101>:	cmp    0x1c(%esp),%ecx
   0x08048e6e <+105>:	je     0x8048e75 <phase_5+112> //ecx=esp+1c=输入2则拆弹成功
   //跳转1:0x08048e70 <+107>:	call   0x80491d5 <explode_bomb>
   0x08048e75 <+112>:	add    $0x2c,%esp
   0x08048e78 <+115>:	ret 


3.调试

在这里插入图片描述在这里插入图片描述
可知:输入为两个整数

在这里插入图片描述

输入1不能为15也不能为0xnnnnnnnf

这一段的伪代码为

ecx=0;
edx=0;
while(eax!=f)
{
edx++;
eax=0x804a280+4*eax //eax=a[eax]
ecx=ecx+eax
}
esp+18=f;
if(edx!=f) 爆炸

可知,while需要执行15次,才能不引起爆炸

查看0x804a280处的值,可以发现,这是一个数组。a[6]=f
在这里插入图片描述

逆推15次得到第一个输入的值

次数eax
156
1414
132
121
1110
100
98
84
79
613
511
47
33
212
15

故第一个输入可以为5. ecx的值为所有的eax累加

在这里插入图片描述

可以得知,第二个输入的值要等于此时%ecx里面的值,才能成功破解密码

输入:5,3.进行单步调试,看看此时%ecx值值为多少
在这里插入图片描述

故答案应该为:5,115

4测试运行

在这里插入图片描述

成功

(6)phase_6

1.汇编代码
Dump of assembler code for function phase_6:
=> 0x08048e79 <+0>:	push   %esi
   0x08048e7a <+1>:	push   %ebx
   0x08048e7b <+2>:	sub    $0x44,%esp
   0x08048e7e <+5>:	lea    0x10(%esp),%eax
   0x08048e82 <+9>:	mov    %eax,0x4(%esp) //esp+4=esp+10
   0x08048e86 <+13>:	mov    0x50(%esp),%eax
   0x08048e8a <+17>:	mov    %eax,(%esp) //esp=esp+50(输入数组a的首地址)
   0x08048e8d <+20>:	call   0x80491fc <read_six_numbers>
   0x08048e92 <+25>:	mov    $0x0,%esi //esi=0
   //跳转4:0x08048e97 <+30>:	mov    0x10(%esp,%esi,4),%eax //eax=(esp+esi*4)+10(a[esi])
   0x08048e9b <+34>:	sub    $0x1,%eax //eax=eax-1
   0x08048e9e <+37>:	cmp    $0x5,%eax 
   0x08048ea1 <+40>:	jbe    0x8048ea8 <phase_6+47> //0<=eax<=5则跳转到1(无符号数)
   0x08048ea3 <+42>:	call   0x80491d5 <explode_bomb>
   //跳转1:0x08048ea8 <+47>:	add    $0x1,%esi //esi=esi+1=1
   0x08048eab <+50>:	cmp    $0x6,%esi  
   0x08048eae <+53>:	je     0x8048ecb <phase_6+82> //esi=6则跳转到2
   0x08048eb0 <+55>:	mov    %esi,%ebx  //ebx=esi
   //跳转3:0x08048eb2 <+57>:	mov    0x10(%esp,%ebx,4),%eax //eax=a[ebx]
   0x08048eb6 <+61>:	cmp    %eax,0xc(%esp,%esi,4)   
   0x08048eba <+65>:	jne    0x8048ec1 <phase_6+72>  //a[esi+1]!=a[ebx] 则跳转到5,否则爆炸
   0x08048ebc <+67>:	call   0x80491d5 <explode_bomb>
   //跳转5:0x08048ec1 <+72>:	add    $0x1,%ebx //ebx=ebx+1
   0x08048ec4 <+75>:	cmp    $0x5,%ebx
   0x08048ec7 <+78>:	jle    0x8048eb2 <phase_6+57> //0<=ebx<=5 则跳转到3
   0x08048ec9 <+80>:	jmp    0x8048e97 <phase_6+30> //无条件跳转到4
    //阶段1:利用2层for玄幻,保证任意两个相邻数都不相等,且输入的每个元素都属于[1,6] 
    
   //跳转2:0x08048ecb <+82>:	lea    0x10(%esp),%eax //eax=esp+10=a[0]
   0x08048ecf <+86>:	lea    0x28(%esp),%ebx  //ebx=esp+28
   0x08048ed3 <+90>:	mov    $0x7,%ecx       //ecx=7
   //跳转6:0x08048ed8 <+95>:	mov    %ecx,%edx       //edx=ecx=7
   0x08048eda <+97>:	sub    (%eax),%edx     //edx=edx-(eax)=7-(eax)
   0x08048edc <+99>:	mov    %edx,(%eax)		//(eax)=edx=7-(eax)=7-输入1
   0x08048ede <+101>:	add    $0x4,%eax       //eax=eax+4
   0x08048ee1 <+104>:	cmp    %ebx,%eax       
   0x08048ee3 <+106>:	jne    0x8048ed8 <phase_6+95> //eax!=ebx则跳转到6
 //遍历修改输入的每一个数  使得a[i]=7-a[i];
   
   0x08048ee5 <+108>:	mov    $0x0,%ebx   //ebx=0
   0x08048eea <+113>:	jmp    0x8048f09 <phase_6+144> //跳转1
   //跳转3:0x08048eec <+115>:	mov    0x8(%edx),%edx //edx=edx+8
   0x08048eef <+118>:	add    $0x1,%eax //eax++
   0x08048ef2 <+121>:	cmp    %ecx,%eax
   0x08048ef4 <+123>:	jne    0x8048eec <phase_6+115> //eax!=ecx跳转到3
   0x08048ef6 <+125>:	jmp    0x8048efd <phase_6+132> //跳转到4 
   //跳转2:0x08048ef8 <+127>:	mov    $0x804c13c,%edx //edx=链表第一个值
   //跳转4:0x08048efd <+132>:	mov    %edx,0x28(%esp,%esi,4) 
   0x08048f01 <+136>:	add    $0x1,%ebx //ebx++
---Type <return> to continue, or q <return> to quit---
   0x08048f04 <+139>:	cmp    $0x6,%ebx 
   0x08048f07 <+142>:	je     0x8048f20 <phase_6+167> ebx=6则跳转到5
   //跳转1:0x08048f09 <+144>:	mov    %ebx,%esi //esi=ebx=0
   0x08048f0b <+146>:	mov    0x10(%esp,%ebx,4),%ecx //ecx=a[ebx]=a[0]
   0x08048f0f <+150>:	cmp    $0x1,%ecx 
   0x08048f12 <+153>:	jle    0x8048ef8 <phase_6+127> //0<=a[ebx]<=1则跳转到2
   0x08048f14 <+155>:	mov    $0x1,%eax //eax=1
   0x08048f19 <+160>:	mov    $0x804c13c,%edx //经查看,此处存了一个链表
   0x08048f1e <+165>:	jmp    0x8048eec <phase_6+115> //跳转到3
   阶段2:仍然是一个两层循环,目的在于将我们从链表中取到的结点地址放入栈中保存
   
   跳转5:0x08048f20 <+167>:	mov    0x28(%esp),%ebx //ebx=esp+28(第一个节点地址)
   0x08048f24 <+171>:	lea    0x2c(%esp),%eax  //eax=esp+2c(第二个节点地址)
   0x08048f28 <+175>:	lea    0x40(%esp),%esi  //esi=esp+40 用于链表越界检查
   0x08048f2c <+179>:	mov    %ebx,%ecx //ecx=ebx(第一个节点地址)
   0x08048f2e <+181>:	mov    (%eax),%edx //edx=第二个节点
   0x08048f30 <+183>:	mov    %edx,0x8(%ecx) ecx+8=edx
   0x08048f33 <+186>:	add    $0x4,%eax eax=eax+4 //用于找下一个节点
   0x08048f36 <+189>:	cmp    %esi,%eax 
   0x08048f38 <+191>:	je     0x8048f3e <phase_6+197>
   0x08048f3a <+193>:	mov    %edx,%ecx //
   0x08048f3c <+195>:	jmp    0x8048f2e <phase_6+181>
   阶段3:经过循环 六个结点又依此串联重组起来
   
   0x08048f3e <+197>:	movl   $0x0,0x8(%edx)
   0x08048f45 <+204>:	mov    $0x5,%esi
   0x08048f4a <+209>:	mov    0x8(%ebx),%eax
   0x08048f4d <+212>:	mov    (%eax),%eax
   0x08048f4f <+214>:	cmp    %eax,(%ebx)
   0x08048f51 <+216>:	jge    0x8048f58 <phase_6+223> //前一个节点》>=后一个节点 则不爆炸
   0x08048f53 <+218>:	call   0x80491d5 <explode_bomb>
   0x08048f58 <+223>:	mov    0x8(%ebx),%ebx
   0x08048f5b <+226>:	sub    $0x1,%esi
   0x08048f5e <+229>:	jne    0x8048f4a <phase_6+209>
   阶段4:判断结点保存的六个数中相邻的数是不是都比后面一个数大,也就是非递增的
   
   0x08048f60 <+231>:	add    $0x44,%esp
   0x08048f63 <+234>:	pop    %ebx
   0x08048f64 <+235>:	pop    %esi
   0x08048f65 <+236>:	ret    
End of assembler dump.


2.分段分析

在这里插入图片描述
调用了phase_2使用过的read_six_numbers函数,可知输入为6个数字

在这里插入图片描述
0<=a[0]-1<=5 故:1<=a[0]<=6,后面又发生了循环,可以知道输入的每个数都属于[0,6]

在这里插入图片描述

双层for循环,任意两个数不相等

在这里插入图片描述

在这里插入图片描述
发现了一个链表

分析完阶段4,去看节点里面都存了些什么值
在这里插入图片描述

node1-node6:275->39d->301->1c4->27e->30c

在这里插入图片描述

故应依次取:2,6,3,5,1,4个节点

又因为:
在这里插入图片描述

故答案为:5,1,4,2,6,3

4.测试运行
在这里插入图片描述

终于做完全部了 第6个好难555

四.答案

phase_1And they have no disregard for human life.
phase_21 2 4 8 16 32
phase_30 i 856
phase_499 3
phase_55 115
phase_65 1 4 2 6 3

尾言

初识汇编,被各种循环折磨得头晕目眩
如果发现文章有问题,拜请指正

最后,想对做这个实验的你说:看晕了就歇歇再看,保持头脑清醒,坚持就是胜利

  • 23
    点赞
  • 138
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值