zhang 原创作品转载请注明出处 《Linux内核分析》MOOC课程http://mooc.study.163.com/course/USTC-1000029000
代码如下:
该代码运行中主要涉及以下寄存器ebp(指向栈底),esp(指向栈顶),eax(存放返回值),eip(指向运行代码)
接下来按运行顺序来分析(假定ebp,esp开始指向0,并将堆栈每隔32位从高到底依次命名为1,2,3...)
pushl %ebp 在1位置存入ebp地址0,esp指向1
movl %esp, %ebp 使ebp指向esp指向地址(1)
subl $4, %esp esp指向2
movl $8, (%esp) 在2位置存入8
call f 先将eip当前地址(addl $1, %eax所在行)存入堆栈(3位置),然后将f位置存到eip中
f: 顺序往下执行
pushl %ebp 在4位置存入ebp地址0,esp指向4
movl %esp, %ebp同上,此时ebp与esp指向4
subl $4, %espesp指向5
movl 8(%ebp), %eax 将ebp(4)-8/4 = 2位置的值给eax,eax=8
movl %eax, (%esp)在5位置存入8
call g 先将eip当前地址(leave所在行)存入堆栈(6位置),,esp指向6,然后将g位置存到eip中
g: 顺序往下执行
pushl %ebp
movl %esp, %ebp同上,此时ebp与esp指向7
movl 8(%ebp), %eaxeax = 8
addl $3, %eaxeax = 8 + 3 = 11
popl %ebp ebp指向4,esp指向6
ret 将6位置的地址存入eip,eip指向了f中的leave,然后esp指向5
leave 将ebp(4)存入esp,弹出ebp,ebp指向0,esp执行3
ret 将3位置的地址存入eip,eip指向addl $1, %eax,esp指向2
addl $1, %eax eax = 11 + 1 = 12
leave ebp(0)存入esp,弹出ebp,ebp指向0,,esp指向0
ret eip没有下一条指令,运行结束
总结:计算机通过堆栈来存储数据,在堆栈空间中通过ebp设定不同的栈底指针来进行函数跳转以及恢复现场,函数内的操作通过esp来完成。eip负责保存下一条需要执行的指令。