hur.cn - 华软网

 热门搜索

在main函数的起始位置,ebp和esp是否是相等的?

  作者:未知    来源:网络    更新时间:2011/8/11
VC环境下,main函数的反汇编代码如下所示,在起始位置保存了ebp以后,又把esp的值保存到了ebp。

_TEXT SEGMENT
_wmain      PROC
      push  ebp                                 ; 保存旧的ebp
      mov   ebp, esp                            ; ebp保存当前栈的位置
... ...

我的问题是,程序起始阶段,堆栈段上面还是什么都没有的阶段,esp和ebp指向的地方应该相等吧,为什么还要保存esp到ebp呢?

---华软 网友回答---
不一定,main函数不能保证是当前进程执行的第一个代码。很多操作系统在加载可执行文件时,要进行很多预处理。同时编译器产生的代码也可能插在main前面。
---华软网友回复---
而且像int argv, char **args这些命令行参数也是要经过编译器在main之前的预先代码从系统读取并传递给main的,所以这里main应该像普通函数那样,这时候栈里是有东西的。
---华软网友回复---
push ebp ; 保存旧的ebp
mov ebp, esp ; ebp保存当前栈的位置

基本上每个函数的开始都是这么一段,ebp被称为基址寄存器,让它等于esp,就是用来在函数内方便定位局部变量地址的。
---华软网友回复---
引用 3 楼 coding_hello 的回复:
push ebp ; 保存旧的ebp
mov ebp, esp ; ebp保存当前栈的位置
基本上每个函数的开始都是这么一段,ebp被称为基址寄存器,让它等于esp,就是用来在函数内方便定位局部变量地址的。


对于一个调用序列
A() {
 int a;
 B();
 {
  int aa;
  aa = 0;
  a = 0;
 }
}
B() {
 int b;
 C();
 {
  int bb;
  bb = 0; 
  b = 0;
 }
}
在函数B中,在的匿名代码区域里面,局部变量bb会使esp变动,这时通过ebp来定位局部变量b的,并且B退出时需要还原ebp的值。
所以普通函数的机器实现里面,用ebp(而不是esp)来访问局部变量会比较方便的。
main是一个函数,使用上述实现就可以了(不会专门针对main来重新实现一种新的编译规则)。
---华软网友回复---
引用 3 楼 coding_hello 的回复:
push ebp ; 保存旧的ebp
mov ebp, esp ; ebp保存当前栈的位置
基本上每个函数的开始都是这么一段,ebp被称为基址寄存器,让它等于esp,就是用来在函数内方便定位局部变量地址的。


对于一个调用序列
C++">
A() {
 int a;
 B();
 {
  int aa;
  aa = 0;
  a = 0;
 }
}
B() {
 int b;
 C();
 {
  int bb;
  bb = 0;  
  b = 0;
 }
}

在函数B中,在的匿名代码区域里面,局部变量bb会使esp变动,这时通过ebp来定位局部变量b的,并且B退出时需要还原ebp的值。
所以普通函数的机器实现里面,用ebp(而不是esp)来访问局部变量会比较方便的。
main是一个函数,使用上述实现就可以了(不会专门针对main来重新实现一种新的编译规则)。

---华软网友回复---
引用 3 楼 coding_hello 的回复:
push ebp ; 保存旧的ebp
mov ebp, esp ; ebp保存当前栈的位置

基本上每个函数的开始都是这么一段,ebp被称为基址寄存器,让它等于esp,就是用来在函数内方便定位局部变量地址的。

++
[ebp-xxxx]寻址调用局部变量
[ebp+xxxx]寻址函数参数
编译器优化时就直接操作esp对局部变量和参数进行寻址了


---华软网友回复---
用frame结构的函数(函数-callee 本身调节堆栈)才有 ebp。
不用frame结构的函数(C 函数)堆栈由调用者(caller)调整,ebp会用于别的地方
---华软网友回复---
ebp-chain
x86架构上函数编译时一般都开启了frame pointer,每个函数刚进入时都会 mov ebp, esp然后sub esp ,xx
这样每个函数在栈上形成一个从地址esp到ebp的frame,frame中保存本函数的局部变量
frame pointer功能可以通过编译优化选项 surpress frame pointers (FPO)关闭
设计frame pointer的意义在于通过ebp-chain,调试器可以分析整个调用堆栈      
华软声明:本内容来自网络,如有侵犯您版权请来信指出,本站立即删除。