Ok so I've recently started figuring out a way to do a very very simple OOP system which doesn't need inheritance and all of that complicated stuff. Basically my system is just a structure with all of the necessary variables and etc. and it also contains DWORDs which are initialized as addresses of functions. Thats one idea, and the other is for the structure to have a child structure which is basically a method table and the system i need for the macro is this:

icall MACRO <object>.<function>, <arguments>
  mov edi, addr <object>
  push <arguments>          ;all of them
  call <object>.<function>
icall ENDM

or

icall MACRO <object>.<function>, <arguments>
  mov edi, addr <object>
  push <arguments>
  call <object>.methodTBL.<function>
icall ENDM

Plus or minus a few instructions (ie push/pop edi register and etc.)

I know this is possible to do, since MASM has its base INVOKE macro which does the arguments, and ObjAsm has its ICall and OCall and etc. macros which do the <object>.<function> thing, however, ObjAsm is beyong my level and i get confused looking at them, making it next to impossible to figure out how they are done.

Anybody have an explanation as to how to do this?

Thanks in advance.
Posted on 2007-08-23 22:58:57 by 16thfactor
Hi
About OA32, if you are interested in knowing how it works, simply ask. I'll try to answere as soon as possible.
I agree with you that the macro sources look complicated, but it is the result of all build-in features.
If you want to follow the OA32 path, I suggest to look first at Demo01 to understand the basics.
Reading the Help.chm file may help another bit.

Regards,

Biterider
Posted on 2007-08-24 00:19:52 by Biterider
Thank you for your reply,

My question is simply about advanced MASM macros. The syntax and etc. How can make it so that the macro takes the first two arguments (<object> and <function>) in this format: object.Function. For example:

icall system.MessageBox, hwnd, addr str_, NULL, MB_OK

Assuming that the system object is a structure and MessageBox is a pointer to the correct function.

I don't want to use OA32 because I don't need the advanced features which it provides (inheritance, interfaces, etc.) and because I think that if I used it would be slower then if I just my own simple methods. This may or may not be true but I am a barebones type of programmer and if I can't see in a disassembler, clearly, what my app is doing, I just don't do it, and I noticed that OA32 requires quiet a bit of overhead.
Posted on 2007-08-24 00:27:02 by 16thfactor
Hi
First of all you have to think about what do you want to support, what type of calling, calling convention, variable argument count, etc, type of virtual method table (if any).
Once you have these points clear, you can think about the macros and syntax.
You can take a look at i.e. the OCall macro in the objects.inc file or the OOP demos in the MASM32 package.
ATC (by Ultrano) is another usefull source with a very good OOP model.
If you nevertheless want to jump directly to the macros, check "SubStr", "InStr" and "CatStr" in the MASM documentation.

Regards,

Biterider
Posted on 2007-08-24 00:39:58 by Biterider
Well I don't really know the technicalities of C++ oop and how the compiler generates code, but I know what the virtual method table is and I don't plan on having one at all. This is what I need for OOP:


custMessageBox proc hwnd:DWORD, text:DWORD, title:DWORD, constant_:DWORD
  invoke MessageBoxA, hwnd, text, title, constant_
custMessageBox endp

OBJECT STRUCT
  variable1  dword  ?
  variable2  dword  ?
  ...etc...
  function1  dword  addr custMessageBox
  function2  dword  addr ExitProcess
OBJECT ENDS

.data?
exObj OBJECT <>

.code
start:
icall exObj.function1, hwnd, addr strText, addr strTitle, dwFlags
icall exObj.function2, 0
end start


My OOP "model" is simple and only meant for me to use for this project and maybe a few more, and it isn't viable in really big projects or those that interact with C++.

I don't understand what you mean by "what type of calling, calling convention." I just basically need it to be like invoke except be able to take the first 2 arguments as the object and name of the DWORD pointer respectively, except with a dot instead of a comma in between the 2. Sort of like OA does:

