在FB里不支持GoSub功能,在面对函数内简单又重复的操作,而所涉及变量又比较多的时候,再在外边定义一个函数就显得累赘,此时如果可以有一个函数内部的子函数,就显得方便多了。
在汇编探索里发现,可以使用汇编来实现函数的子函数功能,但gcc编译的时候,会把子函数部分当做无效代码优化了,通过测试发现,只要用汇编跳转到函数末尾,则gcc编译器就不会直接优化子函数代码了。于是设置了3个宏,来实现FB的GoSub功能。
1、GotoSub(fn)
宏定义如下,用汇编的call来调用子函数,参数是函数名称。
#Macro GotoSub(fn)
Asmcall fn
End Asm
#EndMacro
2、SubName(fn)
宏定义如下,就是定义一个函数的标签,参数是函数名称。(只能通过汇编来调用(call)或者跳转(jmp),goto是不行的)
#Macro SubName(fn)
Asm
fn:
End Asm
#EndMacro
3、RetSub
宏定义如下,就是汇编的返回(ret)。作为子函数时,必须要有返回,不然不能回到原来函数调用的地方。
#Macro RetSub
Asmret
End Asm
#EndMacro
具体实现过程如下:
#include Once "windows.bi"#Macro GotoSub(fn)
Asmcall fn
End Asm
#EndMacro#Macro SubName(fn)
Asm
fn:
End Asm
#EndMacro#Macro RetSub
Asmret
End Asm
#EndMacroSub test()Dim a As Long = 10Dim b As Long = 5Dim c As Long = 0c = a + bGotoSub(test2) '打印输出GotoSub(test1) '乘法计算GotoSub(test2) '打印输出
'--------------------------------------------------
'跳到函数末尾
' 这里不能用exit sub,exit function,return和goto来结束函数,
' 因为如果使用gcc编译的时候,使用以上方法结束函数,子函数部分会被优化。
' 只能使用汇编来跳转到末尾GotoSub(testend)
'--------------------------------------------------
'子函数1 算乘法
SubName(test1) '子函数名c = a * bRetSub '必须有返回,不然就会顺序往下执行
'--------------------------------------------------
'子函数2 单纯的打印c功能
SubName(test2)Print "c = ";cRetSub
'--------------------------------------------------
'函数末尾
SubName(testend)
End Subtest()Sleep
End
必须注意:
1、如果使用子函数,必须有在原有函数主体程序末尾加一个跳转到函数结尾的调用。建议使用函数名+end实现。如GotoSub(testend) 。同时在函数末尾(end sub或者end function前)定义一个函数名,如SubName(testend)。此函数不返回。
2、其他子函数都是使用函数名SubName + 返回RetSub的方式来实现。
3、根据需要也可以不写,比如同时执行a函数+b函数,以及可以单独调用b函数时,a函数放前面,不返回,b函数返回。