万子惠 + 原创作品转载请注明出处 + 《Linux内核分析》MOOC课程http://mooc.study.163.com/course/USTC-1000029000 ”
实验部分(反汇编简单的C程序)
代码:
int g(int x)
{
return x + 6;
}
int f(int x)
{
return g(x);
}
int main(void)
{
return f(4) + 8;
}
最后结果应为18
- 在Code下新建main.c
- 进行编译和反编译
- 反编译结果如下
清理完后*这里vim推荐使用dd(删除整行)
(清理掉.开头的部分)
那么接下来我们开始分析了,这里我们先准备好环境如图
和视频里一样我们简化地址值(本应该是一个向下增长,地址逐渐减小的值)
首先看从main函数开始看:
1.将ebp的值入栈,入栈有两个效果,一是esp向下一位增长一位,然后是在现在的esp上存入ebp的值(当前为0)。
2.将esp的值赋给ebp,就是把ebp移到和esp相同位置。
3.将esp向下移4
4.在esp的位置上存上4
call f=>存储call的下一条指令位置(addl) ,然后跳转到f所在的位置
6.esp向下移动一格并存入ebp当前的值(1)
7.将ebp移到esp当前的位置
8.esp向下移动一格
9.将edp上上在走两格的数据放入eax
10.将eax的值存到esp的位置上
- call g=>存储call的下一条指令位置(ret) ,然后跳转到g所在的位置
12.ebp(4)的值入栈
13.将ebp移到esp的位置
14.将当前ebp的前两个位置的值(4)赋给eax
15.将当前esp的值(4)赋给ebp, esp向上移动一格
16.返程咯,出栈,ebp回到上一个被记录的位置,esp上移
ret=popl %eip
18.回到15行
leave:movl %ebp,%esp
popl %ebp
ret=popl %eip
20.回到23行,eax加8
22.ret,eip回到之前的堆栈
最后的返回值为18
总结部分
part1
学习到汇编语言的基本知识,以及一些名词的意思。
API:程序员与计算机的 接口界面
ABI:二进制接口
cs:eip :用来准确定位指令
几种计算指令:[b,w,l,q:8位,16位,32位,64位]
movl %eax,%edx 寄存器寻址
movl $0x123,%edx 立即数寻址
movl 0x123,%edx 直接寻址
movl (%edx),%edx 间接寻址
movl 4(%edx),%edx 变址寻址(edx=*(int 32_t*)(edx+4))
pushl %eax =>sub $4,%esp
movl %eax,(%esp)
popl %eax =>movl(%esp),%eax
movl $4,%esp
call X (保存当前的eip并读取下条为新eip)
ret =>popl %eip
enter =>push %ebp (创建新空栈)
=>movl %esp,%ebp
leave =>movl %ebp,%esp (撤销函数调用堆栈)
=>popl %ebp
ret:pop eip
堆栈调用特性:向下伸长,向上还原
part2我对计算机如何工作的理解
总体来讲,我觉得用冯诺依曼的模型来描述计算机的工作过程是很精到的。
(特别是对汇编代码进行了一步一步的分析之后,就更能深入体会到这种过程。)
我觉得老师视频里边的那个图更好说明这种方式
在我来用文字说明的话,计算机就是通过cpu的运行经过总线调用内存中数据存储的部分一条一条的按照顺序执行不停地进行存储修改等变化操作,使得我们得到自己想要得到的效果以及存储内容。
part3 学习感受
视频都裁剪得很短,看起来很有快感啊。之前学习过有关汇编的知识但都忘得差不多了,在这个视频多多少少补全了回来,感觉不错。计算机的脑子是很死很顺溜的,所以为了实现强大的功能,它的基本的汇编语言的确就是繁琐的,不算绕。希望在这里能打好基础,往后的学习能更加轻松些。