系统栈的工作原理

(1)内存的不同用途

不管什么样的操作系统、计算机结构, 一个进程使用的内存按照功能大致分为以下4个部分
  1.  代码区:存储着被转入执行的二进制代码,处理器会到这个区域取指并执行
  2. 数据区:用于存储全局变量等
  3. 堆区:进程可以再堆区动态地请求一定大小的内存,并在用完之后归还给栈区。动态分配和回收是堆区的特点
  4. 栈区:用于动态存数函数之间的调用关系,以保证被调用函数在 返回时恢复到母函数中继续执行
在windows平台下,高级语言写出的程序经过编译连接后,最终变成PE文件(可执行文件)。当PE文件被装载运行后,就是进程。
PE文件的机器代码会被载入到内存的代码区,处理器将到内存的 这一区域取指,然后送入到算数逻辑单元执行;如果代码请求开辟动态内存,则会在内存的堆区分配一块大小合适的区域返回给代码区的代码使用;当函数调用发生时,函数的调用关系在等信息会动态地保存在栈区, 以供处理器在执行完函数调用代码时,返回母函数。过程如图
 
如果把CPU比作一个有条不紊的工厂,我们可以得到如下类比:
CPU是完成工作的工人
数据区、栈区、堆区是则是存放 原料、成品等的场所
存在代码区的指令则告诉CPU做什么,如何做
(2)函数调用时发生了什么
通过以下例子研究一下函数调用和递归等性质是如何通过系统栈巧妙实现的
int  func_B(int arg_B1, int arg_B2)
{
  int var_B1, var_B2;
  var_B1=arg_B1+arg_B2;
  var_B2=arg_B1-arg_B2;
  return var_B1*var_B2;
}

int  func_A(int arg_A1, int arg_A2)
{
  int var_A;
  var_A = func_B(arg_A1,arg_A2) + arg_A1 ;
  return var_A;
}

int main(int argc, char **argv, char **envp)
{
  int var_main;
  var_main=func_A(4,3);
  return var_main;
}
       
 经过编译后,各函数对用的机器指令在代码区的分布如左下,不同的函数可能相邻,可能不相邻
当CPU执行调用fun_A 函数时,会从代码区中main函数对应的机器指令的区域跳转到fun_A 对应的机器指令区域,在那里取指并执行;当fun_A 返回时,又回到main的机器指令区域,条用fun_A后面的指令继续执行main函数的代码,CPU的执行轨迹如右下

                         

在函数调用的过程中,伴随的系统栈的操作如下

  1. 在main函数调用fun_A的时候,首先在自己的栈中压入函数返回地址,然后为fun_A创建新栈帧压入系统栈
  2. 在fun_A调用fun_B的时候,同样自己的栈中压入函数返回地址,然后为fun_B创建新栈帧压入系统栈
  3. 在fun_B返回时,fun_B的栈帧被弹出系统栈,fun_B栈中的返回地址被“露”在栈顶,此时CPU按照这个返回地址回到fun_a的代码区执行
  4. 在fun_A返回时,fun_A的栈帧被弹出系统栈,main栈中的返回地址被“露”在栈顶,此时CPU按照这个返回地址回到main的代码区执行
函数调用大致包括以下几个步骤
  1. 参数入栈:参数从右到左的入栈
  2. 返回地址入栈
  3. 代码区跳转
  4. 栈顶调整
调用时用到的指令序列如下
 ;调用前
push 参数3    ; 假设该函数有3个参数,将从右向左依次入栈
push 参数2    
push 参数1    
call 函数地址  ; call指令将同时完成两项工作:a)向栈中压入当前指令在内存中的位置,          ; 即保存返回地址;b)跳转到所调用函数的入口地址

  ;函数入口处
push ebp      ; 保存旧栈帧的底部
mov ebp,esp    ; 设置新栈帧的底部(栈帧切换)
sub esp,xxx    ; 设置新栈帧的顶部(抬高栈顶,为新栈帧开辟空间)



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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值