熟悉函数调用时的堆栈操作是学好汇编语言的必备知识,在此仅仅写出了最简单的函数调用过程 , 有错误的地方,欢迎批评指正.

注:该程序通过VS2012编译. 函数调用方式为C调用方式 : A. 用栈自右向左传參   B : 调用者平衡堆栈

因为使用xls画的堆栈图,仅仅能以贴图方式进行.

1. C语言的源代码


#include "stdafx.h"

 

 

 

 

 

int Plus(int x,int y)

 

{

 

 

 

 

int z = 2;

 

 

 

 

 

 

return x+y+z;

 

}

 

 

 

int _tmain(int argc, _TCHAR* argv[])

{

 

 

 

 

int r = Plus(3,4);

 

return 0;

 

}

 

 

 


2.调用Plus函数的汇编语言

2.1

                 函数调用堆栈图_汇编语言



2.2  压入參数

               函数调用堆栈图_堆栈_02

       两个Push指令,ESP-8.


2.3  调用函数

                函数调用堆栈图_调用函数_03

 

2.4.保存原来EBP

                            函数调用堆栈图_堆栈_04


        注: call指令两个要点  A : 将下一条指令地址 (返回地址)入栈 , ESP - 4

                                              B : 将call指令后的地址存至 EIP 寄存器


2.5 将当前栈顶作为栈底

                                 函数调用堆栈图_汇编语言_05


2.6 开辟栈空间

                 函数调用堆栈图_汇编语言_06

               4,5,6 这三条指令合称为打开栈帧. 

               注 : sub  esp , 0xC0 当中的0xC0为编译器为该函数分配的缓冲区大小。其大小可由编译器设置

               


2.7 保存现场

                           函数调用堆栈图_函数调用_07函数调用堆栈图_编译器_08


2.8  Debug版 编译器向缓冲区填充 int 3(即 0xCC)指令

.                             函数调用堆栈图_汇编语言_09函数调用堆栈图_堆栈_10

              注:后四条指令才真正为函数的核心功能

     EBP本身的地址编号存放的是 上一个函数的EBP的值

                    EBP - XX 为局部变量。  EBP + 4为返回地址 。 EBP + 8及以后为參数

2.9  恢复现场

                    函数调用堆栈图_堆栈_11函数调用堆栈图_汇编语言_12


2.10 恢复栈帧

                             函数调用堆栈图_编译器_13函数调用堆栈图_汇编语言_14


2.11调用函数结束 返回RET

                         函数调用堆栈图_调用函数_15

                                             RET

                   注: 该处採用的是C调用方式, 调用者平衡堆栈 

                         RET指令 将返回地址弹出栈  ESP+4


2.12 平衡堆栈

                                      

                     函数调用堆栈图_堆栈_16函数调用堆栈图_调用函数_17

   能够对照第一幅图的栈顶栈帧,是同样的。另外,ESP , EBP的值随机 。


            在此仅仅列出了调用一个函数的堆栈使用情况,各位看官能够自行拓展