在c语言中,分为主函数跟子函数,主函数的创建是怎么样形成的,为什么局部变量的初始值为随机,函数的传参是什么样的形式,压栈跟出栈又应该怎么去理解(刚开始学习的小白理解,不对的地方请纠正下,感谢)
什么是栈区:
函数的创建,局部变量的初始已经为什么是随机值,这些都会用到栈区,如果没有栈区,就没有计算机语言
在计算机语言的规定中,栈区作为一种容器,遵循先压栈、放入(push)然后出栈、弹出(pop)的过程,先压栈的数据会被放到最下面的地址edp的地址,然后慢慢叠高
每个函数的创建都会在栈区上申请空间,而申请的空间需要去维护,维护申请的空间就需要用到寄存器esp跟edp,在栈区申请的空间使用是从高地址到低地址的,所以edp又叫做栈低地址,esp叫做栈顶地址(栈的使用是从高地址到低地址使用的)
寄存器:集成CPU上面的,并不是在主函数中或者内存上的
main也是被别的函数所调用,在调用main之前,需要开辟函数所需要的地址,开辟子函数也是需要进行维护自己的栈区,栈区的维护就是靠esp跟edp连个寄存器来进行维护,其中edp存放的是高位地址,esp存放的是低位地址。
在函数的时候,编译器会给出一定的地址,以及对该地址的初始化根据vs2013的编译器,创立的空间初始值为cch,如果创立局部变量的时候没有给初始值,那么该初始值就是为0xcc
在创建子函数的时时候,还有一个call的调用指令,调用该指令以后会压栈一个地址,并且会对main函数的地址进行压栈,方便执行完子函数以后,返回到主函数之中
形参跟实参的区别在哪里呢,根据vs2013的编译器中,我们可以看到,创建子函数要对数据进行压栈,每进行一次压栈,(esp)栈顶就会向低地址移动四个字节,在压栈的时候,会把传参的数据进行拷贝一份放在栈区中,注意:拷贝的数据只是数字相同,地址是不同的,所以就是为什么即使改变了形参实参也不会进行改变。
在子函数中如果要进行参数加减,则通过mov数据转移指令对数值进行更改,更改完成以后要是该函数有返回值的话的返回方式是将要返回的值放入到寄存器之中(ret);因为子函数的创建在执行完成以后会进行销毁,如果返回的是子函数的值的话,就会产生一些未知的错误,所以编译器为了实现接收返回值,就将值放入ret的寄存器中
那么执行完子函数以后,应该怎么返回主函数之中呢?
前面我们说到了压栈跟出栈,通俗来说,压栈就是地址的创建,出栈就是地址的销毁,编译器执行完子函数以后,会将栈区数据进行弹出,从低到高,每弹出一个数据,esp和edp的值都会进行相应的变化。
esp会根据栈区创建的mian地址找到存放esp栈顶地址找到main的栈底地址,并将edp的地址更改为创建main函数时的edp地址,然后再将ret寄存器中的值赋值给函数的接收值,这样函数的返回就完成了;