函数的调用方式分析

来源:互联网 发布:ip mac绑定列表 编辑:程序博客网 时间:2024/05/07 10:53

闲来无事,研究了一下VC中的三种函数调用方式 cdcel stdcall fastcall

现将结论公布如下:

1 cdcel调用方式,调用之前的参数压栈是由调用函数完成,函数调用结束之后,由调用函数弹出堆栈中的参数。但是cdcel的esp指针确是需要由调用函数来完成恢复的。

2 stdcall ,调用之前的参数压栈是由调用函数来做,子函数来弹出栈中的参数。相当于,调用函数push,子函数pop。由子函数恢复esp指针。

3 fastcall ,参数的压栈和参数的弹出都是由子函数来完成的,相当于 子函数 既负责push 也负责pop,子函数恢复esp指针。

总体上讲,cdcel 和fastcall比较正式一点,因为写程序都讲究谁申请谁释放,而stdcall方式却将这种成对的操作push和pop在两个模块中来做,虽然这都是编译器自动来完成的。但是cdcel的esp指针却是由调用函数来恢复。

另外:这次分析之后的心得就是:程序中的变量如果不是全局的那么变量的空间都是分配在栈之上的,这个栈的地址是由sp寄存器指示的,每次函数调用,系统都会在esp之后的一定空间(我测试的是esp-40)重新建立栈空间,子函数中的变量就会在这个新的栈上。而且调用函数和被调用函数的中变量的空间分配地址比较接近,因为每次建立新的栈大概也只有40H这么个大小的距离,但是全局变量就不一样了,我当时测试的全局变量地址是00424d8c这个位置,而栈区的变量地址是0013FF84附近,还有就是程序的code应该是根据程序的文件组织结构编译的,并且由EIP进行指示,每次调用子函数的时候,当前eip就会被压栈,子函数结束了就弹出EIP,这样就可以返回到调用子函数的地方了。

还不明白的地方是:在新的栈建立的时候,栈底部为什么要用10H个DWORD,就是64个字节来填充一下,还有就是调用子函数的时候,先是call一下,但是call的不是子函数的地址,而是跳到一个地址之后再jmp一下到子函数的地址。

0 0
原创粉丝点击