Hi There,
I program mostly in VB, and would like to know how to create a function which returns a number or a string similiar to VB like below:


VB CODE EXAMPLE BELOW:
'Function makes a comparison based on giving text and then returns the value...
Public Function FunctionName(Text AS String)
If Text = "Good" then
FunctionName() = "Text Found"
else
FunctionName() = "Text not Found"
End If
End Sub

-OR-

Public Function FunctionName(Text AS String)
If Text = "Good" then
FunctionName() = 817
else
FunctionName() = 978
End If
End Sub


Anyone know how to do it?
Posted on 2003-03-02 22:13:48 by Knight Chat X
With procedures a program normally expects numbers to be returned in the eax register. In any language a function puts the return value into the eax register before it returns. In the case of strings it is actually a pointer to the string that is being returned not the actual text, that pointer is returned in eax as well. When you specify AS STRING you are informing VB that the number returned is a pointer to a NULL terminated string and not an actual number. So, to return a number or a string...

NUMBER:
mov eax,NUMBER
ret

STRING
lea eax,STRING
ret

or

mov eax,OFFSET STRING
ret

Donkey
Posted on 2003-03-02 22:20:40 by donkey
Thank you Donkey, you hit the nail on the head, or as 1 might say to a donkey, you sure pinned the tail on that one, hehe.

That bit of information is hard to come by without all the details.
Posted on 2003-03-02 23:25:54 by Knight Chat X
Knight Chat X,
i am just gonna nit-pick here: your VB is a bit dodgy. Because you didn't declare a return type from your functions, the returned value is cast as a variant. Variants are convenient, but evil ;)

OK, i feel better now :) If you do a search, you will find a couple of fairly detailed posts i have done explaining how to pass values from VB to asm and back, if you read these it may help with your understanding, and enable you to use asm dlls from a VB gui.
Posted on 2003-03-03 05:03:15 by sluggy
When you return string like donkey has shown, make sure that returned string is not LOCAL (on stack) otherwise it becomes invalid when procedure returns.
Posted on 2003-03-03 16:34:34 by comrade
Hi Sluggo,
Yea, I could've probably given a fuller example but figured the question was simple enuff.

Donkey hit the nail on the head, because what I was asking was how to setup a function where the return value could be passed either as a string or number, the example's he gave filled in the gap showing how a function would do a return to produce the right output.

Lastly, I'm trying to convert user defined code from VB to assembler, not use assembler through VB using a DLL or even directly.

Here's a more complete modification of the first post:
Public Function KCX_Test(Text As String) As String
If Text = "Good" then KCX_Test() = "Text Found"
End Sub
Posted on 2003-03-03 16:39:41 by Knight Chat X
sluggy said
Knight Chat X,
i am just gonna nit-pick here: your VB is a bit dodgy. Because you didn't declare a return type from your functions, the returned value is cast as a variant. Variants are convenient, but evil ;)

OK, i feel better now :) If you do a search, you will find a couple of fairly detailed posts i have done explaining how to pass values from VB to asm and back, if you read these it may help with your understanding, and enable you to use asm dlls from a VB gui.


Also he has end sub instead of end function. ;)

And as for the Variants are evil... I havea book here from MS that says to use variants and they are not evil they are actually faster...
Posted on 2003-03-03 16:41:27 by Gunner
Next time, I'm just gonna type the code in the VB IDE that way there's syntax checking, nobody's perfect, haha.

=oP
Posted on 2003-03-03 16:58:31 by Knight Chat X
So you are trying to convert:



Public Function KCX_Test(Text As String) As String
If Text = "Good" Then
KCX_Test = "Text Found"
Else
KCX_Test = "Text NOT Found"
End If
End Function


to assembly? If so, it isn't to hard... I will scrounge up some code, post it and explain it to you.
Posted on 2003-03-03 17:04:29 by Gunner
Yep

Thanks for the help guys I appreciate it.
Posted on 2003-03-03 17:11:26 by Knight Chat X
Ok, for testing, add the following to the .data section (using masm here)


sGood BYTE 'Good', 0
sFound BYTE 'Text Found', 0
sNotFound BYTE 'Text NOT Found', 0
sBadText BYTE 'Bad', 0

and this is the converted function... I was too lazy so I used the api:


KCX_Test proc pszText:DWORD
push offset sGood ; Compare string
push pszText ; String to compare
call lstrcmpi
test eax, eax
jz Good ; It matches
jmp NoGood ; No Match
Good:
lea eax, sFound ; return the address of string
ret

