计算机在执行过程中,最重要的寄存器就是eip,eip指向哪里,cpu就从哪里取指执行,所以要想让程序执行某一个指令,只需要让eip寄存器指向该指令的内存地址即可。但是程序员是不能直接操作eip寄存器的,即不能通过movl指令直接给eip寄存器赋值。eip寄存器的值在顺序执行过程中,执行一条指令后会自动变化指向下一条指令,这是程序员无需操心的。要想不按顺序执行,则可通过call、ret、jmp、pop等指令间接改变eip寄存器的值,实现非顺序执行。
下面我们通过一段c程序的执行来说明在程序执行过程中eip寄存器及ebp和es寄存器的变化,从而了解计算机的和工作过程和函数的调用。
通过
gcc –S –o main.s main.c -m32生成汇编代码,并去除其中以.开头的行。
我们看一下在整个执行过程中栈的变化过,图中的一个小单元格的为一个字节,合并的4个小单元格为一4个字节(即int型和指针型的长度)。
图中左侧为栈的增长过程,图中右侧为栈的收缩过程。
line11和line4为什么是8(%esp呢),我们看一下这张图,因为在栈帧中不光有压入参数时的4个字节,还有call指令时压入的eip寄存器的值,即line20和line12时压入的line21和line13的地址。
王建新原创作品转载请注明出处
《Linux内核分析》MOOC课程http://mooc.study.163.com/course/USTC-1000029000