陈涛(sa16225028) + 原创作品转载请注明出处 + 《Linux内核分析》MOOC课程http://mooc.study.163.com/course/USTC-1000029000
本次实验主要通过写一个c语言程序进行汇编,从而理解计算机是如何执行这些代码以及分析其堆栈的变化。
一、在实验楼虚拟机上编写c语言代码
二、对其代码进行汇编
输入gcc –S –o main.s main.c -m32 ,从而形成汇编代码,如图:
24行:leave
25行:ret
三、阐述堆栈的变化过程
当开始执行改程序的时候,eip是指向main函数入口地址,即eip指向18行存放的指令。设默认的堆栈栈低寄存器ebp的值为1000,则堆栈栈顶指针也为1000。
1、pushl %ebp: 把ebp的值压入堆栈,esp=996,栈顶值为1000
2、movl %esp,%ebp: 将esp的值传给ebp,则ebp值为996
3、subl $4,%esp:将esp的值减去4,则esp的值为994
4、movl $24,(%esp): 将esp所指的值为地址(寄存器间接寻址)的值 赋为24(堆栈的栈顶存放24)
此时堆栈:
5、call f:相当于pushl eip和movl f eip。堆栈先压入eip(23),esp=esp-4=988。然后把f函数的入口函数地址赋值给eip(存放第9行的指令代码)
此时堆栈:
6、pushl %ebp: 在堆栈中压入ebp的值,esp=esp-4=984
7、movl %esp,%ebp: 把esp的值赋给ebp。ebp=esp=984
8、subl $4,%esp: 把esp的值减去4。esp=esp-4=980
9、movl 8(%ebp),%eax: 把ebp+8的地址上所存的值赋给eax,即把地址为992,值为24赋值给eax寄存器
10、movl %eax,(%esp): 相当于压栈
此时堆栈:
11、call g: 相当于pushl eip和movl g eip。栈堆先压入eip(15),在把函数g的入口地址赋给eip
此时堆栈:
12、pushl %ebp: 堆栈压入ebp的值
13、movl %esp,%ebp: 把esp的值赋给ebp
14、movl 8(%ebp),%eax: 将ebp的值加8作为地址,其值赋给eax。即,eax值为24
15、addl $6,%eax: 将eax的值加6。eax的值为30
16、popl %ebp:堆栈弹出,其值赋给ebp。
此时堆栈:
17、ret : 相当于popl %eip(*)。堆栈弹出,其值赋给eip。则eip指向了存储15行代码的地址。
此时堆栈:
18、leave: 相当于movl %ebp,%esp和popl %ebp。将ebp的值赋给esp,堆栈弹出,其值赋给ebp。相当于销毁g的函数堆栈意思。esp=988,ebp=996。
此时堆栈:
19、ret : 相当于popl %eip(*)。堆栈弹出,其值eip(23)赋给eip。
20、addl $4,%eax: 把eax的值加上4,eax的值为30+4=34。
21、leave :相当于movl %ebp,%esp和popl %ebp。将ebp的值赋给esp,堆栈弹出,其值赋给ebp。相当于销毁f的函数堆栈意思。esp=1000,ebp=1000
此时堆栈:
22、ret :相当于popl %eip(*)。把eip赋给调用该c语言程序的命令地址。最后eax的值为34。
总结:
计算机的基本原理是存储程序和程序控制。先要把程序和原始数据存放在内存当中。计算机在运行时,根据eip的值来执行指令,从指定地址中取出数据来进行运算,以此类推… 程序与数据同等地位存储,按程序的设计顺序,一步一步地取出指令以及执行指令是计算机最基本的工作原理。这原理是由美籍匈牙利数学家冯.诺依曼提出来的,故称为冯.诺依曼原理。