flat assembler
Message board for the users of flat assembler.

Index > Main > Compiling OO code

Author
Thread Post new topic Reply to topic
Plue



Joined: 15 Dec 2005
Posts: 151
Plue
I'm trying to write (or write a compiler that writes) object oriented code x86 assembly. Here's the basic concept:
Code:
CLASS ATESTCLASS
  INT myvariable
  FLOAT othervariable
  PROC myparam
    INT mylocalvar
  ENDPROC
ENDCLASS    


The point with object orientation is that you can create multiple instances of the class:
Code:
ATESTCLASS myfirstinstance
ATESTCLASS mysecondinstance    


Now here's the problem: How to do this? I can't simply write it like ordinary code and copy it to a newly allocated memory location as I create instances of the class since the code will still reference to the variables and procedures from where I copied it from.

And I can't allocate memory for it on the stack since I can many objects at once and creating mysecondinstance will mess up the stack for myfirstinstance (I can access variables in myfirstinstance before destroying mysecondinstance). Or won't it?

Any geniouses with a small hint on how to do this?

_________________
Roses are red
Violets are blue
Some poems rhyme
And some don't.
Post 13 Jan 2006, 12:25
View user's profile Send private message Reply with quote
Tomasz Grysztar



Joined: 16 Jun 2003
Posts: 7796
Location: Kraków, Poland
Tomasz Grysztar
One of the common solutions is to provide the "hidden" parameter to all the procedures declared as methods, which carries the pointer to object instance. This way you can have one common instance of the code, to access the variables of the object you use the pointer from hidden parameter, and when you call another method of the same object, you pass the same hidden parameter to it.
Post 13 Jan 2006, 12:54
View user's profile Send private message Visit poster's website Reply with quote
Big Red



Joined: 25 Feb 2005
Posts: 43
Big Red
Quote:
And I can't allocate memory for it on the stack since I can many objects at once and creating mysecondinstance will mess up the stack for myfirstinstance (I can access variables in myfirstinstance before destroying mysecondinstance). Or won't it?


You just have to set up a stack frame via the ebp register. For example...

SomeProc:
push ebp
mov ebp,esp
sub esp,(sizeof total local data you want to use, in bytes)
...

Here you can access your classes by indexing them with EBP. For example, if you have two local classes, and your classes follow the same size definition as STRUCT, you can write...

mov eax,[ebp-sizeof.ATESTCLASS-sizeof.ATESTCLASS+ATESTCLASS.SomeMember]
mov eax,[ebp-sizeof.ATESTCLASS+ATESTCLASS.SomeMember]

... and each will access the SomeMember member of the two different local classes and put it in eax (assuming it's a DWORD).

There are more efficient ways to do this with macros, but when you compile them, this is what they come down to.

Now, if you need to have a "this" pointer passed to this function (the "hidden" parameter Mr. Grysztar mentioned), typically, it would be the first parameter of the function, that is...

mov eax,[ebp+8]

... and eax will have your object. Some calling standards will pass the object in a register such as ecx. Anyhow, you can then access your "this" object using the same method as ebp addressing, only with positive indexes...

mov edx,[eax+ATESTCLASS.SomeMember]

... in fact, you can do this same for any instance passed as parameter, as long as your CLASS macro will allow addressing your class this way. As for the end of the procedure, you only need to top it off in the following fashion...

...
mov eax,(return value)
mov esp,ebp
pop ebp
ret (total size of parameters, in bytes)

edit: corrected last comment


Last edited by Big Red on 13 Jan 2006, 15:18; edited 2 times in total
Post 13 Jan 2006, 13:51
View user's profile Send private message Reply with quote
Fungos Bauux



Joined: 19 Jan 2005
Posts: 31
Location: CWB
Fungos Bauux
Plue, if you build a set of macros for emulating OO behavior, it can be very usefull for lots of ppl. Im new to fasm, but I can try help you to do something like this.
Post 13 Jan 2006, 14:54
View user's profile Send private message Visit poster's website MSN Messenger ICQ Number Reply with quote
Plue



Joined: 15 Dec 2005
Posts: 151
Plue
Stack frame, that's what I need to make. Thank you.
Post 13 Jan 2006, 15:12
View user's profile Send private message Reply with quote
Big Red



Joined: 25 Feb 2005
Posts: 43
Big Red
No problem. As for... (which I forgot to answer)

Quote:
Now here's the problem: How to do this? I can't simply write it like ordinary code and copy it to a newly allocated memory location as I create instances of the class since the code will still reference to the variables and procedures from where I copied it from.


If you have one class with only primitives that you've already allocated space for and initialized, copying them to another class won't copy references but the values themselves, so you won't be copying pointers. If you have pointers to other objects or memory spaces, then yes, you'll have the reference problem like in any other language. And if you lose memory pointers by overriding them, then you get memory leaks, just like in C.

You can probably get around the copying issue by emulating a constructor in an assembly function, which you can call anytime you need a local or global class of some sort. This way, if you have pointers to instances in your class, you'll create separate memory spaces for them, assuming it's what you need. For example, if you need to create one local instance, you could have...

SomeFunction:
(stack frame)
...

lea edx,[ebp-sizeof.ATESTCLASS]
stdcall ATESTCLASSConstructor,edx
(here you would have your local class pointed to by eax, which is probably
easier than using ebp)
...
(here you would put whatever code for your class)
mov edx,[eax+ATESTCLASS.SomeMember1]
...

(here, at the end, you would call your Destructor method for your local class to ensure all your sub-objects are un-allocated)
...
(stack frame)
ret (...)

ATESTCLASSConstructor: ; 1 parameter = memory space for instance
mov eax,[esp+4] ;eax = memory space for instance
mov DWORD [eax+ATESTCLASS.SomeMember1], ValueForSomeMember1
mov DWORD [eax+ATESTCLASS.SomeMember2], ValueForSomeMember2

invoke LocalAlloc,LPTR,(size of sub object)

mov DWORD [eax+ATESTCLASS.SubObject1],eax
sdtcall SubObject1Constructor,eax

mov eax,[esp+4] ;you can return the memory space again for easier access
ret 4

... If you needed SomeFunction to return a class that will be valid after the function call, you would simply need to allocate the memory using LocalAlloc or such and use the constructor on that memory space. You might also want a second constructor if you want the constructor itself to allocate the memory. If you needed to copy values from another class, you could do so after calling the constructor, so that you can access your sub-objects and copy the values in the sub-objects instead of copying their references and sharing them between parent instances (and possibly leaking memory). Even better, you could have your constructor accept parameters to assign as initial values to your class members, and pass the class members from the other objects you're copying from to your constructor to copy.

Anyhow, I'm very aware that this is very inefficient assembly coding, but if you're someone who's just looking to port over C++ code, then it's a good place to start. In fact, EVERYTHING I've written here is pretty much taken directly from disassemblies of MS Compiler-generated OOP code (which is pretty horrible, but has the basics OK). The point is... it just has to work before you can optimize it!
Post 13 Jan 2006, 16:03
View user's profile Send private message Reply with quote
Display posts from previous:
Post new topic Reply to topic

Jump to:  


< Last Thread | Next Thread >
Forum Rules:
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum
You cannot attach files in this forum
You can download files in this forum


Copyright © 1999-2020, Tomasz Grysztar. Also on GitHub, YouTube, Twitter.

Website powered by rwasa.