汇编2 ----C语言函数2

上文讲到call之后,程序发生跳转。之后因为博主设错了一个断点,结果折腾了整整一周,真是欲哭无泪。

这才是正确的断点设置啊TAT。这是call之后的语句。

01281427 83 C4 08 add esp,8

执行call之后ESP的值减少4。在memory窗体中查看ESP的值。

由小端机存储可只栈顶正是函数的返回地址。

012813C0 55 push ebp

012813C1 8B EC mov ebp,esp

函数体开头两条指令是将EBP压栈,将ESP赋给EBP。

Intel几个通用寄存器的作用概括:

EAX — Accumulator for operands and results data

• EBX — Pointer to data in the DS segment

• ECX — Counter for string and loop operations

• EDX — I/O pointer

• ESI — Pointer to data in the segment pointed to by the DS register; source pointer for string operations

• EDI — Pointer to data (or destination) in the segment pointed to by the ES register; destination pointer for

string operations

• ESP — Stack pointer (in the SS segment)

• EBP — Pointer to data on the stack (in the SS segment)

因为ESP的值一直在变化,而函数参数的值和返回值又是根据栈地址的偏移量来计算的,所以需要EBP暂存ESP的值来寻址。

这两条操作后,栈的结构如下图所示:

之后我们来看函数如何取得形参的值。前文已经说过,在函数执行前参数的值已经压栈。观察接下来的指令:

mov eax,dword ptr [ebp+8]

add eax,dword ptr [ebp+0Ch]

在这两条指令之前并无对EBP的操作,所以参数的地址分别为EBP+8和EBP+c

而上述两条指令正是将两个地址处的值相加并传给EAX(正如EAX的作用)

那么函数如何返回值sum?观察下一条指令-

mov dword ptr [ebp-8],eax

EAX的值又传递给了EBP-8的地址。栈结构如图所示。

查看EBP-8的值,恰为1和2的和3

为什么要存在EBP-8而非EBP-4,原书上说是为了防止溢出攻击,我一个记笔记的当然不不明觉厉啦。先在此mark,以后学到相关内容再补充。

函数执行完毕后,当然需要返回喽。上文已经详细介绍了RET指令的过程。观察函数体部分对栈的操作。

push ebx

push esi

push edi

之后都有相对应的pop,所以最后ESP的指向恰和上图的ESP相同。之后pop EBP后,ESP恰好指在返回地址。RET指令返回,函数执行完毕。

执行完后的扫尾工作:

注意到call指令下面的那条指令:

add esp,8

RET作用之一是Pops the top-of-stack value (the return instruction pointer) into the EIP register.

所以RET之后,ESP+4处的1ESP+8处的2仍然存在,而函数已经调用完毕。将ESP+8即标记12已经无用,实现栈回收。

接下来下面的操作如何获得返回值,以及RET特殊用法,release优化,将在下节讨论。

 

 

 

 

posted @ 2015-04-15 22:44  无の心  阅读(196)  评论(0编辑  收藏  举报