0x1 基础知识
CPU:寄存器
内存:物理内存地址、虚拟内存地址
栈:可以看做一种数据结构,先进后出的数据表。有压栈(PUSH)、有弹栈(POP)、标识栈的属性有两个:栈顶(TOP)、栈底(BASE)
可以把栈看做一副扑克,PUSH,往上放一张牌(压入数据),POP,拿走一张牌(弹出数据)。
0x2 函数调用在内存中的栈中发生了什么?
编译后的代码在内存中分布是散乱的,当CPU执行到myfun()函数时,会从代码区域跳进myfun函数中执行里面的机器指令区域(我们写的函数中的代码),在那里取值并执行;当myfun()函数执行完毕,函数的末尾往往
有返回,将返回到myfun()函数外后面的一句代码继续执行。
问题?
CPU如何知道去myfun()函数中取值,执行完myfun()函数后又是如何知道返回到main函数的呢?
CPU是从那里获取这些函数调用和返回的信息呢?答案:栈。
当函数被调用时,系统栈会为这个函数开辟一个新的栈帧,然后把它压入栈中,这个栈帧中的内存空间地址被它所属函数独享的,正常情况下不会和别的函数共享的。当函数返回时,系统栈会弹出该函数所对应的栈帧。
函数调用过程
- 调用myfun()函数时,系统栈为配合myfun()函数执行,会在系统栈中为其开辟新的栈帧并压入。 下列图为 栈中的操作。
myfun() ↓ PUSH 压栈 先进后出 局部变量a ↓ 扑克牌,最先压栈的是myfun2()的返回地址 局部变量b ↓ 返回地址 myfun2() 局部变量a 局部变量b 返回地址 ↑ POP 弹栈时 先弹myfun() 后进先出 |
当myfun()函数返回时,myfun()的栈帧将被弹出系统栈。
寄存器与函数栈帧
每一个函数独占自己栈帧空间,当前正在运行的函数栈帧总是在栈顶。Win32系统提供两个特殊的寄存器来标识。
ESP:栈指针寄存器(extended stack pointer),其内存放着一个指针,该指针永远指向系统栈最上面一个栈帧的栈顶。
EBP:基址指针寄存器(extended base pointer),其内存存放着一个指针,该指针永远指向系统栈最上面一个栈帧的底部。
EIP:指令寄存器(extended instruction pointer),存放一个指针,该指针永远指向下一条等待执行的指令地址。
注意:
"栈帧底部" 和 "栈底"是两个概念,栈底是指 ”系统栈底“ ,而栈帧底部指函数栈帧的底部。而栈帧顶部和系统栈的顶部是同一个位置。ESP和EBP之间的内存空间为当前栈帧。
待修改。。。。。