My eventual goal is to have one object type, say type "object" and that variable can be an integer, array, object made by a class, or even a function. This "object" data type will be a pointer and the data is accessed and mutated by assembly, through the use of memory addresses.

Is this possible?
Posted on 2009-05-27 21:23:58 by ITAmember
Of course. An example is the "VARIANT" type, used in VB - it contains info what it is (string, array, user-object, etc etc) and there are typelibs to describe a custom object.

JavaScript/php/perl interpreters also have that stuff.
It's simply low rate of operations, for the sake of easy coding.

keywords are: virtual dispatch tables, idispatch, COM
Posted on 2009-05-27 23:16:12 by Ultrano
I was thinking of a C struct that held a pointer to the actual value. This "value" would be a struct with function pointers and normal variables as members to simulate OOP. A different "value" would be defined for each data type and the pointer would change memory addresses every time a different value was assigned.

This leaves me with some interesting problems mainly what to do with the pointer that stores the memory address for the variable. I was thinking I could make this of type int and have it store the memory address. But then how would I manipulate it? Would I have to use assembly or could I use C?

Thanks in advance.
Posted on 2009-05-28 15:53:29 by ITAmember
Very interesting subject!  :) Nice link ultrano.
The very basic dynamic object type is a UNION + a field that indicates the type currently in use.
Posted on 2009-05-28 20:48:00 by ChaperonNoir
I'm going to ditch C++ entirely and simulate OOP with C structs. This should make assembly interfacing easier. Say I have this struct: (if my function member pointer syntax is wrong please forgive me as I don't remember the syntax well)

