对call、retn的深入分析和认识

来源:互联网 发布:fgo石头号除了淘宝 编辑:程序博客网 时间:2024/05/01 16:15

为了加深对call、retn的理解,我今天用delphi写了一个小程序,在OD中跟踪程序执行call及retn时堆栈的变化。

程序很简单:

对应的汇编代码:

004A4D28   .  B8 3C4D4A00   mov     eax, 004A4D3C                    ;  ASCII "bbbbbbbb"
004A4D2D   .  E8 9EFFFFFF   call    004A4CD0
004A4D32   .  C3            retn

 

004A4CD0  /$  55            push    ebp

...........

004A4D21   .  59            pop     ecx
004A4D22   .  59            pop     ecx
004A4D23   .  5D            pop     ebp
004A4D24   .  C3            retn

执行到004A4D2D,esp=0013F630,F7进去后到达004A4CD0  也就是summ的第一句代码,esp=0013F62C,也就是说执行call xx系统进行了一个压栈操作!执行到 004A4D24时,esp=0013F62C(和执行到第一句代码时相等),执行了retn后,esp=0013F630,也就是说retn进行了一个出栈的动作! 

另外,函数执行完毕的前后,不管是stdcall还是fastcall,都不保证寄存器不被修改!

总结:

1、执行到函数内的第一个语句时的esp值和到最后一个语句(也就是retn)的esp值是一样的:

004A4CD0  /$  55            push    ebp  ;esp=0013F628
004A4CD1  |.  8BEC          mov     ebp, esp
004A4CD3  |.  5D            pop     ebp
004A4CD4  /.  C2 0400       retn    4 ;esp=0013F628 

2、retn 4表示pop 2次。

3、执行到call xx时的esp值与执行完xx时的esp值不一定相等,对stdcall的尤其是这样。 

粗浅分析,不当之处还请指出。

原创粉丝点击