专注收集记录技术开发学习笔记、技术难点、解决方案
网站信息搜索 >> 请输入关键词:
您当前的位置: 首页 > 汇编语言

push bp的作用是什么,该如何处理

发布时间:2010-06-14 15:51:37 文章来源:www.iduyao.cn 采编人员:星星草
push bp的作用是什么
以下是这个函数的汇编代码
int add(int x, int y){return x+y;};
有几点不明白,在以下的注释中
Assembly code

 push    ebp                    ;缓存栈基址,为什么要缓存栈基址?
 mov     ebp, esp               ;为什么要将目前栈顶作为栈基址?
 mov     eax, dword ptr [ebp+C] ;
 add     eax, dword ptr [ebp+8] ;
 pop     ebp                    ;为什么要恢复栈基址?
 retn                           ;返回



------解决方案--------------------
这条语句是为了保护ebp因为在函数中要使用ebp来取得主程序传来的实参
说白了这段代码就是典型的参数传递问题:是通过堆栈来实现的

 push ebp ;因为子程序中要使用栈基址寄存器ebp
 mov ebp, esp ;将目前栈顶赋给基址寄存器是为了使用 [esp+C/B]来取得入口参数
 mov eax, dword ptr [ebp+C] ;
 add eax, dword ptr [ebp+8] ;
 pop ebp ;上面的保护子程序中使用的ebp,现在要返回前当然要恢复栈基址ebp了
 retn ;返回

------解决方案--------------------
上述方法利用堆栈实现主程序与子程序间的参数传递,这也是堆栈的主要作用之一.
------解决方案--------------------
函数的参数和局部变量都是在栈中分配的,ebp寄存器就是为了方便访问栈中的数据而设计的,通常的函数开头都会执行
push ebp
mov ebp, esp
sub ebp, xxx
这样的代码,之后[ebp]是原ebp的值,[ebp+4]是返回地址,[ebp+8]开始向后是函数的各个参数,[ebp-4]开始向前是局部变量。
函数返回前会执行
mov esp, ebp
pop ebp
push和pop的目的是保护ebp的原值不被破坏。
------解决方案--------------------
上面写错了一点,sub ebp, xxx应该是sub esp, xxx,其目的是为局部变量分配空间,xxx表示该函数内存所有局部变量所需的总空间(字节数)。
------解决方案--------------------
顶!

栈结构(参数入栈顺序跟调用方式有关,这里以C语言默认的CDECL为例):

+| (栈底方向,高位地址) |
| ....................|
| ....................|
| 参数3 |
| 参数2 |
| 参数1 |
| 返回地址 |
-| 上一层[EBP] |
| 局部变量1 |
| 局部变量2 |
|.....................|
 
补充:栈一直随着函数调用的深入,一直想栈顶方向压下去。每次调用函数时候,先压函数参数(从右往左顺序压),再压入函数调用下条指令的地址(由call完成)。接着进入调用函数体中先执行PUSH EBP; MOV EBP ESP;(一般已经由编译器加入到函数头中了),接着就是吧函数体中的局部变量压入栈中。再遇到函数的调用的嵌套则依此类推。(added by smsong)

“PUSH EBP”“MOV EBP ESP”这两条指令实在大有深意:首先将EBP入栈,然后将栈顶指针ESP赋值给EBP。“MOV EBP ESP”这条指令表面上看是用ESP把EBP原来的值覆盖了,其实不然——因为给EBP赋值之前,原EBP值已被压栈(位于栈顶),而新的EBP又恰恰指向栈顶。
此时EBP寄存器就已处于一个很重要的地位,该寄存器中存储着栈中的一个地址(原EBP入栈后的栈顶),从该地址为基准,向上(栈底方向)能获取返回地址、参数值,向下(栈顶方向)能获取函数局部变量值,而该地址处又存储着上一层函数调用时的EBP值!
------解决方案--------------------
Assembly code

 push    ebp                    ;这是保存栈的基地址,因为被调用程序要利用当前栈的相对位置来访问栈内数据
                                     ;当然你也可以不这么做,试想一下你如何获得当前esp+c处的数据,(每次push的时候,esp都是变化的)
 mov     ebp, esp               ;仔细看上面
 mov     eax, dword ptr [ebp+C] ;取得y的值,一般入栈顺序使自右往左
 add     eax, dword ptr [ebp+8] ;取得x的值
 pop     ebp                    ;为什么要恢复栈基址?修改了栈的基地址后,却要返回,但调用程序的栈可能还会用其他有用的数据,不能被破坏
 retn                           ;维持栈平衡,执行这句后,esp指向了x,y入栈前的栈位置

------解决方案--------------------
这要看具体情况了,总之不要随便改ebp就是了。
------解决方案--------------------
正好 遇到类似问题,学习下
------解决方案--------------------
调用函数的过程就是入栈和出栈啊~
------解决方案--------------------
谢谢...明白了,不过还有一点. 
就是把main函数反汇编时也是一样的先.push ebp mov ebp, esp 
如果此时 add ebp 会访问到什么样的数据呢?这样是否是跨越程序段访问数据了?

此时是否[ebp+X],要看是否有实参要取出,即是否有main(命令行参数列表)
如果没有参数列表,也要在堆栈中留出一定字节的空间给局部变量使用,

------解决方案--------------------
也要预留
友情提示:
信息收集于互联网,如果您发现错误或造成侵权,请及时通知本站更正或删除,具体联系方式见页面底部联系我们,谢谢。

其他相似内容:

热门推荐: