【C语言】函数栈帧的创建和销毁
函数栈帧的创建和销毁
一、寄存器的种类和功能
- eax :累加寄存器,运算方面常用;
- ebx :基地址寄存器,在内存寻址时存放基地址;
- ecx :计数寄存器,用于循环操作,比如重复的字符存储操作,或者数字统计;
- edx :作为EAX的溢出寄存器,总是被用来放整数除法产生的余数;
- esp:栈顶指针 push 和 pop 指令会自动调用 esp 的值;
- ebp:栈底指针 ,可以存取某时刻的
esp
,这个时刻就是进入一个函数内后,CPU会将esp
的值赋给ebp
,此时就可以通过ebp
对栈进行操作,比如获取函数参数,局部变量等;
二、常见汇编指令
-
push 指令:压栈,从栈顶增加一个元素,它首先减少
esp
的值,再将源操作数复制到栈地址,在32位平台上,esp
每次减少4字节;首先
esp
的值减少4字节,再将ebp
的值压入栈中。 -
pop 指令:它首先把
esp
指向的栈元素内容复制到一个操作数中,再增加esp
的值。在32位平台上,esp
每次增加4字节;首先将
esp
所指地址处的值赋给edi
,再将esp
的值增加4字节。 -
mov指令:用于将一个数据从源地址传送到目标地址,源操作地址的内容不变;
将
esp
值赋给ebp
,这里并不是将esp
所指向的内存空间的值赋给ebp
。 -
sub 指令:减操作指令,从寄存器减去数值,然后将结果保存到寄存器中;
-
lea 指令:是“load effective address”的缩写,简单的说,lea指令可以用来将一个内存地址直接赋给目的操作数;
将ebp-0E4h的值直接赋给edi,而不是把ebp-0E4h内存地址里的数据赋给eax。
-
rep 指令:重复前缀指令,英文缩写 repeat。能够引发其后字符串指令被重复。
1>
rep
指令重复其上面的指令,ecx
的值是重复的次数,每执行一次,ecx
减 1,直到ecx
减至0。
2>stos
指令将eax
中的值拷贝到es:[edi]
指向的地址。
3>dword
双字 就是四个字节。
4> ptr pointer缩写 即指针
5> [ ] 里的数据是一个地址值,这地址指向一个双字型数据,一次拷贝双字(4个字节)的数据到目的地址。
6>es:[edi]
指向目的串
解释:合起来的意思就是,将栈上从ebp-0E4h
开始的位置,向高地址方向的内存赋值 0CCCCCCCCh,重复 39h 次,每次赋值双字(四字节的空间)。
-
call 指令:将程序下一条指令的位置的IP压入堆栈中,并转移到调用的子程序。
-
ret 指令:用于终止当前函数的执行,将运行权交还给上层函数。也就是,当前函数的帧将被回收;
执行这条命令之后,就自动返回刚才call指令的下一行。
三、函数栈帧的相关问题
-
1>局部变量是如何创建的?
原因:首先为函数分配好栈帧空间,初始化好一部分空间之后,再分配一部分空间。
-
2> 为什么局部变量不初始化内容是随机的?
原因:因为是我们手动放进去的(cc cc cc cc),一旦你初始化,就会把随机值覆盖了。
-
3> 函数是怎么传参的?传参的顺序是怎样的?
原因:当要调用函数的时候,还没有调用的时候,就已经push把参数从右向左压栈进去了,当进入真正进入形参函数的时候,其实在函数栈帧里面。通过指针的偏移量找回了参数的值。
-
4> 函数的形参和实参的关系?
形参是实参的一份临时拷贝
-
5> 函数调用结束后怎么返回的?
ret 已经存下了地址,pop 的过程中 esp 也回到了原来的位置。返回值通过寄存器 eax 带回来了。
总结:2023年9月8日,底层的东西很复杂,很难弄懂,需要多动手去实践,去调试,加油!!!
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。 如若内容造成侵权/违法违规/事实不符,请联系我的编程经验分享网邮箱:veading@qq.com进行投诉反馈,一经查实,立即删除!