Page 1 of 2 12 LastLast
Results 1 to 40 of 45

Thread: [VB6] - Inline assembler Add-in.

  1. #1

    Thread Starter
    PowerPoster
    Join Date
    Feb 2015
    Posts
    2,671

    [VB6] - Inline assembler Add-in.

    Hello everyone!
    There are cases where you need to use the assembly code in your VB6 projects. Usually this is done using a previously-compiled code that is placed into the the memory. Then this code is run using one of millions method. Unfortunately this method has the disadvantages. For instance, you will have to change the procedures of the placement code in the memory If you change the asm-code. In addition it is quite slow process. I've written the Add-in that does these process automatically, also after compilation any processes of the placement of the code in the memory are not performed. Asm-code links to EXE. This add-in supports the asm-code either IDE or the compiled form (native only!).

    How to use?
    First you have to install the Add-in (installer available at the end of article). After installing you should run the Add-in from VB6 IDE (Add-Ins -> Add-in Manager -> Inline assembler). It adds the new item to Add-Ins menu. If current project does not use the add-In features yet it will add the new module to project. You should add the prototypes of the functions in this module in order to call them from VB6 code. You can rename this module, place the prototypes of the functions, but you can't place the code to this module. After creating of the module you can run the ASM-editor. There is the combobox with the the functions which you defined in the module. For each function you can override the code using the NASM syntax. However if you don't override code (just leaving it empty) a function won't be overridden (this function is left a typical vb6 function). Each project (if you use this Add-in) is associated the additional file with *.ia extension in the project folder. This file contains the asm-codes for each function that is overridden by user. This add-in works "transparently", i.e. if you disable add-in project will work and compile, only "stub-functions" will work without overrides. *.ia file isn't "vitally essential" for working of the project, i.e. this project will work anyway.
    Let's consider working of Add-in with the simple example. For instance, we need to mix the two integers-arrays without overflowing, i.e. if the result of the addition is greater than 32767 it should be left to 32767. Opposite, if the result of the addition is smaller than -32768 it should be left to -32768. For this very well suit MMX-extension. It has the instructions for working with the vector data with the saturation. Ok, let's go! Create new project, open Add-in. It adds the new module, rename this module to modInlineAsm. Now define the prototype of the function:
    Code:
    Public Function MMXAdd( _
                    ByRef dest As Integer, _
                    ByRef src As Integer, _
                    ByVal count As Long) As Long
    End Function
    At the first parameter we pass the first element of the array, also this array is result; at the second parameter we pass the first element of the second array; finally, at the third parameter we pass the number of the elements. Note that the size should be a multiple of 8 bytes, because we will use the vector instructions, which work with 8 bytes simultaneously. Now define the procedure that will call this function:
    Code:
    Private Sub Form_Load()
        Dim src()   As Integer
        Dim dst()   As Integer
        Dim size    As Long
        Dim index   As Long
        
        size = 1024
        
        ReDim src(size - 1)
        ReDim dst(size - 1)
        
        For index = 0 To size - 1
            ' // Fill arrays with sine
            src(index) = Sin(index / 40) * 20000
            dst(index) = Sin(index / 23) * 20000
        Next
        
        ' // Add with saturation
        MMXAdd dst(0), src(0), size
        
        '// Draw result
        AutoRedraw = True
        
        Scale (0, 32767)-(index, -32768)
        
        For index = 0 To size - 1
            If index Then
                Me.Line -(index, dst(index))
            Else
                Me.PSet (index, dst(index))
            End If
        Next
        
    End Sub
    As you can see here both arrays are filled with sines which have the different period. Further we mix these arrays using MMXAdd function. Eventually the result array is being shown to the screen. Now we should override the MMXAdd function. For this activate the Add-in. The editor window will be opened, and there we select the MMXAdd function and add the following code:
    Code:
    BITS 32
    
    ; Addition of two arrays using saturation
    ; Size of arrays should be a multiple of 8
    
    push    EBP
    mov   EBP, ESP
    push    EBX
    push    ESI
    push    EDI
    mov   ESI,DWORD [EBP+0x8]
    mov   EDI,DWORD [EBP+0x0C]
    mov   ECX,DWORD [EBP+0x10]
    shr   ECX,2
    
    test   ECX,ECX
    je   EXIT_PROC
    emms   ; Initialize MMX
    
    CYCLE:
       movq   MM0,QWORD [EDI]
       movq   MM1,QWORD [ESI]
       paddsw   MM1,MM0
       movq   QWORD [ESI],MM1
       add   ESI,0x8
       add   EDI,0x8
    loop   CYCLE
    
    emms
    
    EXIT_PROC:
    pop    EDI
    pop   ESI
    pop   EBX
    mov   esp, ebp
    pop   ebp
    
    ret   0x0c
    It's very simple if you know the instruction set. The main instruction is paddsw that adds two four-dimensional 16 bits integer vectors with sign by single operation. Now save project and run it:
    Name:  MMX_test.PNG
