zhengyang 原创作品转载请注明出处 《Linux内核分析》MOOC课程
“数据结构+算法”构成了程序,然后程序被编译器处理成机器指令流,在计算机硬件的一系列处理下得到执行。第一节课的学习中,孟宁老师给我们介绍了汇编程序的相关知识:
“数据结构+算法”构成了程序,然后程序被编译器处理成机器指令流,在计算机硬件的一系列处理下得到执行。第一节课的学习中,孟宁老师给我们介绍了汇编程序的相关知识:
寄存器的分类
-
通用寄存器
- 段寄存器
- 标志寄存器
指令寻址模式
- 寄存器寻址
- 直接寻址
- 间接寻址
- 立即数寻址
- 变址寻址
对move指令,后缀中b、w、l、q分别代表的是8位、16位、32位、64位字节操作。
以AT&T为例,重点对如下几个常用指令进行介绍:
poshl %eax
//将eax寄存器处的数据压入堆栈,和如下的代码效果等同
subl $4,%esp
movl %eax,(%esp)
popl %eax
//将eax寄存器中的数据推出堆栈,和如下代码的效果等同
movl (%esp),%eax
addl $4,%esp
enter
//和如下代码的效果等同
pushl %ebp
movl %esp,%ebp
leave
//和如下代码的效果等同
movl %ebp,%esp
popl %ebp
ret
//将栈顶的返回地址弹出到eip,然后按照eip此时指示的指令地址继续执行程序.
call
//首先是将返回地址(也就是call指令要执行时eip的值)压入栈顶,然后是将程序跳转到当前调用的方法的起始地址。
接下来分析试验中的main.c程序
执行如下命令
gcc –S –o main.s main.c -m32
得到main.s程序文件
将影响程序阅读的部分去除之后,得到如下干净的代码
下面对程序进行分析,先从main:处开始
main:
pushl %ebp ;ebp中的数据压入栈顶,esp从“栈顶”下移一位指向“栈顶-1”
movl %esp,%ebp ;esp中的数据移入ebp中
subl $4,%esp ;esp指向“栈顶-2”处
movl $9,(%esp) ;esp所指位置存入数据9
call f ;将eip(第23行代码地址)压入“栈顶-3”处,esp指向“栈顶-3”处,跳转到f函数处
接下来分析
f:
pushl %ebp ;ebp中数据压入堆栈,esp指向“栈顶-4”处
movl %esp,%ebp ;ebp也指向“栈顶-4”处
subl $4,%esp ;esp指向“栈顶-5”处
movl 8(%ebp),%eax ;ebp指向“栈顶-2”处并将数据发送给eax,所以eax为9
movl %eax,(%esp) ;“栈顶-5”处的数据为9
call g ;eip(第15行代码地址)压入堆栈“栈顶-6”处,esp指向“栈顶-6”处,程序跳转到g函数处
leave
ret
再分析
g:
pushl %ebp ;ebp压入堆栈,esp指向“栈顶-7”处
movl %esp,%ebp ;ebp指向“栈顶-7”处
movl 8(%ebp),%eax ;“栈顶-5”处的值传给eax,eax=9
addl $6,%eax ;eax=9+6=15
popl %ebp ;ebp压出栈,esp指向“栈顶-6”处
ret ;返回程序第15行代码处执行,esp指向“栈顶-5”处
...最后返回main:中执行
addl $2,%eax
leave
ret
可以计算出eax=9+6+2