-------------------------------------------------------------------------------------------
[ENHANCED] VFP 9.0 FIX - THE VARIABLE BEHAVIOR FOR THE VARIABLE NAME WITHOUT MDOT
January 2026
-------------------------------------------------------------------------------------------
CCB
1. BUG:
In vfp9 (and vfp6, vfp7, vfp8), when we run the code:
x2=x1
it will run slower than the code:
x2=m.x1
The bug was reported by Mike Yearwood.
2. CAUSE:
In vfp9 (and vfp6, vfp7, vfp8), when we run the code:
x2=x1
vfp will check the field x1 first, if there is the field x1 in the current work area, it will store the field x1 to the variable x2,
if there is no the field x1 in the current work area, it will store the variable x1 to the variable x2.
So it will run slower.
In Visual FoxPro Advanced, if we set SYS(9062,0), when we run the code:
x2=x1
vfp will not check the field x1, it will check the variable x1 only, it will store the variable x1 to the variable x2.
So it will run faster.
But for some code, for example,
REPLACE fld2 WITH fld1
it will cause an error, because there is no the variable fld1.
3. RESOLUTION:
We can write some code to fix the BUG.
Fun421386 :: ; proc near
push ebp ;0x00421386 : 55
mov ebp , esp ;0x00421387 : 8bec
sub esp , 064h ;0x00421389 : 83ec64
mov ecx , dword ptr [ Data9370f0 ] ;0x0042138c : 8b0df0709300
mov eax , dword ptr [ Data9393ac ] ;0x00421392 : a1ac939300
add ecx , 02Ch ;0x00421397 : 83c12c
push ebx ;0x0042139a : 53
mov ebx , ecx ;0x0042139b : 8bd9
mov dword ptr [ Data9370f0 ] , ecx ;0x0042139d : 890df0709300
movzx ecx ,word ptr [eax] ;0x004213a3 : 0fb708
add eax , 02h ;0x004213a6 : 83c002
mov dword ptr [ Data9393ac ] , eax ;0x004213a9 : a3ac939300
mov al , byte ptr [ Data936f10 ] ;0x004213ae : a0106f9300
test al , al ;0x004213b3 : 84c0
push esi ;0x004213b5 : 56
push edi ;0x004213b6 : 57
mov dword ptr [ ebp - 4 ] , ebx ;0x004213b7 : 895dfc
mov dword ptr [ ebp - 8 ] , ecx ;0x004213ba : 894df8
js Label58f640 ;0x004213bd : 0f887de21600
mov eax , dword ptr [ Data936dec ] ;0x004213c3 : a1ec6d9300
test eax , eax ;0x004213c8 : 85c0
mov edx , dword ptr [ Data9370f8 ] ;0x004213ca : 8b15f8709300
jne Label58f66c ;0x004213d0 : 0f8596e21600
Label4213d6 ::
mov edi , dword ptr [edx] ;0x004213d6 : 8b3a
mov eax , dword ptr [ edi + 0158h ] ;0x004213d8 : 8b8758010000
test eax , eax ;0x004213de : 85c0
jne Label58f6d6 ;0x004213e0 : 0f85f0e21600
Label4213e6 ::
mov edx , dword ptr [ Data9370f8 ] ;0x004213e6 : 8b15f8709300
mov eax , dword ptr [edx] ;0x004213ec : 8b02
mov dword ptr [ ebp - 12 ] , eax ;0x004213ee : 8945f4
mov eax , dword ptr [ eax + 32 ] ;0x004213f1 : 8b4020
xor edi , edi ;0x004213f4 : 33ff
test eax , eax ;0x004213f6 : 85c0
je Label421432 ;0x004213f8 : 7438
test byte ptr [ eax + 16 ] , 020h ;0x004213fa : f6401020
je Label421432 ;0x004213fe : 7432
;
; --------------------------------------------------------------------------------
; VFP 9.0 FIX - THE VARIABLE BEHAVIOR FOR THE VARIABLE NAME WITHOUT MDOT
; June 2021
; --------------------------------------------------------------------------------
; CCB
;
; The variable behavior for the variable name without mdot.
;
; 2021/6/26, by ccb
;
mov edx , dword ptr [ Data9370f8 ]
mov edx , dword ptr [edx]
cmp dword ptr [edx] , 00h
je Label421400
cmp dword ptr vfpa_sys9062_data,00h
je Label421432
cmp dword ptr vfpa_sys9062_data,02h
je Label4213ff
jmp Label421400
Label4213ff ::
mov esi , dword ptr [ ebp - 8 ]
mov edx , dword ptr [ Data9388e4 ]
lea ecx , dword ptr [ esi + 4 * esi ]
movzx ecx ,word ptr [ edx + 4 * ecx + 14 ]
pushd 00h
dec ecx
call Fun53c57a
cmp eax , 0FFFFFFFFh
jne Label421432
mov edx , dword ptr [ Data9370f8 ]
mov eax , dword ptr [edx]
mov eax , dword ptr [ eax + 32 ]
jmp Label421400
Label421400 ::
mov eax , dword ptr [eax] ;0x00421400 : 8b00
mov ecx , dword ptr [ eax + 52 ] ;0x00421402 : 8b4834
xor esi , esi ;0x00421405 : 33f6
test ecx , ecx ;0x00421407 : 85c9
jle Label421432 ;0x00421409 : 7e27
xor ecx , ecx ;0x0042140b : 33c9
lea esp , dword ptr [ esp ] ;0x0042140d : 8d2424
Label421410 ::
mov edx , dword ptr [ eax + 76 ] ;0x00421410 : 8b504c
mov edx , dword ptr [edx] ;0x00421413 : 8b12
mov bx , word ptr [ ebp - 8 ] ;0x00421415 : 668b5df8
cmp word ptr [ ecx + edx ] , bx ;0x00421419 : 66391c11
je Label42142c ;0x0042141d : 740d
mov edx , dword ptr [ eax + 52 ] ;0x0042141f : 8b5034
inc esi ;0x00421422 : 46
add ecx , 034h ;0x00421423 : 83c134
cmp esi , edx ;0x00421426 : 3bf2
jnl Label42142f ;0x00421428 : 7d05
jmp Label421410 ;0x0042142a : ebe4
Label42142c ::
lea edi , dword ptr [ esi + 1 ] ;0x0042142c : 8d7e01
Label42142f ::
mov ebx , dword ptr [ ebp - 4 ] ;0x0042142f : 8b5dfc
Label421432 ::
test edi , edi ;0x00421432 : 85ff
je Label53c8bc ;0x00421434 : 0f8482b41100
lea eax , dword ptr [ edi - 1 ] ;0x0042143a : 8d47ff
push eax ;0x0042143d : 50
mov eax , dword ptr [ ebp - 12 ] ;0x0042143e : 8b45f4
mov ecx , dword ptr [ eax + 32 ] ;0x00421441 : 8b4820
push ecx ;0x00421444 : 51
push ebx ;0x00421445 : 53
call Fun421694 ;0x00421446 : e849020000
test eax , eax ;0x0042144b : 85c0
je Label53c8bc ;0x0042144d : 0f8469b41100
Label421453 ::
pop edi ;0x00421453 : 5f
pop esi ;0x00421454 : 5e
pop ebx ;0x00421455 : 5b
mov esp , ebp ;0x00421456 : 8be5
pop ebp ;0x00421458 : 5d
ret ;0x00421459 : c3
4. APPLIES TO:
VFP 6.0.8167.0
VFP 6.0.8961.0 (SP5)
VFP 7.0.0.9262
VFP 7.0.0.9465 (SP1)
VFP 8.0.0.2521
VFP 8.0.0.3117 (SP1)
VFP 9.0.0.2412
VFP 9.0.0.3504 (SP1)
VFP 9.0.0.4611 (SP2)
VFP 9.0.0.5015 (SP2)
VFP 9.0.0.5411 (SP2)
VFP 9.0.0.5721 (SP2)
VFP 9.0.0.5815 (SP2)
VFP 9.0.0.6303 (SP2)
VFP 9.0.0.6602 (SP2)
VFP 9.0.0.7423 (SP2)
The bug has been fixed in VFP Advanced.
IMPORTANT NOTE:
Recommend to only use SYS(9062,0) for some code, for example,
PRIVATE m.q_oldsys9062
m.q_oldsys9062=VAL(SYS(9062))
=SYS(9062,0) && For the variable name without mdot, vfp will not check the field name, it will check the variable name only.
* the code block start...
* ...
* the code block end.
=SYS(9062,m.q_oldsys9062)
It is similar to the following code:
PRIVATE m.q_oldsele
m.q_oldsele=SELE()
SELE 0
* the code block start...
* ...
* the code block end.
SELE (m.q_oldsele)
There is only a little difference for some statements, for example,
1, x2=x1 and m.x2=x1
the vfp source code:
x2=x1
the compiled p-code:
0D 00 54 F7 00 00 10 FC F7 01 00 FD FE
--------------------------------------
the length of the compiled p-code is 0x0D (13) bytes.
the vfp source code:
m.x2=x1
the compiled p-code:
0F 00 54 F5 0D F7 00 00 10 FC F7 01 00 FD FE
--------------------------------------------
the length of the compiled p-code is 0x0F (15) bytes.
F5 0D : it's M., and then it's the same as x2=x1.
2, PUBLIC x2 and PUBLIC m.x2
the vfp source code:
PUBLIC x2
the compiled p-code:
07 00 37 F7 00 00 FE
--------------------
the length of the compiled p-code is 0x07 (7) bytes.
the vfp source code:
PUBLIC m.x2
the compiled p-code:
09 00 37 F5 0D F7 00 00 FE
--------------------------
the length of the compiled p-code is 0x09 (9) bytes.
F5 0D : it's M., and then it's the same as PUBLIC x2.
3, x2=m.x1 and STORE m.x1 TO x2
the vfp source code:
x2=m.x1
get nti (an integer) of the var x2, save to tmp2 (an integer),
calculate the expression m.x1, save the result to a Value structure val1,
set the var x2 (its nti is tmp2) from val1.
the vfp source code:
STORE m.x1 TO x2
calculate the expression m.x1, save the result to a Value structure val1,
get nti (an integer) of the var x2,
set the var x2 (its nti is eax) from val1.
5. REFERENCE WEBSITES:
1, baiyujia.com:
http://www.baiyujia.com
http://www.baiyujia.com/vfpdocuments/f_vfp9fix180.asp
2, foxite.com:
https://www.foxite.com/archives/memory-variable-0000292846.htm
https://www.foxite.com/archives/mdot-0000322640.htm
https://www.foxite.com/archives/it-is-not-wise-not-to-use-mdot-0000219998.htm
https://www.foxite.com/archives/magical-m-0000180204.htm
https://www.foxite.com/archives/m-prefix-of-local-variables-0000079314.htm
https://www.foxite.com/archives/a-confession-0000382571.htm
https://www.foxite.com/archives/another-thread-on-mdot-0000237222.htm
https://www.foxite.com/archives/best-coding-practices-for-newbies-0000160033.htm
https://www.foxite.com/archives/best-practice-to-declare-variables-0000369623.htm
https://www.foxite.com/archives/debugruntime-differences-and-mdot-0000431500.htm
https://www.foxite.com/archives/for-statement-variable-0000447907.htm
https://www.foxite.com/archives/foxypreviewer-v279-and-mdots-0000323617.htm
3, microsoft.com:
https://docs.microsoft.com/en-us/archive/blogs/calvin_hsia/foxpro-performance-tip-field-name-lookup-for-tables
https://social.msdn.microsoft.com/Forums/en-US/cc859679-4c22-4410-addd-7d013d91ca67/question-on-mem
4, blogspot.com:
https://sandstorm36.blogspot.com/2011/09/learning-mdot-usage-repost.html
6. OTHER:
For reference only, there is no guarantees.
Any questions or suggestions, please send me an email at ccb2000@163.com.
|