First of all note that the example below is totally useless and will probably crash.. The real problem is too complicated to explain quickly so I've setup a simple example that has the same problem:

say you have some data and types:


SomeData dd 44342,2343,23423,4234

SomeStruct STRUCT
Val1 dd ?
Val2 dd ?
SomeStruct ENDS

.code
SomeFunctionPto TYPEDEF PROTO :DWORD, :DWORD


What I want is (or at least seems) simple: doing this ....


push 2
push 1
call dword ptr [SomeData + SomeStruct.Val2]

with an invoke....
(btw the call is a call to a function which prototype is SomeFunctionPto)
The code above translates to:


.00001268: 6A02 push 002
.0000126A: 6A01 push 001
.0000126C: FF151C314000 call d,[00040311C]

which is correct.
now how should I use invoke to do this.. I've tried this:


invoke SomeFunctionPto PTR [SomeData + SomeStruct.Val1], 1, 2

Which seems very logically but it produces this:


.00001273: 6A02 push 002
.00001275: 6A01 push 001
.00001277: E89C1E0000 call 000002518

Why call 2518???? I'm totally lost on this one, i've tried everything, adding offsets ('offset SomeData'), trying different formats but I can't get it to work.. What's wrong?

Thomas
Posted on 2001-09-01 04:31:11 by Thomas
This just worked for me:

invoke SomeFunctionPto PTR .SomeStruct.Val2, 1, 2
Posted on 2001-09-01 10:51:37 by bitRAKE
But I prefer this:


SomeFunctionPto TYPEDEF PROTO :DWORD, :DWORD

pSomeFunctionPto TYPEDEF PTR SomeFunctionPto

SomeData dd 44342,2343,23423,4234

SomeStruct STRUCT
Val1 dd ?
Val2 pSomeFunctionPto ?
SomeStruct ENDS


invoke [SomeData].SomeStruct.Val2, 1, 2

You don't have to use the PTR every time you want to invoke the function - it's built into the STRUCT. :)
Posted on 2001-09-01 11:11:08 by bitRAKE
Well I know that but in the code I want to use this, things are different... the structure is not directly related to the other offset like in your example.. but I will try the first method you posted.. Thanks,

Thomas
Posted on 2001-09-01 11:30:37 by Thomas
Nope, that didn't work either..


invoke SomeFunctionPto PTR [SomeData].SomeStruct.Val2, 1, 2


also produces something like
push 2
push 1
call 2518 (not even call dword ptr [2518], just call 2518 :confused: )

when I use this:


mov eax, offset SomeData + SomeStruct.Val2
invoke SomeFunctionPto PTR [eax], 1, 2

it works but I want to avoid the use of the register... and that should be possible as I can do it with a call too.. when I add offset:
invoke SomeFunctionPto PTR [offset SomeData + SomeStruct.Val2], 1, 2

it gives me this error:

error A2028: expression must be a code address

:confused:
Thomas
Posted on 2001-09-01 11:41:08 by Thomas
Well, they both work with the model that you provided. :) Obviously, we need more information. Or the error is somewhere else if this models your code sufficiently.
Posted on 2001-09-01 11:45:27 by bitRAKE
I've attached the code that assembles... it is shown below too..


.586
.model flat,stdcall
option casemap:none

.data


SomeData dd 344342,42342,23423,4234

SomeStruct STRUCT
Val1 dd ?
Val2 dd ?
SomeStruct ENDS

SomeFunctionPto TYPEDEF PROTO :DWORD, :DWORD


.code
start:

; goal is to make these pieces of code output the same code..
; btw running the exe will probably result in a crash, it's just
; created so you can view the output

db 8 dup (90h) ;do a search on some nops in your fav hexeditor
;to find this code in the .exe



;=============================================
; 1. This is the right output:
;=============================================
push 2
push 1
call dword ptr [SomeData + SomeStruct.Val2]

nop ;seperator
;=============================================
; 2. This SHOULD give the same output:
;=============================================
invoke SomeFunctionPto PTR [SomeData + SomeStruct.Val2], 1, 2

nop ;seperator
;=============================================
; 3. This is what BitRake suggested but didn't work for me:
;=============================================
invoke SomeFunctionPto PTR [SomeData].SomeStruct.Val2, 1, 2

nop ;seperator
;=============================================
; 4. This works but I don't want to use the register:
;=============================================
mov eax, offset SomeData + SomeStruct.Val2
invoke SomeFunctionPto PTR [eax], 6, 1

; My goal is to make the invoke work, without using a
; register and (important) without modifying the structure
; or data... it should be possible but how..