OCall exObj::OBJECT.Function, <arguments>
Posted on 2007-08-24 00:51:00 by 16thfactor
Hi
Try with something like this

mCall macro Cast:req, Args:vararg
    local OName, MName, Pos1
    Pos1 InStr <Cast>, <.>
    if Pos1 ne 0
      OName SubStr <Cast>, 1, Pos1 - 1
      MName SubStr <Cast>, Pos1 + 1
    else
      .err <mCall format error. Dot-method missing.>
    endif
   
    mov eax, OName.MName
    invoke eax, ...
endm   


I just don't do it, and I noticed that OA32 requires quiet a bit of overhead.

At binary level OA32 has no gram of fat (if you know what you are doing)!

Regards,

Biterider
Posted on 2007-08-24 01:04:25 by Biterider
Ok well I took your code and tried it out. It didn't work (assembly errors) so I messed with it, copy pasting some code from random sources and got this:


mCall macro Cast:req, Args:vararg
    local OName, MName, Pos1
    Pos1 InStr <Cast>, <.>
    if Pos1 ne 0
      OName SubStr <Cast>, 1, Pos1 - 1
      MName SubStr <Cast>, Pos1 + 1
    else
      .err <mCall format error. Dot-method missing.>
    endif
    FOR var_, <Args>
        push var_
    ENDM
    mov eax, OName.MName
    lea edi, OName
    call eax
endm


This assembled, however, I now come to a complicated problem. Edi is loaded with the address of the object, how ever, when I did a function that retrieves one of the object's members it errors out saying that the variable is undefined. The easy solution to this would be to do "assume edit:ptr object" BUT I don't want to add another variable to the macro. Is there a MASM macro directive or something else that can retrieve the type of the object reffered to by OName? All it needs to do is retrieve the structure name from the object name. Should be possible... right?
Posted on 2007-08-24 13:38:47 by 16thfactor
16thfactor,

    I have been reading this thread to understand it as best as I can.  I don't know anything about the higher language concepts like OOP and inheritance.  I am strictly a low level guy.  However let me point out some things about MASM.  The INVOKE directive is not an "internal macro".    It can do things, and interacts with other directives (like PROC and PROTO for instance) in ways that a user written macro cannot do no matter how cleverly written.

    Your last posts asks if MASM can retrieve the "type of object" .  I would have so say no.  "Object" is high level language jargon, and is not found in MASM documentation.  I think that "object" means code and data to do a task.  Correct me if I am wrong.  MASM users would use the word subroutine or PROC.  When I program in MASM, I don't give a damn about what type of routine is is.  I just push the parameters or load the registers and INVOKE/CALL the routine. 

    I hope I have clarified some things about MASM, especially that it does not track with the features and item names of the high level languages.  Ratch

   
Posted on 2007-08-24 22:48:11 by Ratch

Well I don't really know the technicalities of C++ oop and how the compiler generates code, but I know what the virtual method table is and I don't plan on having one at all. This is what I need for OOP:

it is perfectly possible to use "invoke <struct>.<member>", (invoke <register> as well).

PROC@1 typedef proto stdcall :DWORD
PPROC@1 typedef ptr PROC@1
PROC@4 typedef proto stdcall :DWORD,:DWORD,:DWORD,:DWORD
PPROC@4 typedef ptr PROC@4

.code
custMessageBox proc hwnd:DWORD, text:DWORD, title_:DWORD, constant_:DWORD
  invoke MessageBoxA, hwnd, text, title_, constant_
  ret
custMessageBox endp

custExitProcess proc exitcode:DWORD
  invoke ExitProcess, exitcode
  ret
custExitProcess endp

OBJECT STRUCT
  variable1  dword  ?
  variable2  dword  ?
  function1  PPROC@4  offset custMessageBox
  function2  PPROC@1  offset custExitProcess
OBJECT ENDS

.data
exObj OBJECT <>
strText db "text",0
strTitle db "title",0

.code
start:
invoke exObj.function1, 0, addr strText, addr strTitle, 0
invoke exObj.function2, 0

