VB6 Pcode - For Loops


Author: David Zimmer
Date: 03.26.20 - 11:08am



First the video version:





I would eventually like to document each opcode. Below is a sample of the For loop family of opcodes.

For Loops

Each different data type has its own opcode for looping. Additionally there are special opcodes
foreach and when the for step increment is something other than 1. Several 
flavors of ExitFor opcodes also exist.

Byte stream length is typically 5, but ForEach variants require 7 bytes.
For loop setup also requires several args on the stack that are consumed when the opcode hits.

There are three main types of for loop. Normal, For Each, and For Step 
Here is an example of a For step loop being initilized

Dim b As Byte
For b = &H22 To &H26 Step 2
	
401630 Module1.Sub Main:
...
401686    F4 22                 LitI2_Byte 0x22   'start value pushed onto stack
401688    FC0D                  CUI1I2            'convert 2 byte integer to unsigned byte (check value bounds)
40168A    04 66FF               FLdRfVar var_9A   'counter variable address pushed onto stack
40168D    F4 26                 LitI2_Byte 0x26   'loop end value pushed onto stack
40168F    FC0D                  CUI1I2
401691    F4 02                 LitI2_Byte 2      'step increment pushed onto stack 
401693    FC0D                  CUI1I2
401695    FE6A 1CFF8300         ForStepUI1 var_E4 loc_4016B3    'var_E4 = loop control structure, loc_4016B3 = address at end of loop
40169B    FCE0 66FF             	FLdUI1 var_9A               'current loop counter value
...
4016AA    04 66FF               	FLdRfVar var_9A             'push counter var address onto stack
4016AD    FE80 1CFF6B00         NextStepUI1 var_E4 loc_40169B   'loc_40169B  = instruction to jump to to restart next loop iter

When ForStepUI1 opcode runs, it will consume the 4 args passed to it on the stack. 
In our example var_e4 given in the byte stream holds the loop control structure

struct ForStepUI1LoopControl{
    step_increment as byte 
	endValue as byte 
}

This struct element sizes is based on which type of For loop it is, ie I2 integer, I4 long etc.

struct ForStepI2LoopControl{
    step_increment as integer 
	endValue as integer 
}


From the byte stream we see the value 8300 (little endian 0x83) is being resolved as loc_4016B3 function start 401630 + 0x83 = 4016B3 The NextStepUI1 takes 1 stack argument, and two byte stream arguments. The stack arg is the address of the counter var which is consumed, and the two byte stream args are the forLoopControl struct address and the loop start address

'-------------- loops (51 opcodes) ------------------- 'MakeOpcode(table_index, opcodeNumber, inst_len, handler_flag , Mnem, Optional shouldLog) MakeOpcode 4, &H76, 7, 1, "ForEachAryVar %a %2 %L" 'for each over a array MakeOpcode 4, &H88, 7, 1, "ForEachCollObj %a %2 %L" 'for each over a collection or variant MakeOpcode 4, &H8B, 7, 1, "NextEachCollObj %a %2 %L" MakeOpcode 4, &H77, 7, 1, "NextEachAryVar %a %2 %L" MakeOpcode 4, &H72, 5, 1, "ForEachCollVar %a %L" MakeOpcode 4, &H74, 5, 1, "ForEachCollAd %a %L" MakeOpcode 4, &H89, 5, 1, "ForEachVar %a %L" MakeOpcode 4, &H8A, 5, 1, "ForEachVarFree %a %L" MakeOpcode 4, &H75, 5, 1, "NextEachCollAd %a %L" MakeOpcode 4, &H73, 5, 1, "NextEachCollVar %a %L" MakeOpcode 4, &H62, 5, 1, "ForUI1 %a %L" 'with byte counter var MakeOpcode 4, &H63, 5, 1, "ForI2 %a %L" 'with integer counter var MakeOpcode 4, &H64, 5, 1, "ForI4 %a %L" MakeOpcode 4, &H65, 5, 1, "ForR4 %a %L" MakeOpcode 4, &H66, 5, 1, "ForR8 %a %L" MakeOpcode 4, &H67, 5, 1, "ForCy %a %L" MakeOpcode 4, &H68, 5, 1, "ForVar %a %L" 'variant type counter MakeOpcode 4, &H6A, 5, 1, "ForStepUI1 %a %L" 'byte counter var step incremented defined by 3rd arg MakeOpcode 4, &H6B, 5, 1, "ForStepI2 %a %L" MakeOpcode 4, &H6C, 5, 1, "ForStepI4 %a %L" MakeOpcode 4, &H6D, 5, 1, "ForStepR4 %a %L" MakeOpcode 4, &H6E, 5, 1, "ForStepR8 %a %L" MakeOpcode 4, &H6F, 5, 1, "ForStepCy %a %L" MakeOpcode 4, &H70, 5, 1, "ForStepVar %a %L" MakeOpcode 4, &H78, 5, 1, "NextUI1 %a %L" MakeOpcode 4, &H79, 5, 1, "NextI2 %a %L" MakeOpcode 4, &H7A, 5, 1, "NextI4 %a %L" MakeOpcode 4, &H7B, 5, 1, "NextStepR4 %a %L" MakeOpcode 4, &H7C, 5, 1, "NextR8 %a %L" MakeOpcode 4, &H7D, 5, 1, "NextStepCy %a %L" MakeOpcode 4, &H7E, 5, 1, "NextStepVar %a %L" MakeOpcode 4, &H80, 5, 1, "NextStepUI1 %a %L" MakeOpcode 4, &H81, 5, 1, "NextStepI2 %a %L" MakeOpcode 4, &H82, 5, 1, "NextStepI4 %a %L" MakeOpcode 4, &H83, 5, 1, "NextStepR4 %a %L" MakeOpcode 4, &H84, 5, 1, "NextR8 %a %L" MakeOpcode 4, &H85, 5, 1, "NextStepCy %a %L" MakeOpcode 4, &H86, 5, 1, "NextStepVar %a %L" MakeOpcode 4, &H8C, 5, 1, "NextEachVar %a %L" 'was 9 dz ex: FE8C 18FF 3600 = 18ff - control var to reload, 0036: jmp procstart + 0x36 MakeOpcode 0, &H64, 5, 1, "NextI2 %a %L" 'End 2-Byte-Integer based FOR/NEXT loop. MakeOpcode 0, &H65, 5, 1, "NextStepI2 %a %L" 'End 2-Byte-Integer based FOR/NEXT loop. MakeOpcode 0, &H66, 5, 1, "NextI4 %a %L" MakeOpcode 0, &H67, 5, 1, "NextStepI4 %a %L" MakeOpcode 0, &H68, 5, 1, "NextStepR4 %a %L" 'End 4-Byte-data based FOR/NEXT loop. MakeOpcode 0, &H69, 5, 1, "NextStepR8 %a %L" 'End 8-Byte-data based FOR/NEXT loop. MakeOpcode 0, &H6A, 5, 1, "NextStepCy %a %L" MakeOpcode 3, &HCB, 5, 1, "ExitForCollObj %a %L" MakeOpcode 3, &HCC, 5, 1, "ExitForCollObj %a %L", 1 MakeOpcode 3, &HCD, 5, 1, "ExitForCollObj %a %L", 1 MakeOpcode 3, &HCE, 5, 1, "ExitForAryVar %a %L" MakeOpcode 3, &HCF, 5, 1, "ExitForVar %a %L" Example Code:
Sub Main1() 
 
    Dim x, y() As String, b As Byte, i As Integer 
     
    y = Split("1,2,3,4,5", ",") 
    For Each x In y 
        i = x 
        For b = 1 To 4 Step 2 
            If b = 4 Then Exit For 
        Next 
    Next 
 