Views: 6819
Size:  20.7 KB
    Nice! As you can see at the screenshot, the two sines are added with the saturation. You can notice the saturation by the peaks.
    Okay, now let's try to compile the EXE file and check what is called and what is compiled:

    As you can see, the code is already inside EXE, without memory allocation and unnecessary stuff.

    How does it work?
    Actually everything is very simple. When Add-in is connected the handlers of key events are set: the compilation start event, running code event, close/save project event etc. When you run code in IDE the all asm-codes are being compiled, also the addresses of the overrides function are calculated. Further the code of the original stub-functions is replaced to asm-code. When you call the stub-function it calls the asm-code. When you stop the execution the Add-in restores the original code. When you compile to the native code (or rather before linking) it finds the OBJ-file of the overridable module and replaces the code of the stub functions to asm-code and resaves file. For this functionality i write the COFF parser. Generally it can provides the lot of different features.
    This project is very poorly tested, because i don't have enough time, therefore i think it'll contain very many bugs. Considering that the half of the project uses the undocumented features and trick, which perhaps don't work as i know. In this project even isn't syntax highlighting, because i don't have the possibility to finish the my highlighter textbox yet. Still i'm using the simple textbox. If someone have found the bugs write here.
    Thanks for attention!

    https://yadi.sk/d/_yMsCu7o3So5GY

  2. #2

  3. #3
    PowerPoster
    Join Date
    Jun 2015
    Posts
    2,224

    Re: [VB6] - Inline assembler Add-in.

    you should make another codebank post on how to make a VST Plugin.

  4. #4

  5. #5
    Frenzied Member
    Join Date
    May 2014
    Location
    Kallithea Attikis, Greece
    Posts
    1,289

    Re: [VB6] - Inline assembler Add-in.

    Where is the code??
    Trick can you use a github for the addin?

  6. #6

  7. #7
    Fanatic Member
    Join Date
    Sep 2010
    Location
    Italy
    Posts
    678

    Re: [VB6] - Inline assembler Add-in.

    very interesting
    I suppose the use of the assmbler code is due to its speed performance.

    I have often noticed that VB6 is very slow. Especially when working on Image processing or Vector operations.
    I would like to be able to implement some functions in assembler.
    However, I would like to be sure that the assembler implementation is much faster and worth using.

    Please can you make an example of simple operations between 2D or 3D vectors (using Floating point (singles / double))?
    Or at least add other examples?

    I had assembly bases, I studied it many years ago, and, having no longer used it, I forgot a lot.
    So at least you could suggest some links where I can study Assembler instructions, registers ... and NASM ?
    (For NASM I found This)

  8. #8

    Thread Starter
    PowerPoster
    Join Date
    Feb 2015
    Posts
    2,671

    Re: [VB6] - Inline assembler Add-in.

    Please can you make an example of simple operations between 2D or 3D vectors (using Floating point (singles / double))?
    Or at least add other examples?
    I've created the example of using generation of the random 4D vectors and calculation the sum of them using SSE:
    Code:
    ' //
    ' // Fast 4D-vectors operations example using inline assembler (SSE)
    ' // by The trick
    ' //
    
    Option Explicit
    
    Private Const FADF_AUTO As Long = 1
    
    Private Type SAFEARRAYBOUND
        cElements   As Long
        lLBound     As Long
    End Type
    
    Private Type SAFEARRAY
        cDims       As Integer
        fFeatures   As Integer
        cbElements  As Long
        cLocks      As Long
        pvData      As Long
        Bounds      As SAFEARRAYBOUND
    End Type
    
    Public Type tVector4D
        fX  As Single
        fY  As Single
        fZ  As Single
        fW  As Single
    End Type
    
    Private Declare Sub SafeArrayAllocDescriptor Lib "oleaut32" ( _
                        ByVal cDims As Long, _
                        ByRef ppsaOut As Long)
    Private Declare Sub MoveArray Lib "msvbvm60" _
                        Alias "__vbaAryMove" ( _
                        ByRef Destination() As Any, _
                        ByRef Source As Any)
    Private Declare Sub MoveArray2 Lib "msvbvm60" _
                        Alias "__vbaAryMove" ( _
                        ByRef Destination As Any, _
                        ByRef Source() As Any)
    Private Declare Function QueryPerformanceCounter Lib "kernel32" ( _
                             ByRef lpPerformanceCount As Currency) As Long
    Private Declare Function QueryPerformanceFrequency Lib "kernel32" ( _
                             ByRef lpFrequency As Currency) As Long
    Private Declare Function RtlCompareMemory Lib "ntdll" ( _
                             ByRef ptrSource1 As Any, _
                             ByRef ptrSource2 As Any, _
                             ByVal Length As Long) As Long
                        
                        
    Private msLog   As String   ' // Events log
    
    Sub Main()
        Dim tVB()   As tVector4D
        Dim tAsm()  As tVector4D
        
        ' // Run tests
        TestVB tVB
        TestAsm tAsm
        
        ' // Compare results
        If RtlCompareMemory(tVB(0), tAsm(0), Len(tAsm(0)) * UBound(tAsm)) = Len(tAsm(0)) * UBound(tAsm) Then
            msLog = msLog & "Match"
        Else
            msLog = msLog & "Doesn't match"
        End If
        
        ' // Display
        MsgBox msLog
        
    End Sub
    
    ' // Run inline asm test
    Private Sub TestAsm( _
                ByRef tRes() As tVector4D)
        Dim tVec1()     As tVector4D
        Dim tVec2()     As tVector4D
        Dim cAlloc1     As CAllocator
        Dim cAlloc2     As CAllocator
        Dim lRndSeed    As Long
        
        LogEvent "ASM test is running...", True
        
        Set cAlloc1 = New CAllocator
        Set cAlloc2 = New CAllocator
        
        tVec1 = CreateVectorArr4D(10000000, cAlloc1)
        tVec2 = CreateVectorArr4D(10000000, cAlloc2)
        
        lRndSeed = 327680
        
        LogEvent "Allocation"
        
        FillRandomAsm tVec1, lRndSeed
        FillRandomAsm tVec2, lRndSeed
        
        LogEvent "Fill random"
        
        VectorsAdditionAsm tVec1, tVec2
        
        LogEvent "Vectors Addition"
        
        tRes = tVec1
        
    End Sub
    
    ' // Run pure-VB test
    Private Sub TestVB( _
                ByRef tRes() As tVector4D)
        Dim tVec1()     As tVector4D
        Dim tVec2()     As tVector4D
        Dim cAlloc1     As CAllocator
        Dim cAlloc2     As CAllocator
        
        LogEvent "VB6 test is running...", True
        
        Set cAlloc1 = New CAllocator
        Set cAlloc2 = New CAllocator
        
        tVec1 = CreateVectorArr4D(10000000, cAlloc1)
        tVec2 = CreateVectorArr4D(10000000, cAlloc2)
        
        LogEvent "Allocation"
        
        FillRandomVB tVec1
        FillRandomVB tVec2
        
        LogEvent "Fill random"
        
        VectorsAdditionVB tVec1, tVec2
        
        LogEvent "Vectors Addition"
        
        tRes = tVec1
        
    End Sub
    
    ' // Log
    Public Sub LogEvent( _
               Optional ByRef sText As String, _
               Optional ByVal bNoTime As Boolean)
        Static cFreq    As Currency, _
               cOldVal  As Currency
        Dim cNewVal     As Currency
        
        If cFreq = 0@ Then
        
            QueryPerformanceFrequency cFreq
            QueryPerformanceCounter cNewVal
            cOldVal = cNewVal
            
        Else
        
            QueryPerformanceCounter cNewVal
            
        End If
        
        If Not bNoTime Then
            msLog = msLog & Format$((cNewVal - cOldVal) / cFreq, "0.00000") & "ms. "
        End If
        
        msLog = msLog & sText & vbNewLine
            
        cOldVal = cNewVal
            
    End Sub
    
    
    ' //
    ' // Alloc at 16 bytes boundary
    ' //
    Public Function CreateVectorArr4D( _
                    ByVal lCount As Long, _
                    ByVal cAlloc As CAllocator) As tVector4D()
        Dim pDesc   As Long
        Dim tDesc   As SAFEARRAY
        Dim tVec    As tVector4D
        
        SafeArrayAllocDescriptor 1, pDesc
        
        MoveMemory tDesc, ByVal pDesc, Len(tDesc)
    
        tDesc.pvData = cAlloc.Alloc(lCount * Len(tVec))
        tDesc.cbElements = Len(tVec)
        tDesc.fFeatures = FADF_AUTO
        tDesc.Bounds.cElements = lCount
        
        MoveMemory ByVal pDesc, tDesc, Len(tDesc)
        
        MoveArray CreateVectorArr4D, pDesc
        
    End Function
    Code:
    Option Explicit
    
    ' //
    ' // Fill with random values
    ' //
    Public Sub FillRandomVB( _
               ByRef tVec() As tVector4D)
        Dim lIndex  As Long
        
        For lIndex = 0 To UBound(tVec)
        
            tVec(lIndex).fX = Rnd
            tVec(lIndex).fY = Rnd
            tVec(lIndex).fZ = Rnd
            tVec(lIndex).fW = Rnd
            
        Next
        
    End Sub
               
               
    ' //
    ' // Vectors addition
    ' // tVecDst(0..n) = tVecDst(0..n) + tVecSrc(0..n)
    ' //
    Public Sub VectorsAdditionVB( _
               ByRef tVecDst() As tVector4D, _
               ByRef tVecSrc() As tVector4D)
        Dim lIndex  As Long
        Dim lCount  As Long
        
        If UBound(tVecDst) > UBound(tVecSrc) Then
            lCount = UBound(tVecSrc) + 1
        Else
            lCount = UBound(tVecDst) + 1
        End If
        
        For lIndex = 0 To lCount - 1
            
            tVecDst(lIndex).fX = tVecDst(lIndex).fX + tVecSrc(lIndex).fX
            tVecDst(lIndex).fY = tVecDst(lIndex).fY + tVecSrc(lIndex).fY
            tVecDst(lIndex).fZ = tVecDst(lIndex).fZ + tVecSrc(lIndex).fZ
            tVecDst(lIndex).fW = tVecDst(lIndex).fW + tVecSrc(lIndex).fW
            
        Next
        
    End Sub
    Code:
    Option Explicit
    
    Public Sub FillRandomAsm( _
               ByRef tVec() As tVector4D, _
               ByRef lRndSeed As Long)
    
    End Sub
    
    Public Sub VectorsAdditionAsm( _
               ByRef tVecDst() As tVector4D, _
               ByRef tVecSrc() As tVector4D)
               
    End Sub
    The CAllocator class:
    Code:
    ' //
    ' // 16-byte alignment allocator
    ' //
    
    Option Explicit
    
    Private mpMem   As Long
    
    Public Property Get Ptr() As Long
        Ptr = (mpMem + 15) And &HFFFFFFF0
    End Property
    
    Public Function Alloc( _
                    ByVal lSize As Long) As Long
        
        If mpMem Then Err.Raise 5
        
        mpMem = CoTaskMemAlloc(lSize + 16)
        
        Alloc = (mpMem + 15) And &HFFFFFFF0
        
    End Function
    
    Public Sub Free()
        
        If mpMem Then
            CoTaskMemFree mpMem
        End If
        
        mpMem = 0
        
    End Sub
    
    Private Sub Class_Terminate()
        Free
    End Sub
    Code:
    FillRandomAsm:
    BITS 32
    
    ; Validate SafeArray
    mov eax, dword [esp + 4]
    test eax, eax
    jz EXIT
    
    mov eax, dword [eax]
    test eax, eax
    jz EXIT
    
    mov cx, word [eax]
    dec cx
    jnz EXIT
    
    push edi
    
    mov ecx, dword [eax + 0x10]	; SA.Bounds.cElements
    mov edi, dword [eax + 0x0c]	; SA.pvData
    
    mov eax, __float32__(16777216.0)
    movd xmm1, eax
    
    mov eax, dword [esp + 0x0c]	; *Seed
    mov eax, dword [eax]		; Seed
    
    ; Multiply by 4
    shl ecx, 2
    
    CYCLE:
    test ecx, ecx
    jz END_CYCLE
    
    ; VB6 Rnd algo: NewVal = (0xFFC39EC3 - (OldVal * 0x2BC03)) And &HFFFFFF
    imul eax, eax, 0x2BC03
    sub eax, 0xFFC39EC3
    neg eax
    and eax, 0xFFFFFF
    cvtsi2ss xmm0, eax
    divss xmm0, xmm1
    
    ; Store
    movd [edi], xmm0
    
    add edi, 4
    dec ecx
    jmp CYCLE
    
    END_CYCLE:
    
    mov edi, dword [esp + 0x0c]
    mov dword [edi], eax
    
    pop edi
    
    EXIT:
    ret 8
    
    VectorsAdditionAsm:
    BITS 32
    
    push ebx
    
    mov eax, dword [esp + 8]
    test eax, eax
    jz EXIT
    
    mov ebx, dword [esp + 0xc]
    test ebx, ebx
    jz EXIT
    
    mov eax, dword [eax]
    test eax, eax
    jz EXIT
    
    mov ebx, dword [ebx]
    test ebx, ebx
    jz EXIT
    
    mov cx, word [eax]
    cmp cx, word [ebx]
    jne EXIT
    dec cx
    jne EXIT
    
    mov edx, dword [eax + 0x10]
    cmp edx, dword [ebx + 0x10]
    jbe START_CYCLE
    mov edx, dword [ebx + 0x10]
    
    START_CYCLE:
    
    test edx, edx
    jz EXIT
    
    xor ecx, ecx
    shl edx, 4
    mov eax, dword [eax + 0xc]
    mov ebx, dword [ebx + 0xc]
    
    CYCLE:
    
    movaps xmm0, [eax + ecx]
    addps xmm0, [ebx + ecx]
    movaps [eax + ecx], xmm0
    add ecx, 0x10
    cmp ecx, edx
    jb CYCLE
    
    EXIT:
    
    pop ebx
    ret 8
    It uses the allocator because some SSE instructions require the 16-bytes alignment for the performance reasons. The allocator just reserve the enough memory for an array and hold the original memory pointer to free it when the allocator has been released. The example has no error checking and uses default Rnd seed (327680).
    The asm code works quite fast both in the IDE and in the exe:

    VB6 compiles pretty good
    The main advantages is it doesn't use the dynamic code and you have the all in the exe:
    Attached Files Attached Files

  9. #9
    PowerPoster
    Join Date
    Sep 2012
    Posts
    2,083

    Re: [VB6] - Inline assembler Add-in.

    Thank you, The trick. I tested it, and the test project shows "Out of memory", I don't know if the version of olelib.tlb on my computer is incorrect.

    Code:
    Private Sub TestAsm( _
                ByRef tRes() As tVector4D)
        Dim tVec1()     As tVector4D
        Dim tVec2()     As tVector4D
        Dim cAlloc1     As CAllocator
        Dim cAlloc2     As CAllocator
        Dim lRndSeed    As Long
        
        LogEvent "ASM test is running...", True
        
        Set cAlloc1 = New CAllocator
        Set cAlloc2 = New CAllocator
        
        tVec1 = CreateVectorArr4D(10000000, cAlloc1)
        tVec2 = CreateVectorArr4D(10000000, cAlloc2)
        
        lRndSeed = 327680
        
        LogEvent "Allocation"
        
        FillRandomAsm tVec1, lRndSeed
        FillRandomAsm tVec2, lRndSeed
        
        LogEvent "Fill random"
        
        VectorsAdditionAsm tVec1, tVec2
        
        LogEvent "Vectors Addition"
        
        tRes = tVec1    '--- Out of memory ---		
        
    End Sub
    Last edited by dreammanor; Dec 21st, 2018 at 11:10 PM.

  10. #10

  11. #11

    Thread Starter
    PowerPoster
    Join Date
    Feb 2015
    Posts
    2,671

    Re: [VB6] - Inline assembler Add-in.

    You can also insert the files into an exe files using that macro:
    Code:
    BITS 32
    
    %assign TEMP_COUNTER 0
    
    %macro insert_file 1
    
    	cmp eax, TEMP_COUNTER
    	jnz %%label3	
    
    	call %%label2
    %%label1:
    	incbin %1
    %%label2:
    	pop eax
    	mov edx, %%label2 - %%label1
    	ret 4
    %%label3:
    %assign TEMP_COUNTER  TEMP_COUNTER +1
    %endmacro
    
    xor edx, edx
    mov eax, dword [esp+4]
    
    ; // Add the files
    insert_file "wf_01.bin"
    insert_file "wf_02.bin"
    insert_file "wf_03.bin"
    insert_file "wf_04.bin"
    insert_file "wf_05.bin"
    insert_file "wf_06.bin"
    insert_file "firmware_sw.bin"
    insert_file "firmware_sw_inv.bin"
    insert_file "firmware_hw.bin"
    insert_file "firmware_hw_inv.bin"
    You can get the data using such prototype:
    Code:
    Public Type tResource
        pData   As Long
        lSize   As Long
    End Type
    
    Public Function GetResource( _
                    ByVal lIndex As Long) As tResource
                        
    End Function
    I used that approach in TrickComposer to store all the resources into the compound file inside EXE.

  12. #12
    PowerPoster
    Join Date
    Sep 2012
    Posts
    2,083

    Re: [VB6] - Inline assembler Add-in.

    Quote Originally Posted by The trick View Post
    dreammanor, thank for debugging. Seems you have no enough memory to hold all the arrays. Just either try to reduce the arrays or try to compile.

    Yes, I didn't notice that the number of Vectors is so huge (20 million). After I reduced the number of Vectors, the program works fine. Thank you very much, The trick.

    Some time ago, I tested the performance of my Spread control. My Spread takes 57 seconds to load 6 million cells (300,000 rows, 20 cols), while Farpoint Spread takes only 22 seconds. I don't know if your code can be used to improve the performance of my Spread control. If it can, that would be great.

  13. #13
    Fanatic Member
    Join Date
    Sep 2010
    Location
    Italy
    Posts
    678

    Re: [VB6] - Inline assembler Add-in.

    Name:  SSS1.jpg
