程序可以被分成三段(部分):
指令、数据和函数。
elf可执行文件的分段:
文件头,包含文件的类型等信息。
数据段,静态数据,包括全局变量和静态变量;
代码段,要执行的指令;
栈,除了栈是自顶向下增长外,其他模型都是自底向上增长。
堆,程序员自己管理的数据区域。
所以程序在内存中的存储,并不是按写的时候那样存放,而是数据放一起,指令放在一起,函数调用放在一起。
%是寄存器,如%edx;
$是常量,比如$0x1;
()是内存,比如(%edx);
push是将ebp寄存器的值存到内存;
pop是将esp内存的值存到寄存器。
ebp是栈底指针;
esp是栈顶指针。
函数调用的基本操作:
1.跳转到函数调用地址;
2 建立新栈帧;
3.存储局部变量;
那么堆栈后,怎么修改临时变量呢?
比如a=0;存入栈中,一顿堆栈,
此时a=1;那么要通过栈底指针ebp索引变量a的数据,并通过mov赋值。
栈用来存储:
1)push操作先移动栈顶指针,之后将信息入栈。
2)esp为堆栈指针,栈顶由esp寄存器来定位。压栈的操作使栈顶的地址减小,弹出的操作使栈顶的地址增大。
3)ebp是32位的bp,是基址指针。bp为基指针寄存器,用它可直接存取堆栈中的数据,它在调用函数时保存esp,以便函数结束时可以正确返回。
4)默认的函数内部变量的压栈操作为:从上到下、从左向右,采用4字节对齐。数组压栈方法略有不同,即从最后一个元素开始,直到起始元素为止,即采用从右向左的方法压栈。
压栈操作是4字节对齐,所以即使压入的是char类型,也占用4字节
每个函数在调用前都会做一件事情。
(1)把调用方的ebp入到自己的栈里去
(2)用esp指向新的栈顶位置,把esp的值赋给ebp,产生新的ebp
(3)开辟空间,初始0XCCCCCCCC。
ebp入栈,实参入栈,形参入栈,调用call指令。call有两步,把下一行指令的地址入栈,跳转到调用的函数执行。形参内存主调方开辟,主调方释放。