内存

程序与内存的关系,不可分割,内存是承载程序运行的介质,也是程序进行各种运算和表达的场所,了解内存的状况,对于理解程序有着非常重要的作用
下图为一个linux下一个进程里典型的内存布局。
这里写图片描述
一个程序的内存空间,和其系统的位数有关,一般32为系统,其内存大小为4GB,(2的32次方)。但是对于4GB的内存空间,windows系统会默认将高地址的2GB空间分配给内核,linux默认将高地址1GB空间分配给内核。剩下的空间为用户空间。如上图,是32为Linux系统x86体系下的虚拟地址空间。

  1. 保留区
  2. 代码段和只读数据段
  3. 数据段
  4. 堆区
  5. 动态链接库区
  6. 栈区
  7. 命令行参数
  8. 环境变量
    以上为一个进程的虚拟地址空间的内容。

  1. 保留区
    保留区,在大多数的操作系统里,极小的地址是不允许访问的,这也是c语言中将无效指针赋值为0的一个原因,上图中128M的内存空间不可访问,访问会发生段错误。
  2. 代码段和只读数据段
    代码段和只读数据段都是:可读不可写可执行,即内容不容更改。其起始地址为0x08040800。代码段存放的为指令,只读数据段通常存储的是常量字符串。
  3. 数据段
    数据段分为.data和.bss段。数据段可读可写不可执行。.data段中存储的数据类型为初始化过的全局变量和静态变量,(且初始化值不为0)。.bss段中存储的数据类型为未初始化的全局变量和静态变量(或初始化后值为0)。
  4. 堆区
    堆区的数据是通过malloc函数进行分配,通过free进行释放。它的数据增长方式是从低地址向高地址增长,这与栈完全相反。
  5. 动态链接库区
    这个区域用于映射装在的动态链接库,在linux下,如果可执行文件依赖其他共享库,那么系统会从0x40000000开始的地址分配相应的空间,并将共享库载入到该空间。
  6. 栈区
    栈是程序中最为重要的概念之一,没有栈就没有函数,就没有局部变量。另栈具有先进后出的特性,可以将栈想象成一个水杯,先进去的要最后才能出来。栈是一个动态的内存区域,随着函数的消亡而变大或变小,压栈使栈增大,出栈使栈减小。
    并且在经典操作系统中,栈总是向下增长。在i386下,栈顶由esp的寄存器表示,栈底由ebp的寄存器表示。这两个寄存器的位置划定了当前函数的活动范围。压栈使栈顶的地址减小,出栈使栈顶地址增大。
  7. 命令行参数
  8. 环境变量
    命令行参数和环境变量是存储在栈的后边,其存储地址高于栈的起始地址。

对一个小程序做一个简单的入栈出栈介绍

int add(int a,int b)
{
    int temp;
    temp=a+b;
    return temp;
}
void main()
{
    int a=10;
    int b=20;
    add(a,b);
}

这里写图片描述
如图所示:首先确定ebp和esp,共占有12个字节,故开辟出三个单位。
在调用add函数时,做了下面这几件事情。
这里写图片描述
这里总结调用函数时所做的事:
1.将所有或一部分参数压入栈中,如果有其他参数没有入栈,那么使用某些特定的寄存器传递。注意,不论函数的参数是否有默认参,都是需要将参数入栈操作的。还有一点就是进行参数传递时,如果参数为立即数,那么将该立即数直接入栈,省去了从内存中调用数值的步骤,比参数为变量高效一些。
2.把当前指令的下一条指令的地址压入栈中。在图中,就是将call指令的下一条指令压入栈中。
3.跳转到函数体执行。
其中2、3步由call一起执行。此时ebp为图中0x100的位置,esp在ebp的基础上增加了add函数所占内存空间的大小。
另外,如果需要寄存器变量,则在图中所示第五步之后,将寄存器变量入栈。
进入到add函数之后,做了一下几件事情:
这里写图片描述
这里,完成add函数体内的内容(即三句程序)。
注意:在函数体内部返回已知值时,当这个值所占空间小于4字节,则用eax寄存器返回,如果在4-8字节之间,则用eax 和 edx 寄存器一起返回,大于8字节,则系统产生一个临时量将其返回。
关于这个临时量的问题,暂且先放在这里,以后再来解释一下。
接着,做下面几个事:
这里写图片描述
这样就回到了main函数中,然后接着下面的指令继续进行。要知道main函数也是一个函数。
同时,将程序解剖到这一步,我也生成了一些疑问,比如:返回到main函数后,如果没有变量接着返回值,会进行怎样的编译,有变量接着返回值又是怎样的编译,希望可以在后续的工作,再认真看一下。

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值