2021-02-24

函数的栈和栈帧?

1.调用该函数之前,参数入栈,进入函数第一行代码,返回值入栈一次

2.以codec的函数约定,参数入栈是反顺序的

main:

ebp 00000000

 

esp 0018FFF0

 

1.push xxx

esp=0018ffec

 

2.在主栈中建立栈帧

push ebp

mov ebp,esp

建立栈帧就是在主函数中重新确定一块空间作为栈的内部栈(它用作函数中的函数存储临时变量)

 

栈的演化

以xxxx第5章节,stack.exe为例

 

红色标记表示当前esp值

  1. 初始栈的情况

Main:

ebp 00000000

 

 

esp 0018FFF0

  1. push 100

main:

ebp 00000000

 

esp 0018ffec       <-100

 

esp 0018FFF0

 

小结:在主程序中ebp<esp 入栈esp减小

 

3.添加参数push ecx

Main:

00000000

 

Esp 0018ffd8  倒数第二个参数push 参数1

 

Esp 0018ffdc  倒数第一个参数 push 参数2

          

Esp 0018ffe0

0018fff0

 

4.进入内部函数第一行

Main:

00000000

 

Esp 0018ffd4  <-存储函数返回地址(call函数的下一行)

 

Esp 0018ffd8  倒数第二个参数push 参数1

 

Esp 0018ffdc  倒数第一个参数 push 参数2

          

Esp 0018ffe0

0018fff0

 

5.建立栈帧(ebp为帧 esp为栈寄存器)  (栈帧一般是在进入函数内部后创建,这里演示栈帧造成的ebp esp变化情况)

Push ebp

Mov ebp,esp

Main:

00000000

 

ebp esp 0018ffd0   ç00000000  所以栈帧中第一个4字节存储上一级栈ebp的地址

 

Esp 0018ffd4  <-存储函数返回地址(call函数的下一行)           <-内部函数第一行

                                                         <-进入函数

Esp 0018ffd8  倒数第二个参数push 参数1

 

Esp 0018ffdc  倒数第一个参数 push 参数2

          

Esp 0018ffe0

 

0018fff0

 

6.sub esp,8  在栈帧中为函数分配局部变量存储空间(局部变量以mov 地址,局部变量值 方式存储,而不是push)

Main:

00000000

 

esp 0018ffc8

            <-这里是新创建的栈帧,即主函数内的新函数栈。它用于存储新函数的局部变量(mov 地址,局部变量值)

 

ebp esp 0018ffd0   00000000  所以栈帧中第一个4字节存储上一级栈ebp的地址

 

Esp 0018ffd4  <-存储函数返回地址(call函数的下一行)         <-内部函数第一行

                                                       <-进入函数

Esp 0018ffd8  倒数第二个参数push 参数1

 

Esp 0018ffdc  倒数第一个参数 push 参数2

          

Esp 0018ffe0

0018fff0

 

7.push eax 在函数内部push和在主函数中push好像是一样的,与新建的栈帧没啥关系

Main:

00000000

 

esp 0018ffc4

 

esp 0018ffc8

            <-这里是新创建的栈帧,即主函数内的新函数栈。它用于存储新函数的局部变量(mov 地址,局部变量值)

 

ebp esp 0018ffd0   00000000  所以栈帧中第一个4字节存储上一级栈ebp的地址

 

Esp 0018ffd4   <-存储函数返回地址(call函数的下一行)         <-内部函数第一行

                                                        <-进入函数

Esp 0018ffd8  倒数第二个参数push 参数1

 

Esp 0018ffdc  倒数第一个参数 push 参数2

          

Esp 0018ffe0

0018fff0

 

总结:

根据以上,当断点在函数第一行时 定位参数 返回地址

Esp   返回地址

Esp+4 第一个参数

Esp+8 第二个参数

 

如果断点在建立栈帧后(即进入函数后执行完push ebp  mov ebp,esp)

Ebp+4 返回地址

Esp+8 第一个参数

Esp+c 第二个参数

 

 

上一篇:JDK成长记16:从0分析你不知道的synchronized底层原理(下)


下一篇:C语言进阶(二)--- 整型存放练习