函数调用原理

1.程序的执行实际是cpu执行指令。

 
2.指令的执行在程序看来可以分为:内存和内存之间的互换,i/o操作(当然还有其他硬件调度暂时我们忽略)。
 
3.一个进程我们一般会分这么几个内存段供他使用:代码段,数据段,堆栈段。编译的时候现将c文件编译为汇编然后根据汇编语言将程序载入内存,之后的操作就是操作内存了。
 
4.真如3所言那么代码执行之前,变量的内存就应该确定了,否则怎么装载入内存呢?是的,除去函数内部的局部变量,其他的变量地址是确定的,那么为什么函数的变量地址没法确定呢?实际我们不能说是没有确定,而是没有确定绝对地址,我们考虑一种情况,就是递归,函数自己调用自己,如果采用绝对的地址的话,没法处理这种情况。那么怎么解决呢?
 
5.解决这个问题前先明确
  
 寄存器:ip指令指针寄存器,ss栈基址寄存器,sp栈顶指针寄存器,bp(可以认为没啥用因为sp是始终指向栈顶的,就再弄一个用来别的用处,实际他的用处好大的)。
  
  栈:计算机提供的一个数据装载结构 pop xxx 将栈顶的数据存入xxx;push向栈内压入数据;sp始终指向顶。
 
  栈顶:进出数据的一端为栈顶。
 
 解决这个问题的关键在于让每一次函数调用的时候函数内的变量地址都不一样,但编译的时候相对地址又是一样的,怎么办?那只有一个方法唠,就是每次都修改相对地址的参考地址,也就是sp寄存器的值(多说一句函数调用前会先把ip修改,指令地址切换到函数指令的地方)。当一个函数被call的时候先把参数压入栈,然后函数内部变量入栈,函数结束的时候再把这些变量都弹出,涉及到函数里面调用函数的时候,我们会做额外操作,修改sp的值,记录原来sp的值,记录下一条指令的地址,修改了sp值之后,之后所有的操作地址都是相对最新的这个sp的,当函数执行完毕后,把保存的上一个函数的sp值再重新给sp寄存器,把保存的下一条指令的地址给ip 寄存器,重复做即可,罗嗦一句函数的结果也是保存在寄存器里的。
 
 所以,栈只会保存数据而不保存指令,栈不是为函数设计的,函数的实现只是巧妙利用了栈而已。
posted @ 2016-03-15 17:27  神不知鬼不晓  阅读(778)  评论(0编辑  收藏  举报