// "object" is my dynamic type
struct foo {
   // function pointer
   void (*func_pointer)(object, object, etc);
   object some_data_member;

If I had a true dynamic language then I could add data and function members to this struct. I'm thinking I can just solve this by making two lists of type "object", one for function members and one for data members. This should work fine right?

Back to assembly, say "object" is defined by this struct:

typedef struct{
   // a variable of type "int" that holds the memory address of the current object
   int memory_pointer;
   // the type of object, stored as an "int" to avoid very slow string comparison
   int type;
} object;

and say memory_pointer stores the address of an instance of this struct (for this example, it could hold the address of any supported type):

typedef struct{
   // this is a struct that defines the dynamic type of "int" and has some simulated OOP
   // this member stores the actual number
   int value;
   // store a function or two?
   void (*func_pointer)(object, object, etc) = some_func;
} dint;

Now say I have this code:

object some_name;
some_name = <a dint instance>; // the text in the angle brackets is not code

that is an over-simplification as I would have to type lots of syntax but you get the idea. The question is, how to I use assembly to call some_func with just a memory address to the struct instance location?

One quick note, my goal is to be able to translate the python programming language into C. This results in two steps, making a dynamic type library (which I'm working on now) and the actual translator. Because it will be translated like this complicated syntax is no problem.

Thanks in advance. (once again)
Posted on 2009-05-28 21:25:56 by ITAmember
The question is, how to I use assembly to call some_func with just a memory address to the struct instance location?

mov eax,pDint
call dword ptr
; add esp,.. optional, if you passed args

Interfacing asm is easy with VC++ in C++ mode. Using basic COM style for the classes is also easy. Made even easier by ATC, search for "endclass" here.

There're also macros to make the asm reflection of structs easier to read:

; Examples:
; MyStruct struct
; pFunc1 IFUNC(x,y,z)
; pFunc2 IFUNC(tx:real8,ty,vx:real8)
; MyStruct ends
; SomeProc proc
; local pFunc4:IFUNCVAR(x,y,z)
; local pFunc5:IFUNCVAR(arg1:real8,arg2:real8)
; local obj1:MyStruct
; ...
; invoke pFunc4,1,2,3
; invoke obj1.pFunc1,7,8,9
; lea ecx,obj1
; invoke .MyStruct.pFunc1,7,8,9
; ret
; SomeProc endp

The sources for some of the things are at  (address uptime not guaranteed). Cut/paste on demand.
Posted on 2009-05-29 04:16:19 by Ultrano
I'm really interested in interfacing with C++ code. Right now, I'm studying C++ asm listings to get it to work.
Do you have that class and endclass macro handy ultrano? I didn't find them in your inc file.
Posted on 2009-05-29 10:42:41 by ChaperonNoir
Ah yes, forgot to upload it:
Posted on 2009-05-29 11:42:54 by Ultrano
Posted on 2009-05-29 15:57:45 by ChaperonNoir
Better check out ObjAsm32 also.
Ultrano, didn't you make ATC closed source?
Posted on 2009-05-30 03:06:16 by Homer
:D how can a macro-lib be closed-source?
It's just that the non-oop stuff were released bundled with the several ATC classes just as .lib . Though, most of those classes were uploaded separately here beforehand.
Posted on 2009-05-30 08:29:08 by Ultrano
I had a deep look at Ultrano's macro lib and I must say that I didn't know that the masm preprocessor was that powerful.
It does a lot more things than the C preprocessor! It's very amazing.
Posted on 2009-05-30 10:26:30 by ChaperonNoir
Well, I seem to remember you telling me that ATC was no longer public, perhaps I misunderstood you when you told me that.
Can a macro lib be closed source?
Is a macro sourcecode?
In regards to examples of closed source macro libs, ask one of the boys for which I developed with Bryant as a bit of a lark. It allows you to build executables which contain NO import table, and whose code is totally pc-relative and can execute at any address (or in another process).
Posted on 2009-05-30 13:35:51 by Homer
Ah, ATC2 was simply silently updated, I didn't post a notification because no-one requested it.
Meanwhile, for some time my (which is tightly related to ATC2) was provided without source for the defined protos there.
Posted on 2009-05-30 14:02:07 by Ultrano
TASM supports "OOP" directly. Unfortunatly it isn't well explained.


;declare a main object with two virtual functions and two variables

object_1 struct method{
virtual vfunc_a,stdcall: dword, params:dword:?
virtual vfunc_b,c: dword, param:dword
var_a byte ?
var_b word ?

;declare an inherited object and add another virtual function and a variable,
; (assume "myfunc_..." are existing somewhere in the source)

object_2 struct object_1 method{
virtual vfunc_a:dword=myfunc_a
virtual vfunc_b:dword=myfunc_b
virtual vfunc_c:dword=myfunc_c
var_c dword ?

;let TASM build the virtual-functions-table
tblinst ;(must follow each "struct method" declaration if virtual functions need to
; be initialized)

;initialize the object with the virtual-function-pointer
;and pre-load the variables
inst_object_2 object_2{@mptr_object_2=@tableaddr_object_2, var_a=0ffh, var_b=1234h, var_c=11223344h}

;invoke a virtual function and commit necessary parameters with STDCALL convention

call inst_object_2 method object_2:vfunc_a uses ds ecx, offset xyz, 1, 2, 3

;ECX points to "SELF", so we can access the variables from within the virtual functions:

mov eax,.object_2.var_c
add al,.object_2.var_a
add ax,.object_2.var_b

Posted on 2009-05-31 04:49:24 by TasmDev
I think I have the basic structure of how I'm going to implement this stuff. My dynamic object type will really just be a normal int that holds a memory address, defined like this:

typedef int object;

This memory address will point to a certain data type defined by a struct, here's how I would define the dynamic int type:

typedef struct
    linked_list data; /*stores all the data and function pointer members as memory addresses*/
    int type; /*stores the type, each type is given an integer identifier*/
    int data; /*each object type will have the data member that stores the actual data*/
} dint;
Posted on 2009-06-04 11:08:28 by ITAmember
kinda like a VARIANT eh
Posted on 2009-06-04 11:52:51 by Homer
Yeah, kind of like variant. I've been giving it some more thought and I've decided the linked list in each dynamic type struct is unnecessary. Since this is going to be a library that is used by a "compiler" the compiler will know ahead of time which data members to add to the struct when it's generated.

Since every variable is going to be an int holding a memory address all operations are going to be handled by functions written with inline assembly. I'm hoping these are all very simple functions, like  > 5 lines, which could be possible considering how simple some of these operations are. Would it be a good idea to write these functions as argument taking preprocessor macros? Here's an example of how a normal addition operation would be translated into these functions:

/*normal operation*/
a = b + c;
/*translated by compiler*/
assign(a, add(b, c));

Since everything is going to be a function it would seem that the function call overhead would really slow down the program, on the other hand that many macros could make the code very large. That's why I'm asking this.

I have a real question now, here's a review of my declaration code:

typedef int object;

typedef struct
   object some_data_member;
   object some_data_member2;
   int type; /*stores the type, each type is given an integer identifier*/
   int data; /*each object type will have the data member that stores the actual data*/
} dint;

Say I have variable "a" of type "object". I want to change "a"s member in the struct to 1, how would I access and mutate the member given the memory address to this struct location? I don't really know how C stores the data members in a struct. :sad:

Really sorry if you already answered that, this looks like what I'm looking for

The question is, how to I use assembly to call some_func with just a memory address to the struct instance location?

mov eax,pDint
call dword ptr
; add esp,.. optional, if you passed args

But I don't really understand how each data member is stored. :sad:
Posted on 2009-06-07 21:59:53 by ITAmember
The data is laid out inside the struct in the same order it was defined.
Whether there is any PADDING between its member fields or not depends on the datatypes involved. I believe the default behaviour is that all fields are aligned to 16 byte boundaries, and so therefore the entire struct always ends on a 16 byte boundary too.
That means that single CHAR member will be followed by one byte of padding, but SHORT or LONG members don't need any padding at all.
Posted on 2009-06-08 00:08:40 by Homer
You can investigate the location of each structure data member with a debugger or with some printf work to determine the proper offsets. I think that's what you meant?
Posted on 2009-06-08 01:09:57 by ChaperonNoir