End Sub 
 
401630 Module1.Sub Main:
401630    F5 00000000           LitI4 0x0
401635    F5 FFFFFFFF           LitI4 0xFFFFFFFF
40163A    3A 54FF0000           LitVarStr var_AC str_401270=',' 
40163F    4E 44FF               FStVarCopyObj var_BC
401642    04 44FF               FLdRfVar var_BC
401645    1B 0100               LitStr str_401258='1,2,3,4,5' 
401648    04 34FF               FLdRfVar var_CC
40164B    0A 02001400           ImpAdCallFPR4 rtcSplit
401650    04 34FF               FLdRfVar var_CC
401653    FF36 0820             StAryVar  0x2008 (Bstr | ARRAY)
401657    59 30FF               PopTmpLdAdStr var_D0
40165A    04 68FF               FLdRfVar var_98
40165D    FF02                  StAryCopy
40165F    36  [8 bytes]         FFreeVar var_BC var_CC 
401666    6C 68FF               ILdRf [var_98]
401669    04 6CFF               FLdRfVar var_94
40166C    FE76 28FF08008300     ForEachAryVar var_D8 0x8 loc_4016B3
401674    04 6CFF               	FLdRfVar var_94
401677    55                    	CI2Var
401678    70 64FF               	FStI2 [var_9C]
40167B    F4 01                 	LitI2_Byte 1
40167D    FC0D                  	CUI1I2
40167F    04 66FF               	FLdRfVar var_9A
401682    F4 04                 	LitI2_Byte 4
401684    FC0D                  	CUI1I2
401686    F4 02                 	LitI2_Byte 2
401688    FC0D                  	CUI1I2
40168A    FE6A 24FF7800         	ForStepUI1 var_DC loc_4016A8
401690    FCE0 66FF             		FLdUI1 var_9A
401694    FC14                  		CI2UI1
401696    F4 04                 		LitI2_Byte 4
401698    C6                    		EqI2
401699    1C 6F00               		BranchF loc_40169F
40169C    1E 7800               		Branch loc_4016A8
40169F                    loc_40169F:	; 401699
40169F    04 66FF               		FLdRfVar var_9A
4016A2    FE80 24FF6000         	NextStepUI1 var_DC loc_401690
4016A8                    loc_4016A8:	; 40169C
4016A8    04 6CFF               	FLdRfVar var_94
4016AB    FE77 28FF08004400     NextEachAryVar var_D8 0x8 loc_401674
4016B3    14                    ExitProcI4 





Comments: (0)

 
Leave Comment:
Name:
Email: (not shown)
Message: (Required)
Math Question: 99 + 16 = ? followed by the letter: S 



Twitter
RSS
About Me
More Blogs
Main Site
Posts: (All)
2020 (6)
     Using VB6 Obj files from C
     Vb6 PCode Internals
     Vb6 Runtime ForLoop Disasm
     VB6 Pcode - For Loops
     Yara Corrupt Imports
     Yara Undefined values
2019 ( 12 )
2017 ( 5 )
2016 ( 4 )
2015 ( 6 )
2014 ( 5 )
2013 ( 9 )
2012 ( 13 )
2011 ( 19 )
2010 ( 11 )
2009 ( 1 )