过程调用与栈帧

来源:互联网 发布:远光软件工资待遇 编辑:程序博客网 时间:2024/06/05 18:07

本博客(http://blog.csdn.net/livelylittlefish)贴出作者(三二一@小鱼)相关研究、学习内容所做的笔记,欢迎广大朋友指正!

     

过程调用和栈帧

 

1. 过程调用

一个过程调用包括将数据和控制从代码的一部分传递到另一部分。

过程调用的任务:为过程的局部变量分配空间,并在退出时释放这些空间,俗称保存现场/恢复现场。

 

2. 栈帧

栈的作用:参数传递、局部变量分配、保存调用的返回地址、保存寄存器以供恢复

 

IA32程序用程序栈来支持过程调用。

栈帧:为单个过程分配的那部分栈称为栈帧(stack frame

下图表述了一个通用的栈帧: 

 

 high address |=================|<----+

              |                 |     |

              |                 |     |

              |                 |     |

              |                 |  previous stack frame

              |                 |     |

              |                 |     |

              |                 |     |

              |=================|<----+

              |    ...          |     |

              |                 |     |

              |-----------------|     |

        4+4n  |    param n      |     |

              |-----------------|     |

              |    ...          |  caller stack frame

              |                 |     |

              |-----------------|     |

          +8  |    param 1      |     |

              |-----------------|     |

          +4  |  return addr    |     |

              |=================|<----+

      %ebp->  |     %ebp'       |     |  //this saved %ebp' for previous stack frame

              |-----------------|     |

              |                 |     |

              | saved register  |     |

              | local variable  |     |

              | temp variable   |     |

              |-----------------|     |

              |                 |  callee stack frame

              | param section   |     |

              |                 |     |

              |-----------------|     |

              |                 |     |

              |-----------------|     |

      %esp->  |                 |     |

  low address |-----------------|<----+

 

 

帧指针:%ebp,指向栈底,在本过程中,%ebp值保持不变

栈指针:%esp,指向栈顶,程序执行时,栈指针可以移动,来分配或释放空间

  • %esp减小——分配空间
  • %esp增大——释放空间

 

%ebp不变,而%esp可变,故程序执行中,大多数信息的访问都是相对于帧指针的,例如如下指令:

lea 0xffffffe8(%ebp), %eax ;%ebp-24地址中的数据(实际上是地址)存入%eax寄存器

(回忆一下《汇编语言》,lea是什么?。。。。leaLoad Effective Address

(为什么是%ebp-24?。。。。因为计算机中数据是用反码表示的,反码0xffffffe8表示的值即为-24,即-0x18

 

考虑这样一个调用,调用者caller,被调用者callee

caller调用callee时,caller的返回地址被压入栈中,形成caller栈帧的末尾。

返回地址:就是当程序从callee返回时应该继续执行的地方(指令的地址),当被调用过程返回时,程序会从此处继续执行。

callee的栈帧从保存的帧指针的值(%ebp)开始,其后即为其保存的寄存器的值,和callee调用其他过程的参数。

 

思考:为什么(非寄存器)局部变量存放在栈中而非寄存器中?

  • 寄存器不够存放所有的局部变量
  • 有些局部变量是数组或结构,必须通过数组或结构引用来访问
  • 若要对一个局部变量使用地址操作符“&”,必须能为它产生一个地址

 

一般地,C/C++程序的调用方式为__cdecl,即参数从右向左的顺序入栈;如此,则%ebp+0x8为第一个参数,%ebp+0xc为第二个参数,以此类推。(默认地,编译器会考虑内存按双字对齐)

 

3. 各类型的数据在栈中的排列方式

栈的增长方式:由高地址向低地址方向增长

 

数据存放方式:

例如内存中存放的long型数据为0x12345678

 

a. 高端法(Gig Endian)

 

高字节(高位) => 低地址

低字节(低位) => 高地址

 

       |----------|

0x2003 |    78    | high address

       |----------|

0x2002 |    56    |

       |----------|

0x2001 |    34    |

       |----------|

0x2000 |    12    | low address

       |----------|

 

 

数组存放方式(大端法):

例如int a[8];

 

             |----------|

a[7], 0x2017 |    80    | high address

             |----------|

a[6], 0x2016 |    70    |

             |----------|

a[5], 0x2015 |    60    |

             |----------|

a[4], 0x2014 |    50    |

             |----------|

a[3], 0x2013 |    40    |

             |----------|

a[2], 0x2012 |    30    |

             |----------|

a[1], 0x2011 |    20    |

             |----------|

a[0], 0x2010 |    10    | low address

             |----------|

 

b. 小端法(Little Endian)

 

高字节(高位) => 高地址

低字节(低位) => 低地址

 

       |----------|

0x2003 |    12    | high address

       |----------|

0x2002 |    34    |

       |----------|

0x2001 |    56    |

       |----------|

0x2000 |    78    | low address

       |----------|

 

 

4. 过程调用和返回指令

  • call 过程调用,有一个目标地址(被调用过程起始点指令地址)

任务:将返回地址入栈,并跳转到被调用过程的起始处

  • leave:为返回准备栈

任务:

movl %ebp, %esp ;set stack pointer to the beginning of frame

popl %ebp ; restore saved %ebp and set stack ptr to the end of caller's frame

  • ret 从过程调用中返回

任务:从栈中弹出返回地址,并跳转到那个位置

 

%eax通常用来返回值,如果函数要返回整数或指针。 

 

Reference

关于程序调用方式:

http://yangwei.blogbus.com/logs/1550582.html

http://blog.csdn.net/cradmin/archive/2008/10/22/3124159.aspx

 

栈帧结构:

《深入理解计算机系统》

http://bigwhite.blogbus.com/logs/2005/11/1592114.html

http://bbs.tech.ccidnet.com/read.php?tid=645517

原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 被野猴子抓伤了怎么办 孩子入学前疫苗补不全怎么办 额头肤色比脸黑怎么办 高跟鞋小了挤脚怎么办 老板欠工人工资不给怎么办 小孩吃了生豆子怎么办 拍夜晚的天空太亮怎么办 购房发票字体不清晰怎么办 接到客人电话预定时怎么办 产检资料弄丢了怎么办 工作中同事喜欢争风头怎么办 想出卖身体赚钱了怎么办 孩子生下来不想要了怎么办 舌头被铁管冻住怎么办 人被水泥冻住了怎么办 姑娘果孕妇吃了怎么办 纹身后吃了辣的怎么办 怀孕五个多月不想要了怎么办 失业后又干保安档案怎么办 前列大腺脓肿要怎么办 小动物死了孩子很伤心怎么办 向客人开错房间怎么办 工伤认定没有证人证言怎么办? 一个月没来月经怎么办14岁 刮了胡子下巴痒怎么办 月经多怎么办喝什么好 大姨妈不调怎么办来了 多人被骗没证据怎么办 一直坏肚子拉水怎么办 犯人在监狱有高危高血压怎么办 丈夫出轨他死都不承认怎么办 没写欠条的债该怎么办 被尾随回家知道住处怎么办 微信记录全没了怎么办 微信记录没有了怎么办 ipad登录不了下不了软件怎么办 苹果手机打开自动时间不对怎么办 魅族手机时间不同步怎么办 小米手环时间不准怎么办 电脑网络dns配置错误怎么办 去泰国手机要打电话怎么办