NOTE: The functions were located & tested inside an object.
Additionally, the offsets from ebp I provided might not be the same in all situations
*Returning a long
Parameter with double pointer to return
Local Variable to hold data assigned to be returned
Example:
Public Function Test() as Long
Test = 20 'local variable
End Function
EBP+0C = Double pointer to return
EBP-18 = Local variable to hold data to be returned
*Returning an integer
Parameter with double pointer to return
Local Variable to hold data assigned to be returned
Example:
Public Function Test() as Integer
Test = 20 'local variable
End Function
EBP+0C = Double pointer to return
EBP-18 = Local variable to hold data to be returned
*Returning an boolean
Parameter with double pointer to return
Local Variable to hold data assigned to be returned
Example:
Public Function Test() as Boolean
Test = True 'local variable
End Function
EBP+0C = Double pointer to return
EBP-18 = Local variable to hold data to be returned
Additional Notes: Visual basic uses -1 for true and 0 for false
*Returning an byte
Parameter with double pointer to return
Local Variable to hold data assigned to be returned
Example:
Public Function Test() as Byte
Test = 20 'local variable
End Function
EBP+0C = Double pointer to return
EBP-18 = Local variable to hold data to be returned
*Returning an double
Parameter with double pointer to return
Local Variable to hold data assigned to be returned
Example:
Public Function Test() as Double
Test = 20 'local variable
End Function
EBP+0C = Double pointer to return
[[RETURN]] = High Dword
[[RETURN+4]] = Low Dword
EBP-1C = Local variable to hold data to be returned
[LOCAL] = High Dword
[LOCAL+4] = Low Dword
Additional Notes: The visual basic double data type follows the IEEE double precision floating point standard
*Returning an single
Parameter with double pointer to return
Local Variable to hold data assigned to be returned
Example:
Public Function Test() as Single
Test = 20 'local variable
End Function
EBP+0C = Double pointer to return
EBP-18 = Local variable to hold data to be returned
Additional Notes: The visual basic single data type follows the IEEE single precision floating point standard
*Returning a currency
Parameter with double pointer to return
Local Variable to hold data assigned to be returned
Example:
Public Function Test() as Curreny
Test = 20 'local variable
End Function
EBP+0C = Double pointer to return
[[RETURN]] = Low Dword
[[RETURN+4]] = High Dword
EBP-1C = Local variable to hold data to be returned
[LOCAL] = Low Dword
[LOCAL+4] = High Dword
Additional Notes: The visual basic currency data type follows an unknown standard, perhaps put forth by microsoft.
This is a typical string comparison programmers in vb6 will use, look out for this
;...
push offset string1
push offset string2
push 0
;...
call __vbaStrComp
not eax
test ax, ax
;...
je NotMatch
This block of code pushes two strings, and the comparison type to use then calls __vbaStrComp.
__vbaStrComp returns zero if it's a match. This is why the programmer will not it and then do:
If Return = True Then
'match
else
'not match
end if
If they do not perform some sort of not on the return then the if structure looks like this:
If Return = False Then
'not match
else
'match
End if
If the vb6 function is located in an object, the params will look like this:
;nasm syntax
%define return_caller [esp+04h]
%define this [esp+08h]
;...
%define returnvalue [esp+0Ch]
Where this and return are both double pointers, correct me if i'm wrong. If you have additional parameters to the function then you need to adjust the return offset.
note: this is the equivalent of the me object
note: eax is used to return the hresult, thus functions must return values over the stack
Here is a watered down version of how visual basic handles a simplistic for/next loop.
Visual Basic code located in a form
Private Sub Form_Load()
Dim intCounter as Integer, i as Integer
For intCounter = 1 to 100
i = i + 1
Next intCounter
End Sub
Watered down assembly listing
; Dim intCounter As Integer, i As Integer
; ...
; For intCounter = 1 To 100
mov eax, 1
$FORLOOPHEAD:
; i = i + 1
add cx, 1
jo SHORT $ERROROVERFLOW
add ax, 1
jo SHORT $ERROROVERFLOW
; Next intCounter
cmp ax, 100 ; 00000064H
jle SHORT $FORLOOPHEAD
; ...
$ERROROVERFLOW:
call DWORD PTR __imp____vbaErrorOverflow
; ...
; End Sub
Note: This also points out a potential optimization that should be taken into consideration by all developers: Use the appropriate data type for the amount of cycles through the for/next loop that are expected. i.e. if you need the for loop to cycle from 1 to 100 don't use an integer, use a byte. Thus, it wouldn't use ax/cx for adding, but rather al/cl. On second hand, using eax/ecx for adding might always be faster, I don't know-- if that be the case it would be to your advantage to always use a long data type for counters. Anyone have a thought on this?
Is this how an api call is made?
.text:00405348 aGetprivateprof db 'GetPrivateProfileStringA',0 ; DATA XREF: .text:00405368o
.text:00405361 align 4
.text:00405364 off_405364 dd offset aKernel32 ; DATA XREF: GetPrivateProfileStringA:loc_405387o
.text:00405364 ; "kernel32"
.text:00405368 dd offset aGetprivateprof ; "GetPrivateProfileStringA"
.text:0040536C align 10h
.text:00405370 dd offset unk_4193BC
.text:00405374 dd 2 dup(0)
....
.text:0040537C ; DWORD __stdcall GetPrivateProfileStringA(LPCSTR lpAppName,LPCSTR lpKeyName,LPCSTR lpDefault,LPSTR lpReturnedString,DWORD nSize,LPCSTR lpFileName)
.text:0040537C GetPrivateProfileStringA proc near ; CODE XREF: sub_417520+14Dp
.text:0040537C mov eax, dword_4193C4
.text:00405381 or eax, eax
.text:00405383 jz short loc_405387
.text:00405385 jmp eax
.text:00405387 ; ---------------------------------------------------------------------------
.text:00405387
.text:00405387 loc_405387: ; CODE XREF: GetPrivateProfileStringA+7j
.text:00405387 push offset off_405364
.text:0040538C mov eax, offset DllFunctionCall
.text:00405391 call eax ; DllFunctionCall
.text:00405393 jmp eax
.text:00405393 GetPrivateProfileStringA endp
Also, i've noticed that they're not called by any definate functions. how does vb6 store/call functions and call event subs?
i thought api calls were made through msvbvm60.dll, not directly from the exe? but i could be wrong.
Quote from: l2k-Shadow on March 23, 2008, 04:11 PM
i thought api calls were made through msvbvm60.dll, not directly from the exe? but i could be wrong.
They are. hence "DllFunctionCall".