infact this is how i handle the COM stuff
....
IMalloc struct
iIUnknown IUnknown <>
Alloc PPROC@2 ?
Realloc PPROC@3 ?
Free PPROC@2 ?
GetSize PPROC@2 ?
DidAlloc PPROC@2 ?
HeapMinimize PPROC@1 ?
IMalloc ends
PIMalloc typedef ptr IMalloc
....
mov ecx,pIMalloc
mov edx,
invoke .IMalloc.Alloc,ecx,sizeof CClassFactory

example attached
Attachments:
Posted on 2007-08-25 07:58:11 by drizz
Ratch,
I understand that. When I used "object", I meant in the sense of a structure. Can I, using MASM macro capabilities, retrieve the type of the declaration referenced by OName? For example, if I declared exObj as a EXAMPLE_OBJECT structure and used the mCall macro with parameters exObj.FunctionCall, could masm retrieve the EXAMPLE_OBJECT type in another macro?

Anyway, I think i'll just copy paste assume edi:ptr object_type at the beginning of every function. Less problems that way.

Drizz,
For some reason my MASM doesn't let me do that. Always says undefined procedure.
Posted on 2007-08-25 08:22:36 by 16thfactor

Drizz,
For some reason my MASM doesn't let me do that. Always says undefined procedure.

undefined procedure? i can't find any error, here is full source:
.686
.model flat,stdcall
option casemap:none
ExitProcess PROTO :DWORD
includelib kernel32.lib
MessageBoxA PROTO :DWORD,:DWORD,:DWORD,:DWORD
MessageBox equ <MessageBoxA>
includelib user32.lib

PROC@1 typedef proto stdcall :DWORD
PPROC@1 typedef ptr PROC@1
PROC@4 typedef proto stdcall :DWORD,:DWORD,:DWORD,:DWORD
PPROC@4 typedef ptr PROC@4

.code
custMessageBox proc hwnd:DWORD, text:DWORD, title_:DWORD, constant_:DWORD
  invoke MessageBoxA, hwnd, text, title_, constant_
  ret
custMessageBox endp

custExitProcess proc exitcode:DWORD
  invoke ExitProcess, exitcode
  ret
custExitProcess endp

OBJECT STRUCT
  variable1  dword  ?
  variable2  dword  ?
  function1  PPROC@4  offset custMessageBox
  function2  PPROC@1  offset custExitProcess
OBJECT ENDS

.data
exObj OBJECT <>
strText db "text",0
strTitle db "title",0

.code
start:
invoke exObj.function1, 0, addr strText, addr strTitle, 0
invoke exObj.function2, 0
end start

Posted on 2007-08-25 08:35:09 by drizz
Thanks, it worked. Interesting technique with the PROC@1 and the pointer to it. I have never tried declaring the variables with that type so I suppose thats what did it.
Posted on 2007-08-25 09:58:56 by 16thfactor
16thfactor,

    Here is the way I would do it.  Notice that I am an advocate of PROCless programming.  That saves having to use the EBP register in an already register starved CPU.  The down side is that you now have a dynamic stack frame.  I keep track of the stack frame with a STRUCT, which represents the parameters PUSHed onto the stack.  Notice the way I need to compensate the stack reference for every parameter pushed.  Another advantage to PROCless programming is that I don't need to PUSH all the parameters at the same time.  This means I can PUSH them when they become available, and not have to gather them together for a single PROC call.  Ratch

Attachments:
Posted on 2007-08-25 14:49:46 by Ratch
16thfactor,
you can read about it in masm programmer's guide (chapter 7, "Calling Procedures with INVOKE").
typedef is required for indirectly calling procedures with invoke.
Posted on 2007-08-25 14:51:06 by drizz
Sorry for the late reply.

Thank you Ratch, that helped a lot.

I'll get the chapter as soon as possible and read it. Thank you Drizz.
Posted on 2007-08-27 15:33:41 by 16thfactor