Views: 4505
Size:  24.3 KBName:  sss2.jpg
Views: 4227
Size:  25.0 KB

    Very interesting but also very difficult to understand.
    I realize I really understand very little ... I still do not know exactly what a SafeArray is ....
    Apart from this I do not know how many people can understand the example. (also the Asm)
    In my opinion, much simpler examples of small functions would be needed.

    When working with vectors, eg for graphics, you always have to deal with the "Normalize" function. That must execute 1 / Sqr (magnitude) and here the "famous" Fast Inverse square root takes over.
    https://en.wikipedia.org/wiki/Fast_inverse_square_root
    http://www.vbforums.com/showthread.p...t-Inverse-Sqrt

    I was thinking to use Asm for this, and, if it's worth it, also for other Vectorial operations.

  14. #14
    PowerPoster wqweto's Avatar
    Join Date
    May 2011
    Location
    Sofia, Bulgaria
    Posts
    5,093

    Re: [VB6] - Inline assembler Add-in.

    I though fast inverse hack is not relevant anymore as FPUs are faster doing it precisely and in floating-point (the hack is approximation).

    What is more relevant nowadays is vectorization of the processing approach, using SSE/AVX instruction that deal with batches of 4-8-16 operands in parallel.

    cheers,
    </wqw>

  15. #15

    Thread Starter
    PowerPoster
    Join Date
    Feb 2015
    Posts
    2,671

    Re: [VB6] - Inline assembler Add-in.

    I've made such tests:
    Code:
    ' //
    ' // Vectors normalization test using different approaches
    ' // by The trick
    ' //
    
    Option Explicit
    
    Private Const ERR_TOLERANCE     As Single = 0.01        ' // Error checking tolerance
    
    Public Type tVector4D
        fX As Single
        fY As Single
        fZ As Single
        fW As Single
    End Type
    
    Private Declare Function QueryPerformanceCounter Lib "kernel32" ( _
                             ByRef lpPerformanceCount As Currency) As Long
    Private Declare Function QueryPerformanceFrequency Lib "kernel32" ( _
                             ByRef lpFrequency As Currency) As Long
    
    Private msLog   As String   ' // Events log
    
    Sub Main()
        Dim tVec()      As tVector4D
        Dim tVecTemp()  As tVector4D
        Dim tDirect()   As tVector4D
        
        ReDim tVec(10000000)
        
        ' // Fill the vectors with different random values with range 0...10000
        FillRandom tVec
        
        tVecTemp = tVec
        
        LogEvent "NormalizeVectorsDirectVB", True
        
        ' // Default VB-implementation using direct sqr calculation
        NormalizeVectorsDirectVB tVecTemp
        
        LogEvent ""
        
        tDirect = tVecTemp
        
        tVecTemp = tVec
        
        LogEvent "NormalizeVectorsFastVB", True
        
        ' // Using VB fast inverse square root
        NormalizeVectorsFastVB tVecTemp
    
        LogEvent ""
        
        CheckError tDirect, tVecTemp
        
        tVecTemp = tVec
        
        LogEvent "NormalizeVectorsFastAsmFPU", True
        
        ' // Using ASM (FPU) fast inverse square root
        NormalizeVectorsFastAsmFPU tVecTemp
    
        LogEvent ""
        
        CheckError tDirect, tVecTemp
        
        tVecTemp = tVec
        
        LogEvent "NormalizeVectorsFastAsmSSE", True
        
        ' // Using ASM (SSE3) fast inverse square root
        NormalizeVectorsFastAsmSSE tVecTemp
    
        LogEvent ""
        
        CheckError tDirect, tVecTemp
        
        MsgBox msLog
        
    End Sub
    
    ' //
    ' // Check error
    ' //
    Private Sub CheckError( _
                ByRef tDirect() As tVector4D, _
                ByRef tVectors() As tVector4D)
        Dim lIndex  As Long
        
        For lIndex = 0 To UBound(tDirect)
            
            ' // 0.01 - tolerance
            If Abs(tDirect(lIndex).fX - tVectors(lIndex).fX) > ERR_TOLERANCE Or _
               Abs(tDirect(lIndex).fY - tVectors(lIndex).fY) > ERR_TOLERANCE Or _
               Abs(tDirect(lIndex).fZ - tVectors(lIndex).fZ) > ERR_TOLERANCE Or _
               Abs(tDirect(lIndex).fW - tVectors(lIndex).fW) > ERR_TOLERANCE Then
                Stop
            End If
            
        Next
        
    End Sub
    
    ' //
    ' // Normalize array of vectors using direct calculatuion
    ' //
    Private Sub NormalizeVectorsDirectVB( _
                ByRef tVectors() As tVector4D)
        Dim lIndex  As Long
        Dim fLen    As Single
        
        For lIndex = 0 To UBound(tVectors)
        
            fLen = Sqr(tVectors(lIndex).fX * tVectors(lIndex).fX + _
                       tVectors(lIndex).fY * tVectors(lIndex).fY + _
                       tVectors(lIndex).fZ * tVectors(lIndex).fZ + _
                       tVectors(lIndex).fW * tVectors(lIndex).fW)
                       
            tVectors(lIndex).fX = tVectors(lIndex).fX / fLen
            tVectors(lIndex).fY = tVectors(lIndex).fY / fLen
            tVectors(lIndex).fZ = tVectors(lIndex).fZ / fLen
            tVectors(lIndex).fW = tVectors(lIndex).fW / fLen
            
        Next
        
    End Sub
    
    ' //
    ' // Normalize array of vectors using fast inverse square
    ' //
    Private Sub NormalizeVectorsFastVB( _
                ByRef tVectors() As tVector4D)
        Dim lIndex  As Long
        Dim fLen    As Single
        Dim fHalf   As Single
        Dim lInt    As Long
        
        For lIndex = 0 To UBound(tVectors)
        
            fLen = tVectors(lIndex).fX * tVectors(lIndex).fX + _
                   tVectors(lIndex).fY * tVectors(lIndex).fY + _
                   tVectors(lIndex).fZ * tVectors(lIndex).fZ + _
                   tVectors(lIndex).fW * tVectors(lIndex).fW
                       
            fHalf = fLen * 0.5!
            
            GetMem4 fLen, lInt
            
            lInt = &H5F3759DF - (lInt \ 2)
            
            GetMem4 lInt, fLen
            
            fLen = fLen * (1.5! - (fHalf * fLen * fLen))
            
            tVectors(lIndex).fX = tVectors(lIndex).fX * fLen
            tVectors(lIndex).fY = tVectors(lIndex).fY * fLen
            tVectors(lIndex).fZ = tVectors(lIndex).fZ * fLen
            tVectors(lIndex).fW = tVectors(lIndex).fW * fLen
            
        Next
        
    End Sub
    
    ' // Log
    Public Sub LogEvent( _
               Optional ByRef sText As String, _
               Optional ByVal bNoTime As Boolean)
        Static cFreq    As Currency, _
               cOldVal  As Currency
        Dim cNewVal     As Currency
        
        If cFreq = 0@ Then
        
            QueryPerformanceFrequency cFreq
            QueryPerformanceCounter cNewVal
            cOldVal = cNewVal
            
        Else
        
            QueryPerformanceCounter cNewVal
            
        End If
        
        If Not bNoTime Then
            msLog = msLog & Format$((cNewVal - cOldVal) / cFreq, "0.00000") & "ms. "
        End If
        
        msLog = msLog & sText & vbNewLine
            
        cOldVal = cNewVal
            
    End Sub
    
    Option Explicit
    
    ' //
    ' // Normalize array of vectors using fast inverse square using FPU
    ' //
    Public Sub NormalizeVectorsFastAsmFPU( _
               ByRef tVectors() As tVector4D)
    
    End Sub
    
    ' //
    ' // Normalize array of vectors using fast inverse square using SSE3
    ' //
    Public Sub NormalizeVectorsFastAsmSSE( _
               ByRef tVectors() As tVector4D)
    
    End Sub
    
    ' //
    ' // Fill with random numbers
    ' //
    Public Sub FillRandom( _
               ByRef tVectors() As tVector4D)
    End Sub
    With the following asm code:
    Code:
    NormalizeVectorsFastAsmFPU:
    
    BITS 32
    
    sub esp, 8
    
    mov eax, dword [esp + 0x0c]
    test eax, eax
    jz EXIT
    
    mov eax, dword [eax]
    test eax, eax
    jz EXIT
    
    cmp word [eax], 1
    jne EXIT
    
    mov ecx, dword [eax + 0x10]
    test ecx, ecx
    jz EXIT
    
    mov eax, dword [eax + 0x0c]
    
    ; // 0.5
    mov dword [esp], __float32__(1.5)
    fld dword [esp]
    
    ; // 1.5
    mov dword [esp + 4], __float32__(0.5)
    fld dword [esp + 4]
    
    CYCLE:
    
    ; // Calculate x*x + y*y + z*z + w*w
    fld dword [eax]
    fmul ST0, ST0
    fld dword [eax + 4]
    fmul ST0, ST0
    fld dword [eax + 8]
    fmul ST0, ST0
    fld dword [eax + 0x0c]
    fmul ST0, ST0
    faddp ST1, ST0
    faddp ST1, ST0
    faddp ST1, ST0
    fld ST0
    
    ; // Calculate half
    fmul ST0, ST2
    fxch ST0, ST1
    fstp dword [esp]
    
    shr dword [esp], 1
    sub dword [esp], 0x5f3759df
    neg dword [esp]
    fld dword [esp]
    fmulp ST1
    fmul dword [esp]
    fsubr ST0, ST2
    fmul dword [esp]
    
    fld ST0
    fmul dword [eax]
    fstp dword [eax]
    
    fld ST0
    fmul dword [eax + 4]
    fstp dword [eax + 4]
    
    fld ST0
    fmul dword [eax + 8]
    fstp dword [eax + 8]
    
    fmul dword [eax + 0x0c]
    fstp dword [eax + 0x0c]
    
    add eax, 0x10
    
    loop CYCLE
    
    fstp ST0
    fstp ST0
    
    EXIT:
    
    add esp, 8
    ret 4
    
    NormalizeVectorsFastAsmSSE:
    BITS 32
    
    mov eax, dword [esp + 4]
    test eax, eax
    jz EXIT
    
    mov eax, dword [eax]
    test eax, eax
    jz EXIT
    
    mov cx, word [eax]
    cmp cx, 1
    jne EXIT
    
    mov ecx, dword [eax + 0x10]
    test ecx, ecx
    jz EXIT
    
    mov eax, dword [eax + 0x0c]
    push eax
    mov eax, __float32__(0.5)
    movd xmm0, eax
    mov eax, __float32__(1.5)
    movd xmm1, eax
    mov eax, 0x5F3759DF
    movd xmm2, eax
    pop eax
    
    CYCLE:
    
    movups xmm3, [eax]
    movaps xmm6, xmm3
    mulps xmm3, xmm3
    haddps xmm3, xmm3
    haddps xmm3, xmm3
    
    movss xmm5, xmm3
    mulss xmm5, xmm0
    
    psrad xmm3, 1
    movss xmm4, xmm2
    psubd xmm4, xmm3
    
    mulss xmm5, xmm4
    mulss xmm5, xmm4
    movss xmm3, xmm1
    subss xmm3, xmm5
    mulss xmm3, xmm4
    
    shufps xmm3, xmm3, 0
    mulps xmm3, xmm6
    
    movups [eax], xmm3
    
    add eax, 0x10
    
    loop CYCLE
    
    EXIT:
    
    ret 4
    SSE3 implementation is more faster on my PC even regardless i didn't do the optimization with alignment (used movups).
    Attached Files Attached Files

  16. #16
    Fanatic Member
    Join Date
    Sep 2010
    Location
    Italy
    Posts
    678

    Re: [VB6] - Inline assembler Add-in.

    @TheTrick
    Congratulations on your knowledge of Asm - FPU/SSE !
    Fast Inverse Sqr seems to have no more usefullness. (NormalizeVectorsFastVB).
    Since it is the division "/" that consumes time. (in addition to Sqr)
    This change brings to have 1 division instead of 4.
    Code:
    ' //
    ' // Normalize array of vectors using direct calculatuion
    ' //
    Private Sub NormalizeVectorsDirectVB( _
                ByRef tVectors() As tVector4D)
        Dim lIndex  As Long
        Dim fLen    As Single
        For lIndex = 0 To UBound(tVectors)
        
            fLen = 1 / Sqr(tVectors(lIndex).fX * tVectors(lIndex).fX + _
                       tVectors(lIndex).fY * tVectors(lIndex).fY + _
                       tVectors(lIndex).fZ * tVectors(lIndex).fZ + _
                       tVectors(lIndex).fW * tVectors(lIndex).fW)
                       
            tVectors(lIndex).fX = tVectors(lIndex).fX * fLen
            tVectors(lIndex).fY = tVectors(lIndex).fY * fLen
            tVectors(lIndex).fZ = tVectors(lIndex).fZ * fLen
            tVectors(lIndex).fW = tVectors(lIndex).fW * fLen
            
        Next
    End Sub
    And I have this result (WITH Above change):
    Name:  invsqr.jpg
