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 带回来了。