Experiences with VB6 and ASM : (I hope it is useful)

[0] VB6 uses two methods of passing parameters to external functions, each with a different keyword : ByVal and ByRef (default).
I' ve experienced the use of both with two different data types : String and Long;
here are the results :

[1] Passing a string to an ASM function

VB internally uses BSTR data type which is different from the traditional null-terminated string. If you try to pass it to your asm function ByRef, you get a pointer to it rather that the actual data. It should be possible to "decode" this format but you can fly over that problem by the use of ByVal : this cause a copy of your string to be created by VB in the classical format and a pointer to that string to be pushed on the stack! It is now easy to manipulate it into your function :

ASM DLL:

.data

Hello db 'HELLO',0

.code
........................
Stringa proc puntatore:DWORD

push MB_OK
push offset Hello
push puntatore
push 0
call MessageBox
ret

Stringa endp

VB6 EXE:
Public Declare Sub Stringa Lib "skeleton.dll" (ByVal puntatore As String)
........
Dim l As String
l = "World!"
Call Stringa(l)
................
RESULTS : HELLO World!

[2] Passing a Long ByVal to an ASM function

Longs are 32 bit signed values that can be stored/returned directly in the eax register.
Because of their nature, when you pass them by value, you get them as they are.
If you pass, for example, 5, you get 5 onto the stack.

ASM DLL:

Schiera proc ptrSchiera:DWORD
mov eax, ptrSchiera
ret
Schiera endp

VB6 :
Public Declare Function Schiera Lib "skeleton.dll" (ByVal ptrSchiera As Long) As Long
..........
Dim k As Long
Dim j As Long
j = Schiera(k)

RESULTS : J=0; k=0

k = 1
j = Schiera(k)

RESULTS : J=1; k=1

Those examples are banal but demonstrate the mechanism of parameters passing/returning by eax. You can do whatever you want with the value once you have it in asm and then send it back to VB by eax.

[3] Passing a Long ByRef to an ASM function

This is a very interesting way to directly access the value of VB's Long variables by
your asm code. Here you get on the stack the effective address of Longs and can use it to change their value!

ASM DLL:

Schiera proc ptrSchiera:DWORD

mov eax, ptrSchiera
mov DWORD PTR , 99; I use eax to address the memory ***
mov eax, ptrSchiera
ret

Schiera endp

VB6 EXE:

Public Declare Function Schiera Lib "skeleton.dll" (ByRef ptrSchiera As Long) As Long
.....................
Dim k As Long
Dim j As Long
k = 1
j = Schiera(k)

RESULTS : j=1242668 (memory address); k=99



*** Those instructions seemed good to me but didn't work : (cause of my ignorance, sorry)

;They change the value of ptrSchiera, don't write at its address as I expected!
;mov DWORD PTR ptrSchiera, 99
;mov DWORD PTR , 99
;are the same of : mov ptrSchiera, 99

[4] Passing an array of Longs ByRef to an ASM function

It is very similar to the last one and very useful for me! By using an array
of longs I can easily deal with a formatted memory area back in VB while using
the POWER of assembly for computations. Note that I don't declare I am
passing an array to my function, I just pass the first element of it.

ASM DLL:

Schiera proc ptrSchiera:DWORD

mov eax, ptrSchiera
mov DWORD PTR , 99;sch(1)
add eax, 4
mov DWORD PTR , 88;sch(2)
mov eax, ptrSchiera
ret

Schiera endp

VB6 EXE:

Public Declare Function Schiera Lib "skeleton.dll" (ByRef ptrSchiera As Long) As Long
.....................
Dim sch(1 To 10) As Long
Dim j As Long
sch(1) = 22
j = Schiera(sch(1))

RESULTS : j=2289432 (memory address); sch(21) = 99 And....what about sch(2) ? Obviously 88!!

fooCoder
Posted on 2003-04-22 04:00:58 by fooCoder
Please REMOVE the last "mov eax, ptrSchiera" from [3] and [4], it is useless!:)

fooCoder
Posted on 2003-04-22 04:04:52 by fooCoder
... doesn't seem useless to me.
Posted on 2003-04-22 04:44:14 by abc123
yes, that's really useful information foocoder

eg. for writing a game you could do the speed-critical parts in assembler ... and the high-score tables and "type in your name" etc parts in VB...:)
Posted on 2003-04-22 05:16:35 by argus
fooCoder,
if you had done a search of the board you would have found that i (and others) have posted all this information before. In fact, you seem to quote the very same information i posted to one of your threads about two days ago. Here are a few pointers:

- it is good that you experimented, this is an excellent way to learn

- if you search the board first, you can save yourself a lot of time

- <edit> this point removed, no longer valid!!!!!!!!!! </edit>

- to be a safe and good VB l33t h4x0r, your dll function declarations should use "As Any" for the array parameters

- if you want to receive string values back (ie change them in the asm function), then you either have to learn to use BSTR's (they really are simple), or like i said the other day pass a byte array ByRef then reassemble it into a string back in VB. Arrays of structures have to be handled the same way.
Posted on 2003-04-22 06:55:19 by sluggy
To abc123 : I wrote that the last "mov eax, ptrSchiera" are useless because eax is has just been just loaded with the same value before.

To argus : Yes, I think it is one of the best way to use assembly in modern applications. You can manage speed critical tasks or take advantage of such instructions like mmx, simd...etc

To sluggy : You are right, I "felt" that those info were around but I haven't had the time to make a good research of threads...(I am working with an old P II off-line until the end of May) so I captured the moment when nobody was putting pressure on me at office and made those experiences...I just knew how to pass strings and longs ByVal but hadn't played with arrays or similar...( You give me the idea :) )

Anyway, this forum is composed of people of different skills, some are experts (COM, Videogames...) other are just novices asking apparently simple questions...sometimes you can read questions, posted by novices, which is impossible to answer because one don't know where to start from...I am neither a novice in assembly nor an expert so I hope that what I write can be useful for the first ones and interesting to the last ones (which I hope can correct my faults/omissions..etc...)

I have a debt with this forum because 85% I know about Win32 programming is due to it!! :) (16 bit asm, flat real mode programming are another music...)

Soon I will be experiencing with asm and .NET languages to check if about has changed about calling asm-DLLs, because I want really to USE much more assembly at work (alone or mixed).

regards,

fooCoder
Posted on 2003-04-22 23:38:23 by fooCoder
Does VB support the use of inline assembler?

(I am not a VB user.)
Posted on 2003-04-23 08:53:04 by Vortex
Don't think so...
Posted on 2003-04-23 08:57:16 by f0dder
No, it doesn't. However, in QB (maybe VB, too), you could use DEF SEG and use the DATA statement to enter byte code and jump to it. i have seen something for use in QuickBasic (not QBasic) that adds assembly-language like capabilities to QB, like:

mov reg.ax,bleh

don't remember where i saw this, but it is *somewhere* on my 386. i think it was a Snoopy game (like a 2D game).
Posted on 2003-04-23 09:35:20 by jademtech
No, it doesn't. However, in QB (maybe VB, too), you could use DEF SEG and use the DATA statement to enter byte code and jump to it. i have seen something for use in QuickBasic (not QBasic) that adds assembly-language like capabilities to QB, like:

mov reg.ax,bleh

don't remember where i saw this, but it is *somewhere* on my 386. i think it was a Snoopy game (like a 2D game).
Most of the old Basics had this feature using PEEK/POKE/CALL. IMO this feature is good on 8 bit cpus, but would be useless on todays cpus.
Posted on 2003-04-23 17:04:09 by sluggy