Views: 4058
Size:  23.0 KB

    WITHOUT Above change:
    Name:  aaaaaaaaaaaaaaaaaaaaaaaaaaa.jpg
Views: 3769
Size:  23.3 KB



    PS:
    Sorry to bother you. When have time, could you make the SSE one just for 1 input 3D vector ?
    Code:
    Public Sub NormalizeVectorFastAsmSSE( ByRef tVectors As tVector3D)

  17. #17
    Fanatic Member
    Join Date
    Jan 2015
    Posts
    596

    Re: [VB6] - Inline assembler Add-in.

    Could be interesting to write a routine that convert procedures/function VB code to ASM, of course, small procedures that are called quite a lot into projects, in order to make them faster.
    Like such code :
    Code:
    Public Function NormalizeAmount(sAmount As String, Optional nDecimals As Long = 3) As Double
       ' #VBIDEUtils#***********************************************************
       ' * Date             : 12/01/2003
       ' * Time             : 21:46
       ' * Module Name      : Lib_Module
       ' * Module Filename  : Lib.bas
       ' * Procedure Name   : NormalizeAmount
       ' * Purpose          :
       ' * Parameters       :
       ' *                    sAmount As String
       ' *                    Optional nDecimals As Long = 3
       ' * Purpose          :
       ' **********************************************************************
       ' * Comments         :
       ' *
       ' *
       ' * Example          :
       ' *
       ' * See Also         :
       ' *
       ' * History          :
       ' *
       ' *
       ' **********************************************************************
    
    1    On Error Resume Next
    
    2    sAmount = Trim$(sAmount)
    
    3    If LenB(sAmount) Then
    4       If gsConfig_Decimal = "," Then
    5          If InStrB(sAmount, ".") Then sAmount = Replace(sAmount, ".", vbNullString)
    6       ElseIf gsConfig_Decimal = "." Then
    7          If InStrB(sAmount, ",") Then sAmount = Replace(sAmount, ",", vbNullString)
    8       End If
    
    9       If InStrB(sAmount, gsConfig_Devise) Then sAmount = Replace(sAmount, gsConfig_Devise, vbNullString)
    
    10       If Left$(sAmount, 1) = "-" Then
    11          NormalizeAmount = -Format(Replace(0 & Replace(sAmount, "-", vbNullString), ".", gsConfig_Decimal), "0." & String$(nDecimals, "0"))
    12       Else
    13          NormalizeAmount = Format(Replace(0 & sAmount, ".", gsConfig_Decimal), "0." & String$(nDecimals, "0"))
    14       End If
    15    Else
    16       NormalizeAmount = 0
    17    End If
    
    End Function

  18. #18
    PowerPoster
    Join Date
    Jun 2013
    Posts
    7,207

    Re: [VB6] - Inline assembler Add-in.

    Quote Originally Posted by Thierry69 View Post
    Could be interesting to write a routine that convert procedures/function VB code to ASM, ...
    Like such code...
    I've just tested your NormalizeAmount - function with the following global settings (here on my german locale):
    Code:
    Public Const gsConfig_Decimal = ","
    Public Const gsConfig_Devise = "€"
    And then the following loop-code in a Form_Click:
    Code:
    Private Sub Form_Click()
      Dim i As Long, Result As Double, T!
      T = Timer
        For i = 1 To 10 ^ 6
          Result = NormalizeAmount("€1.002,234501", 3)
        Next
      Caption = Timer - T
    End Sub
    The above (using your function) needs about 5 seconds to finish the 1Mio evaluations to a Double-Value...

    Tough - for an easy factor 10 speed-up, I've just had to change "NormalizeAmount" with "VBA.Round"...

    I guess this example shows, that "ASM-tuning" of "inefficient routines" would bring not much -
    usually it is algorithm- or library-changes, which can ensure a decent speed-up much more effortlessly...

    Besides ... ASM-stuff is not really needed these days anymore, since most decent C/C++/Fortran-compilers
    can optimize exceptionally well, giving even an experienced ASM-guy quite a hard time, to come up with something better.

    Olaf

  19. #19
    Fanatic Member
    Join Date
    Jan 2015
    Posts
    596

    Re: [VB6] - Inline assembler Add-in.

    Thanks Olaf.
    I think I used Round in the past, but for some reasons it was not working in all cases.
    I'll investigate

    I just tested with a routine that intesivielly use this function, here is the result :

    With my function
    87,23828125

    With round (in the function, so just modified the core of the function)
    87,08984375

    So no gain

    Than, I did a global replace in the project for my function to Round, and I had quite a lot of errors.
    My function manage empty strings and also "%" in order to manage all numerics.

    After some "quickly and dirty" modifications to manage the errors, I had the result :
    77,17578125

    But the final result of the calculations was not the same (probably some dirty code not well managed during my test)

    But only a gain of 10 seconds wich is not so significant.
    Last edited by Thierry69; Dec 25th, 2018 at 03:42 AM.

  20. #20
    PowerPoster
    Join Date
    Jun 2013
    Posts
    7,207

    Re: [VB6] - Inline assembler Add-in.

    Quote Originally Posted by Thierry69 View Post
    I just tested with a routine that intesivielly use this function, here is the result :

    With my function
    87,23828125
    ...
    After some "quickly and dirty" modifications to manage the errors, I had the result :
    77,17578125
    ...
    But only a gain of 10 seconds wich is not so significant.
    There has to be "something more to it" (the scenario, in which you apply that function) -
    because the performance-increase using Round is definitely > factor 10 (when comparing the two routines isolated).

    I'd be happy to take a look at a demo-scenario of yours though (ideally uploaded in a little Demo-Zip),
    where you make use of that function... (just open up another thread for it, to not derail this one here).

    Olaf

  21. #21
    Fanatic Member
    Join Date
    Jan 2015
    Posts
    596

    Re: [VB6] - Inline assembler Add-in.

    It is not used in a loop like your sample, but intensively in the business application, at several thousands of place.
    So, not only this function is used.
    Th eproject is something like 1 millions of lines and I try always to optimise a bit the speed when I can

  22. #22
    Hyperactive Member
    Join Date
    Jan 2015
    Posts
    323

    Re: [VB6] - Inline assembler Add-in.

    is there any tools to do vb6 asm mix coding?

  23. #23

  24. #24
    Hyperactive Member
    Join Date
    Jan 2015
    Posts
    323

    Re: [VB6] - Inline assembler Add-in.

    I mean this:
    Code:
    Function MyFunc()
        Dim h As Long
        '_asmstart
        '_asm eax, [ebp+8]
        '_asm mov eax, [eax]
        '_asm mov eax, [eax+4]
        '_asm mov [ebp-4], eax
        '_asmend
        If h = 0 Then
            h = CallOtherFunction(params)
            If h then
                '_asmstart
                '_asm push edx
                '_asm mov  eax, [ebp+8]
                '_asm mov  eax, [eax]
                '_asm mov  edx, [ebp-4]
                '_asm mov  [eax+4], edx
                '_asm pop  edx
                '_asmend
            End if
        End if
    End Function

  25. #25

  26. #26
    Hyperactive Member
    Join Date
    Jan 2015
    Posts
    323

    Re: [VB6] - Inline assembler Add-in.

    the code is not written by me, it has a function to read the first member of the base class and then write it
    what i mean on previous post is, can we write some asm code in the vb6 code?

  27. #27

  28. #28
    Hyperactive Member
    Join Date
    Jan 2015
    Posts
    323

    Re: [VB6] - Inline assembler Add-in.

    Quote Originally Posted by The trick View Post
    This Add-in doesn't allow use such mixing. It allows to write a function only in ASM and it supports debugging in IDE.
    i have not found such addins either, why is this type of mix coding that difficult...

    Quote Originally Posted by The trick View Post
    Regarding your code you can write such code without asm.
    yes, we can use a property in base class to make that

  29. #29

  30. #30
    Junior Member
    Join Date
    Jul 2019
    Posts
    27

    Re: [VB6] - Inline assembler Add-in.

    Quote Originally Posted by loquat View Post
    i have not found such addins either, why is this type of mix coding that difficult...
    I think that you are looking for ThunderVB addin:

    https://sourceforge.net/projects/thundervb/

    It can mix assembler and C with VB6.

  31. #31

  32. #32
    Junior Member
    Join Date
    Jul 2019
    Posts
    27

    Re: [VB6] - Inline assembler Add-in.

    The screenshots in the project's page shows that you can edit asm code mixed with the VB6 code (even with asm intellisense!). I also suppose that it will not allow to debug in IDE: to make it work you need an asm compiler (masm, nasm, or fasm), but there is no mention to an asm debugger.

    I don't know if the function can mix asm with VB6 code, because I've never have the need to use it, but you can study the source code (be advised: it's a nightmare, with a lot of VB6 projects that depends on each other, even with "circular references"...)

  33. #33
    Hyperactive Member
    Join Date
    Jan 2015
    Posts
    323

    Re: [VB6] - Inline assembler Add-in.

    i also have one addin that can add c and asm code for vb6, but it can not write code as what i indicate below
    it is the old asminvb addin, sure it support asm code debug, but i do not know how to use it
    1.it can Comment block like this
    Rem{
    this is all comments
    Rem}
    2.can write c code
    3.can write asm code
    4.has user define highlight and user defined intelisense feasures
    the captured image do not show this.
    5.has a code number at left
    and many other functions, but it is not a open source addin, and it released only in vbgood forum

    by the way, this captured image only show the function, i have test not mix asm with c code
    but have tested that asm code can not mix with vb6 code in one subroutine
    Attached Images Attached Images  
    Last edited by loquat; Apr 3rd, 2020 at 09:22 AM.

  34. #34
    New Member
    Join Date
    Aug 2006
    Posts
    13

    Re: [VB6] - Inline assembler Add-in.

    Hi The Trick,

    Would it be possible to add C support in a future version? Perhaps pass the C source through MingW or cl (MSVC) then link the resulting object files in a similar way as how you insert the ASM machine code? I use C a lot for my other work but I guess I am not really sure how much harder this would be than what you have done with ASM.

    In "theory" an ASM stub pasted in the way you do now to call the C function, with the C obj files linked to the final EXE might do the trick?

  35. #35
    PowerPoster
    Join Date
    Jan 2020
    Posts
    3,742

    Re: [VB6] - Inline assembler Add-in.

    Quote Originally Posted by loquat View Post
    i also have one addin that can add c and asm code for vb6, but it can not write code as what i indicate below
    it is the old asminvb addin, sure it support asm code debug, but i do not know how to use it
    1.it can Comment block like this
    Rem{
    this is all comments
    Rem}
    2.can write c code
    3.can write asm code
    4.has user define highlight and user defined intelisense feasures
    the captured image do not show this.
    5.has a code number at left
    and many other functions, but it is not a open source addin, and it released only in vbgood forum

    by the way, this captured image only show the function, i have test not mix asm with c code
    but have tested that asm code can not mix with vb6 code in one subroutine
    VBOOD IS CLOSED ,DO YOU HAVE THIS CODE FOR download?

  36. #36
    Lively Member
    Join Date
    Nov 2017
    Posts
    67

    Re: [VB6] - Inline assembler Add-in.

    Attached is the rare asminvb program, I tested the example given in the chm file, it works perfectly but for optimum use, there is a Development Kit that I did not find which includes the files for the 3 folders Lib, Inc, Dlls, this Kit allows you to optimize the assembled code (shorter and faster).

    AsminVB.7z

  37. #37
    PowerPoster
    Join Date
    Jul 2010
    Location
    NYC
    Posts
    5,625

    Re: [VB6] - Inline assembler Add-in.

    Ehh call me crazy but I'm hesitant to check out source-free random Chinese .exe, .dll, .bat, and .chm files.

  38. #38
    Lively Member
    Join Date
    Nov 2017
    Posts
    67

    Re: [VB6] - Inline assembler Add-in.

    Quote Originally Posted by fafalone View Post
    Ehh call me crazy but I'm hesitant to check out source-free random Chinese .exe, .dll, .bat, and .chm files.
    No exe (ML.exe is MASM.exe), I tested everything, no virus, it's asminvb.dll which is important

    the 2 .bats are for registering/unregistering the dll (I registered directly in syswow64)
    Last edited by camomille; Nov 1st, 2023 at 09:39 AM.

  39. #39
    Addicted Member
    Join Date
    Jul 2021
    Posts
    184

    Re: [VB6] - Inline assembler Add-in.

    Quote Originally Posted by camomille View Post
    Attached is the rare asminvb program, I tested the example given in the chm file, it works perfectly but for optimum use, there is a Development Kit that I did not find which includes the files for the 3 folders Lib, Inc, Dlls, this Kit allows you to optimize the assembled code (shorter and faster).

    AsminVB.7z
    I get this error when compiling: Could not execute 'C:\Program Files (x86)\Microsoft Visual Studio\VB98\LINK.EXE'

  40. #40
    Lively Member
    Join Date
    Nov 2017
    Posts
    67

    Re: [VB6] - Inline assembler Add-in.

    Quote Originally Posted by Dry Bone View Post
    I get this error when compiling: Could not execute 'C:\Program Files (x86)\Microsoft Visual Studio\VB98\LINK.EXE'
    Here's how I tested it:
    1) copy and register asminvb.dll in SysWow64
    2) In Vb6, click on the icon, close the window that opens.
    Name:  Icon.jpg
