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

好久不用,很多内容都忘了。刚刚复习了一下,再写一遍:32位x86系统C函数调用时的内存分布。

 

每个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),被调用函数首先执行如下指令:

pushl %ebp
movl  %esp, %ebp

 

此时 esp=ebp=0x10。

 

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

 

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

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

 

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

 

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

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值