首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > 嵌入开发 > 汇编语言 >

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

2012-03-27 
push bp的作用是什么以下是这个函数的汇编代码int add(int x, int y){return x+y}有几点不明白,在以下的

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(命令行参数列表)
如果没有参数列表,也要在堆栈中留出一定字节的空间给局部变量使用,

[解决办法]
也要预留


[解决办法]
不同的语言不相同,举个例子吧:
象VS2008的main反汇编后,代码如下

C# code
int main() {   return 0; }
[解决办法]
探讨
如果没有命令行参数也没有其它变量呢?

[解决办法]
访问的是其他函数的
当然访问之后程序依然可正常执行才是最重要的
[解决办法]
学习~

热点排行