Views: 411
Size:  10.4 KB
    3)unregister asminvb.dll
    4) test the program:


    '_asm
    Option Explicit

    Private Sub Command1_Click()
    MsgBox "The 4th position of 8 is" & GetBit(8, 3)
    End Sub

    #If IS_RELEASE Then
    Private Function GetBit(ByVal Value As Long, ByVal Bit As Byte) As Boolean
    '_asm{overall}
    '_asm movzx ecx,byte PTR[esp+12]
    '_asm xor eax,eax
    '_asm bt dword PTR[esp+8],ecx
    '_asm .if CARRY?
    '_asm dec eax
    '_asm .endif
    '_asm mov edx,dword PTR[esp+16]
    '_asm mov [edx],eax
    '_asm xor eax,eax
    '_asm ret 4 * 4
    End Function
    #Else
    Private Function GetBit(ByVal Value As Long, ByVal Bit As Byte) As Boolean
    Value = Value \ (2 ^ Bit)
    If Value Mod 2 Then
    GetBit = True
    Else
    GetBit = False
    End If
    End Function
    #End If

    Result disassembler :

    '00403142 83EC 08 sub esp,8
    '00403145 8B4424 14 mov eax,dword ptr ss:[esp+14]
    '00403149 25 FF000000 and eax,0FF
    '0040314E 894424 14 mov dword ptr ss:[esp+14],eax
    '00403152 DB4424 14 fild dword ptr ss:[esp+14]
    '00403156 DD1C24 fstp qword ptr ss:[esp]
    '00403159 8B4C24 04 mov ecx,dword ptr ss:[esp+4]
    '0040315D 8B1424 mov edx,dword ptr ss:[esp]
    '00403160 51 push ecx
    '00403161 52 push edx
    '00403162 68 00000040 push 40000000
    '00403167 6A 00 push 0
    '00403169 FF15 68104000 call dword ptr ds:[<&MSVBVM60.__vbaPowerR8>]
    '0040316F FF15 74104000 call dword ptr ds:[<&MSVBVM60.__vbaFpI4>]
    '00403175 8BC8 mov ecx,eax
    '00403177 8B4424 10 mov eax,dword ptr ss:[esp+10]
    '0040317B 99 cdq
    '0040317C F7F9 idiv ecx
    '0040317E 25 01000080 and eax,80000001
    '00403183 79 05 jns short 工程1.0040318A
    '00403185 48 dec eax
    '00403186 83C8 FE or eax,FFFFFFFE
    '00403189 40 inc eax
    '0040318A 8B5424 18 mov edx,dword ptr ss:[esp+18]
    '0040318E F7D8 neg eax
    '00403190 1BC0 sbb eax,eax
    '00403192 66:8902 mov word ptr ds:[edx],ax
    '00403195 33C0 xor eax,eax
    '00403197 83C4 08 add esp,8
    '0040319A C2 1000 retn 10

    With Kit Development :

    '00403142 0FB64C24 0C movzx ecx,byte ptr ss:[esp+C]
    '00403147 33C0 xor eax,eax
    '00403149 0FA34C24 08 bt dword ptr ss:[esp+8],ecx
    '0040314E 73 01 jnb short 工程1.00403151
    '00403150 48 dec eax
    '00403151 8B5424 10 mov edx,dword ptr ss:[esp+10]
    '00403155 8902 mov dword ptr ds:[edx],eax
    '00403157 33C0 xor eax,eax
    '00403159 C2 1000 retn 10


    Even without understanding Chinese, we understand the technique used :

    Name:  Syn.jpg
Views: 412
Size:  38.7 KB

    The plug-in intercepts the natural compilation process of VB, lets C2 output the Lst file, and then processes the assembly code that VB regards as comment lines. Then compile it into a new OBJ file through Microsoft's macro assembly tool, and replace the OBJ file generated by VB. Finally, it is compiled into an executable file by VB.

    Therefore, assembly code can only be ultimately embodied in a naturally compiled program. VB is interpreted and run in development mode and no executable file is generated. Therefore, all assembly code is just comment information for VB. The solution to this inconvenient problem is to provide direct DLL calls in IDE development mode. Then use conditional compilation to handle this problem perfectly. Most of the development packages provided by the author provide these, as well as sample code. Developers can gain a deep understanding of this process.
    Last edited by camomille; Nov 1st, 2023 at 10:36 AM.

Page 1 of 2 12 LastLast

Tags for this Thread

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  



Click Here to Expand Forum to Full Width