前言
这篇文章主要记录了我做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 |
---|---|
15 | 6 |
14 | 14 |
13 | 2 |
12 | 1 |
11 | 10 |
10 | 0 |
9 | 8 |
8 | 4 |
7 | 9 |
6 | 13 |
5 | 11 |
4 | 7 |
3 | 3 |
2 | 12 |
1 | 5 |
故第一个输入可以为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_1 | And they have no disregard for human life. |
---|---|
phase_2 | 1 2 4 8 16 32 |
phase_3 | 0 i 856 |
phase_4 | 99 3 |
phase_5 | 5 115 |
phase_6 | 5 1 4 2 6 3 |
尾言
初识汇编,被各种循环折磨得头晕目眩
如果发现文章有问题,拜请指正文章来源:https://www.toymoban.com/news/detail-442018.html
最后,想对做这个实验的你说:看晕了就歇歇再看,保持头脑清醒,坚持就是胜利文章来源地址https://www.toymoban.com/news/detail-442018.html
到了这里,关于《深入理解计算机系统》Lab2-Bomblab的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!