NoGood:
lea eax, sNotFound ; same here
ret
KCX_Test endp

and to call it we pass the address of the string to check:


push offset sGood ; need address to string
call KCX_Test

push 0
push 0
push eax ; address of returned string
push 0
call MessageBox

push offset sBadText ; need address to string
call KCX_Test

push 0
push 0
push eax ; address of returned string
push 0
call MessageBox


Make sense?
Posted on 2003-03-03 17:23:47 by Gunner
Knight Chat X,

Here's a quick way to do it using the CompareString function from the API. It's generally not as fast as comparable handwritten functions but it is fairly efficient when no parameters are specified
.Const

LOCALE_SYSTEM_DEFAULT equ 2048
.data
lpszGOOD BYTE "Good",0
lpszFOUND BYTE "Text Found",0
lpszNOTFOUND BYTE "Text NOT Found",0

.code
start:
; lots of stuff here to do with your window and exactly what is calling the procedure etc...


[b]KCX_Test proc lpszTEXT:DWORD
invoke CompareString,LOCALE_SYSTEM_DEFAULT,0,lpszTEXT,-1,ADDR lpszGOOD,-1
cmp eax,2
jne @F
mov eax,OFFSET lpszFOUND
ret
@@:
mov eax,OFFSET lpszNOTFOUND
ret
KCX_Test endp[/b]

start ends
Pass the string as a pointer to the procedure like this...

Invoke KCX_Test,ADDR MyString

Donkey
Posted on 2003-03-03 17:39:03 by donkey
;DATA
.data
scs1 BYTE "Test1",0
scs2 BYTE "Test2",0
m1Found BYTE "Match 1 Found",0
m2Found BYTE "Match 2 Found",0
mNotFound BYTE "No Match's Found",0


;PROC
;Does a text/string comparison, then return a text/string pointer in eax...
KCX_Test proc pszText:DWORD
push offset scs1 ; push compare string.
push pszText ; push string to compare.
call lstrcmpi ; call string compare api.
test eax,eax ; do comparison.

jz Match1Found ; jump if comparison match's.
jmp Check2 ; match not found so jump to next check.

Match1Found: ; match 1 found code label.
lea eax,m1Found ; put/set string pointer in the eax register.
ret ; return/exit function.

Check2: ; check 2 code label.
push offset scs2 ; push compare string 2.
push pszText ; push string to compare.
call lstrcmpi ; call string compare api.
test eax,eax ; do comparison.

jz Match2Found ; jump if comparison match's.
jmp ChecksFinished ; match not found, so do 1 last jump.

Match2Found: ; Match 2 found code label.
lea eax,m2Found ; put/set string pointer in the eax register.
ret ; return/exit function.

ChecksFinished: ; Checks Finished code label.
lea eax,mNotFound ; put/set string pointer in the eax register.
ret ; return/exit function.
KCX_Test endp

;CALL FUNCTION
push offset m2Found ;push string check pointer.
call KCX_Test ;call test function.

;VIEW TEST RESULT
push 0 ;push style.
push 0 ;push title.
push eax ;push returned string pointer.
push 0 ;push return window handle.
call MessageBox ;call function to display result.
Posted on 2003-03-08 03:24:48 by Knight Chat X
Save some bytes.



.data
scs1 BYTE "Test1",0
scs2 BYTE "Test2",0
m1Found BYTE "Match 1 Found",0
m2Found BYTE "Match 2 Found",0
mNotFound BYTE "No Match's Found",0

.code
KCX_Test proc pszText:DWORD
push offset scs1
push pszText
call lstrcmpi
test eax,eax

jnz Check2

Match1Found:
lea eax,m1Found
ret

Check2:
push offset scs2
push pszText
call lstrcmpi
test eax,eax

jnz ChecksFinished

Match2Found:
lea eax,m2Found
ret

ChecksFinished:
lea eax,mNotFound
ret
KCX_Test endp

;CALL FUNCTION
push offset m2Found ;push string check pointer.
call KCX_Test ;call test function.

;VIEW TEST RESULT
push 0 ;push style.
push 0 ;push title.
push eax ;push returned string pointer.
push 0 ;push return window handle.
call MessageBox ;call function to display result.


Posted on 2003-03-08 06:52:20 by roticv
You optimized the code using jnz to replace the other jmp instructions and speed up the code, saved a few bytes, thanks... =)

btw, have I seen you somewhere before?
Posted on 2003-03-08 07:18:55 by Knight Chat X
I really don't know. I just hang around on 2 forums.
Posted on 2003-03-08 07:30:03 by roticv