文章详情

  • 游戏榜单
  • 软件榜单
关闭导航
热搜榜
热门下载
热门标签
php爱好者> php文档>堆栈调用,局部变量

堆栈调用,局部变量

时间:2007-02-13  来源:wxz20032003

堆栈调用,局部变量

一:在分析汇编代码时总是要遇到无数的Call,对于这些Call,尽量要根据Call之前传递的参数和Call的返回值来判断Call的功能。传递参数的工作必须由函数调用者和函数本身来协调,计算机提供了一种被称为栈的数据结构来支持参数传递。
   当参数个数多于一个时,按照什么顺序把参数压入堆栈。函数调用后,由谁来把堆栈恢复。在高级语言中,通过函数调用约定来说明这两个问题。常见的调用约定有:

二:堆栈框架也称为活动记录,它为程序的返回地址,传递进来的参数,保存的寄存器喝局部变量保存的堆栈空间。堆栈框架是按以下的步骤创建的。

1:参数被压入堆栈。

2:过程被调用,返回地址被压入堆栈。

3:过程开始执行时,EBP被压入堆栈。

4:使EBP和ESP的值相等,从这里开始,EBP就作为寻址参数的基址指针。

5:可以从ESP中减掉一个数值来给过程的局部变量创建空间。

 

【例】按__stdcall约定调用函数test2(Par1, Par2)   

        push par2  ; 参数2              ;参数被压入堆栈(从右向左)
        push par1  ; 参数1              ;
        call test2;                            ;过程被调用
        {                                ;过程开始执行
             push ebp                    ; EBP被压入堆栈,保护现场原先的EBP指针
             mov  ebp, esp            ;使EBP=ESP, 设置新的EBP指针,指向栈顶,

;从这里开始,EBP就作为寻址参数的基址指针。
             mov  eax, [ebp+0C]  ; 调用参数2
             mov  ebx, [ebp+08]   ; 调用参数1
             sub  esp, 8              ; 若函数要用局部变量,则要在堆栈中留出点空间

;从ESP中减掉一个数值来给过程的局部变量创建空间
             …
             add  esp, 8                 ; 释放局部变量占用的堆栈
             pop  ebp                    ; 恢复现场的ebp指针
             ret  8                      ; 返回(相当于ret; add esp,8)
        }

三: 其堆栈调用示意图:(编译原理的教程中说的更清楚)

四:例子

 

 

00401000  /$  6A 04        push    4               ; /Arg2 = 00000004

00401002  |.  6A 03         push    3                ; |Arg1 = 00000003

00401004  |.  E8 16000000   call    0040101F          ; \local.0040101F

00401009  |.  8BD8         mov     ebx, eax

0040100B  |.  6A 00         push    0                ; /ExitCode = 0

0040100D  \.  FF15 00204000 call    dword ptr [<&KERNEL32.ExitProces>; \ExitProcess

 

 

 

 

 

00401013      00            db      00

00401014      00            db      00

00401015      00            db      00

00401016      00            db      00

00401017      00            db      00

00401018      00            db      00

00401019      00            db      00

0040101A      00            db      00

0040101B      00            db      00

0040101C      00            db      00

0040101D      00            db      00

0040101E      00            db      00

 

 

 

 

 

 

0040101F  /$  55           push    ebp

00401020  |.  8BEC         mov    ebp, esp

;使EBP=ESP=0012FFB4

;设置新的EBP指针,指向栈顶,

;从这里开始,EBP就作为寻址参数的基址指针。

00401022  |.  83EC 04       sub     esp, 4

;扩展栈空间ESP=0012FFB0

00401025  |.  8B45 0C       mov    eax, dword ptr [ebp+C];

                                                               ;当前堆栈3个双字偏移的数值

                                                               ; ebp+C=0012FFB4+C=0012FFC0

                                                               ;EAX=[0012FFC0]=00000004

00401028  |.  8B5D 08       mov     ebx, dword ptr [ebp+8]

                                                               ;当前堆栈2个双字偏移的数值

                                                               ; ebp+8==0012FFB4+8=0012FFBC

                                                               ;EBX=[0012FFBC]=00000003

0040102B  |.  895D FC      mov     dword ptr [ebp-4], ebx

                                                               ;[ebp-4]就是局部变量=[0012FFB4-4]=[0012FFB0]

                                                               ;自动减4,也就是将EBX中的值00000003

;放入堆栈的0012FFB0地址处

;参数1放局部变量里

0040102E  |.  0345 FC       add     eax, dword ptr [ebp-4]

                                                               ;将局部变量与EAX相加后放入EAX中

                                                               ;EAX=00000007

                                                               ;参数2与局部变量相加

00401031  |.  83C4 04       add     esp, 4

                                                               ; 释放局部变量占用的堆栈,ESP: 0012FFB4

00401034  |.  5D            pop     ebp

                                                               ;恢复原有的EBP, ESP:0012FFB8

00401035  \.  C2 0800       retn    8

                                                               ; 返回(相当于ret; add esp,8)

                                                               ; ESP: 0012FFC4

 

 

 

堆栈的情况:

0012FFB0   00000003        ;局部变量

0012FFB4   0012FFF0              ;保存EBP, push    ebp

0012FFB8   00401009       ;压入返回地址

;返回到 local.<模块入口点>+9 来自 local.0040101F

0012FFBC   00000003        ; push    3,每次堆栈地址加32位,双字

0012FFC0   00000004        ; push    4

 

 

 

 

五:说明

Intel的堆栈是在内存中是向下扩展的。先进栈的数据内存地址最高,后进栈的数据内存地址减少。且数据是按小尾类型存储,例如:数值12345678H存放的形式(假设按字):先存1234,后存放5678。

相关阅读 更多 +
排行榜 更多 +
辰域智控app

辰域智控app

系统工具 下载
网医联盟app

网医联盟app

运动健身 下载
汇丰汇选App

汇丰汇选App

金融理财 下载