现在的位置: 首页 > 综合 > 正文

x86系统C语言函数调用时的内存分布

2018年03月21日 ⁄ 综合 ⁄ 共 1068字 ⁄ 字号 评论关闭

每个C语言函数在运行过程中,在栈顶对应一个栈帧。想想堆栈是一个地址由上往下增长的线性内存(为什么要由上往下增长?后面说明),栈帧的顶端地址位于esp寄存器,栈帧底部地址由ebp寄存器保存(当然,这个说法不准确,ebp再往下还有这个函数的参数,后面详细说明)。结构如下所示(每行4字节):

 

00  临时变量2                               <---- esp

04  临时变量1

08  局部变量2

0C  局部变量1

10  调用函数ebp指针值                  <---- ebp

14  调用函数下一条执行指令地址

18  参数1

1C  参数2

可以看出,esp指向栈顶,ebp指向调用函数的ebp值: *esp = (first temp variable), *ebp = (last function's ebp),第一个参数是*(ebp+8),上一个函数中的返回指令是*(ebp+4)

 

在函数调用前,esp指向参数1(0x18),执行call命令后,esp指向调用函数下一条执行指令地址(0x14),被调用函数首先执行如下指令:

At&t asm代码  收藏代码
  1. pushl %ebp  
  2. movl  %esp, %ebp  

 

此时 esp=ebp=0x10。

 

 ok,回到刚才的问题,为什么要从上往下想象地址空间。这种想象地址空间的能力非常重要,这个搞不好,在学汇编和读汇编时会比较郁闷。

 

一般我们想象一个栈的时候,要么从上往下增长,要么从下往上增长,或者从左往右、从右往左增长。不过一般push时我们感觉是“压进去”,pop时感觉是“弹出来”,这样从上往下增长的话,感觉比较怪异:往上面压进去,从上午往下弹出来。而水平压进去、弹出来的话,展示栈中的内容展示不了多少,因为栈中数字一般是四字节(对于32位系统)一个数据,水平写栈中内容的话可能就是如下的样子:

0x12345678  0x87654321  0x12345678  0x87654321  0x12345678  0x87654321 

 

一行写不了几个数据,并且还看着比较不舒服。所以,栈从下往上涨是想起来最舒服的。

 

而内存空间为什么地址从上往下依次增大想象起来更舒服一些呢?首先,栈一般都是从大地址往小地址增长的,按照栈从下往上增长的方向,内存地址当然要从上往下增长了。另外,C语言中的结构(struct)都是从上往下写的,而一般上面的地址比下面的地址要小,更靠前,因此地址从上往下想时也更加符合平时看着的习惯。

http://spartan1.iteye.com/blog/1266594

抱歉!评论已关闭.