; My output of this program is:
; (if yours is different without changing anything, maybe
; something's wrong with my masm version?)

; ----- nr 1 --- correct ------------------------------------
;.00001008: 6A02 push 002
;.0000100A: 6A01 push 001
;.0000100C: FF1504204000 call d,[000402004]

;.00001012: 90 nop

; ----- nr 2 --- wrong -------------------------------------
;.00001013: 6A02 push 002
;.00001015: 6A01 push 001
;.00001017: E8E80F0000 call 000001204 ;<< strange

;.0000101C: 90 nop

; ----- nr 3 --- wrong as well -----------------------------
;.0000101D: 6A02 push 002
;.0000101F: 6A01 push 001
;.00001021: E8DE0F0000 call 000001204 ;<<same here

;.00001026: 90 nop

; ----- nr 4 --- correct, but I don't want to use it -------
;.00001027: B804204000 mov eax,000402004
;.0000102C: 6A01 push 001
;.0000102E: 6A06 push 006
;.00001030: FF10 call d,[eax]
end start
Posted on 2001-09-01 12:27:05 by Thomas
Well, they both work with the model that you provided.

Not for me, when I assemble the code in my post above, I don't get the desired result as you can see in my dumps above.
Posted on 2001-09-01 12:32:57 by Thomas
Why not just make a macro like invoke that does whatever you want it to do.

Takes VARARG and pushes them like invoke, then takes the first varable and call dword ptr firstvariable ???

I don't know masm syntax, or else I would explain.
Posted on 2001-09-01 12:42:00 by Kenny
That would work but my first requirement is to use invoke... Because invoke has the advantages of type & parameter count checking.
I think the only problem here is getting the right syntax for the memory location.. Somehow it works for call, but not for invoke.
Posted on 2001-09-01 12:56:25 by Thomas
Nothing is wrong with your assembler. Of course, I'm wrong. :rolleyes: My second method does produce the correct code. Are you sure you can't use it?
Posted on 2001-09-01 12:58:32 by bitRAKE
The problem is, as I said, that the structure and the offset are not directly related..
I don't know if you've seen the object superclassing macro NaN wrote (as you have had contact with him), there after some calculations, two local symbols are used to form an offset. One is always 'offset something', but the other one can be either a structure member offset ('SomeStruct.Val2'), or just a number (0 or 4). the final offset in the invoke will be the sum of these two symbols.. So we can have:
call , but sometimes:
call . And in that case, we have nothing to do with the structure.

But I still wonder why it does work when I use it in a call, but doesn't with invoke... It should be the same in my view...
Posted on 2001-09-01 13:13:43 by Thomas
The assembler is making some assumptions about the PTR type - that's why it doesn't work. Just need to find a way to override those assumptions. I've been playing with the PROTO and can't figure it out? This has to be an error in MASM - why should it assume a near call here?

As to your reasoning for not using the second method: I think the objects should be an instance of the structure. Like:
SomeFunctionPto TYPEDEF PROTO :DWORD, :DWORD


pSomeFunctionPto TYPEDEF PTR SomeFunctionPto

SomeData SomeStruct2 { {44342,2343},23423,4234}

SomeStruct STRUCT
Val1 dd ?
Val2 pSomeFunctionPto ?
SomeStruct ENDS

SomeStruct2 STRUCT
SomeStruct <>
dd ?
dd ?
SomeStruct2 ENDS

invoke [SomeData].SomeStruct2.Val2, 1, 2
I don't think the data should be separated from the structure - it causes all kinds of problems. :) I emailed NaN about this yesterday. ;) Of course, this causes other problems.

This produces the right code as well:

pSomeFunctionPto TYPEDEF PTR SomeFunctionPto

invoke pSomeFunctionPto PTR .SomeStruct.Val2, 1, 2
Posted on 2001-09-01 13:46:22 by bitRAKE
I got it working!

See the attached file...
Posted on 2001-09-01 14:29:31 by Kenny
We use that method for calling an object's method, but things are different when calling a superclass method (the original method of the inherited object). The problem here is that the final offset where the dword value to call is, is not directly related to the structure anymore, there are values being substracted and added to get the right offset, so we can't use the type of a structure member in this case....
But I'll think about it, maybe we can use it anyways..
Posted on 2001-09-01 14:35:26 by Thomas
Kenny (saw your post after I replied :rolleyes: ), thanks tons!
it works, however I don't seem to need the NEAR thing in the prototype.... So basically I can use this:


funcptr TYPEDEF PTR SomeFunctionPto
invoke funcptr PTR [SomeData + SomeStruct.Val2], 1, 2

(funcptr is a local macro symbol I will use in the final macro).
This way I don't have to add another typedef for each prototype.

Thanks again :alright:

Thomas
Posted on 2001-09-01 14:42:19 by Thomas
np man ;) All I did was read the MASM reference manual :P
Posted on 2001-09-01 14:46:06 by Kenny
BitRake,

Thanx to these efforts, your comment you emailed me about concerning the syntax requirements are now lifted!!!! (Pretty happy about this).

Now Function pointing requires as much work as a simple proc would (with the extra keystrokes for "TYPEDEF" )

ie) Circ_setRadiusPto TYPEDEF PROTO :DWORD, :DWORD

This is NICE!..

Also, we now don't require complicated struct entries (both thanx to Thomas' work here..)

ie) Method dd ? ; all that is required!

Anywho.. Looks like today has been a good day of R&D...
PS: THANX Kenny and BitRake for you help!!!

NaN
Posted on 2001-09-01 20:15:53 by NaN
Kenny, see the end of my last post. Nice to see you found the same solution. :)
Posted on 2001-09-01 20:19:03 by bitRAKE
HEHE! Nice! I guess great minds read the manual alike :)

I hadn't seen your post when I posted because I hadn't refreshed.

Well, good work. You beat me by 2 minutes :alright:
Posted on 2001-09-01 23:01:02 by Kenny