使用下面的代码进行测试
Dim i As Long, a As Long
Private Sub Command1_Click()
For i = 1 To 10
a = a + 2
Next i
End Sub
使用SC找到Command1的入口点,OD进行调试,发现循环部分的反汇编是下面的样子
004019CD > 8BD1 MOV EDX,ECX
004019CF . 8BC7 MOV EAX,EDI
004019D1 . 83C2 02 ADD EDX,2
004019D4 . 70 3A JO SHORT TNEXT.00401A10
004019D6 . 83C0 01 ADD EAX,1
004019D9 . 8BCA MOV ECX,EDX
004019DB . 70 33 JO SHORT TNEXT.00401A10
004019DD . 83F8 0A CMP EAX,0A
004019E0 . 8BF8 MOV EDI,EAX
004019E2 .^7E E9 JLE SHORT TNEXT.004019CD
将上面的代码修改一下
Dim i As Variant, a As Long
Private Sub Command1_Click()
For i = 1 To 10
a = a + 2
Next i
End Sub
我们把循环计数器i的类型改成了变体,也就是没有Option Explicit强制变量声明情况下使用未声明变量时默认的类型,同样方法看反汇编代码,发现变化是比较大的
00401A78 . FF15 18104000 CALL DWORD PTR DS:[<&MSVBVM60.__vbaVarFo>; MSVBVM60.__vbaVarForInit
00401A7E > 3BC3 CMP EAX,EBX
00401A80 . 74 1C JE SHORT TNEXTWIT.00401A9E
00401A82 . 8B4E 44 MOV ECX,DWORD PTR DS:[ESI+44]
00401A85 . 8D55 9C LEA EDX,DWORD PTR SS:[EBP-64]
00401A88 . 8D45 AC LEA EAX,DWORD PTR SS:[EBP-54]
00401A8B . 83C1 02 ADD ECX,2
00401A8E . 52 PUSH EDX
00401A8F . 50 PUSH EAX
00401A90 . 70 47 JO SHORT TNEXTWIT.00401AD9
00401A92 . 57 PUSH EDI
00401A93 . 894E 44 MOV DWORD PTR DS:[ESI+44],ECX
00401A96 . FF15 78104000 CALL DWORD PTR DS:[<&MSVBVM60.__vbaVarFo>; MSVBVM60.__vbaVarForNext
00401A9C .^EB E0 JMP SHORT TNEXTWIT.00401A7E
00401A9E > 895D FC MOV DWORD PTR SS:[EBP-4],EBX
循环开始调用了MSVBVM60.__vbaVarForInit,而每次循环都要调用MSVBVM60.__vbaVarForNext,大家都知道如此频繁的调用API对于一个循环的执行效率来说是非常不利的