venus565825

 

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

<!--[if !vml]--><!--[endif]-->

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

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 )
        }

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

<!--[if !vml]--><!--[endif]-->

四 : 例子

 

 

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 。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值