level 11
//事先说明,仅作进一步的思考,不作实用性使用
结合前一段时间的一些经验,加上昨天和今天遇到的问题及我对其的解决,让我生出了发一个贴讨论一下VB6的函数调用。(虽然我也不怎么懂)
2020年12月09日 10点12分
1
level 11
我们最开始接触VB6的时候
我们知道VB6有Function和Sub两类函数可以用来调用
Sub函数是无返回值的函数,无法返回(直接)结果
Function函数是有返回值函数,可以直接返回结果
2020年12月09日 10点12分
2
level 11
然后我们又接触了Private、Public修饰词,知道了函数是分私有函数和公有函数的
Private修饰的函数逻辑上只能本模块调用(实际上实际编程时可以绕过这一限制)
Public修饰的函数则可以让所有模块调用
(Friend修饰的友元函数是再后来学习类模块才接触到的)
2020年12月09日 10点12分
3
level 11
后来我们又注意到了给函数传递参数时的ByVal和ByRef修饰词
ByVal修饰词的参数使用时不会影响原本的变量
ByRef修饰词的参数使用时则会影响原本的变量
2020年12月09日 10点12分
4
level 11
当然闲话说这么多,进入正题
此处仅讨论
●基于模块的公有函数和私有函数
●基于类模块的私有函数
●函数传递参数时无可选参数
2020年12月09日 10点12分
5
level 11
先说参数传递问题(此处仅讨论Long型,Byte型和Int型Bool型应该会对齐,其他应该是复制一份然后传入地址,具体尚未进一步探究,无准确参考性)
ByVal是直接将值压入堆栈
ByRef则会将变量的地址压入堆栈
所以使用ByVal不会影响到原变量,使用ByRef则会影响到原变量
2020年12月09日 10点12分
6
level 11
标准模块
Public Sub函数
标准的stdcall调用约定,从右往左入栈,然后会将返回地址置于栈顶,最后会将eax寄存器置为0
Public Function函数
标准的stdcall调用约定,但是函数内部会多出很多迷惑的准备工作(即便是一个空函数),暂时没有细细探究,返回值存在eax寄存器
Private Function/Sub函数
基本分别同上,不同在于参数和返回地址之间会多压入一个值进入堆栈,作用未知
//以下内容部分参考资料,部分实验,部分推理,正确性不一定准确,希望大家一起来仔细实验讨论一下
Public函数的调用通过vTable查表进行调用,和API函数调用类似(摘自网上)
Private函数的调用直接调用函数
在直接调用时,Private函数略快于Public函数,使用函数指针调用时Public函数略快于Private函数,直接调用略快于函数指针调用
2020年12月09日 10点12分
7
level 11
类成员函数
Sub
thiscall调用约定,参数从右向左入栈,入栈返回之前入栈this指针,并且将this指针保存在ecx寄存器,结束时eax置0
Function函数
thiscall调用约定,基本同上,但在参数入栈前会将返回地址入栈(先准备等号左边,再调用等号右边?),返回时将返回值存入事先入栈的指针指向的地址,并将eax置为0
//VB6的这波操作都让我怀疑我前面Function函数是不是搞错了,一会儿再去看一下
2020年12月09日 11点12分
8
回头看了一下,VB6的标准function遵循的还是stdcall调用约定,而不是将返回值直接存入地址
2020年12月09日 11点12分