NASM - The Netwide Assembler

NASM Forum => Example Code => Topic started by: Bryant Keller on July 12, 2010, 05:14:59 AM

Title: NASM OOP - Work In Progress
Post by: Bryant Keller on July 12, 2010, 05:14:59 AM
Below is some sample code to demonstrate what it can do so far, nothing overly special. 'virtual' methods can be overloaded whereas 'static' methods cannot. That might change as I'm thinking of making a change to the syntax now that the core is working fairly well.

Even though I mention it in the source, I want to go ahead and thank Ultrano and Homer for their help with this as I wouldn't have ever gotten this far without their help.

Code: [Select]
BITS 32

%define SINGLE_FILE_BUILD
%include "objects.inc"

EXTERN puts
EXTERN printf

CLASS CTest
virtual method, Say
static method, CTest
static method, Hello
static method, GoodBye
static dword, m_who
ENDCLASS

CLASS CHaha, CTest
ENDCLASS

CLASS CBlah, CHaha
virtual method, Say
static method, CBlah
static method, Hi
ENDCLASS

CLASS MYA
static method, Say
static method, @MYA
ENDCLASS

SECTION .text

MYA_@MYA:
%push
%stacksize flat
%arg this:DWORD

push ebp
mov ebp, esp
push dword strAuthor
push dword strGoodBye
call printf
add esp, (4 * 2)
leave
ret

%pop

MYA_Say:
%push
%stacksize flat
%arg this:DWORD, msg:DWORD

push ebp
mov ebp, esp
push dword [msg]
call puts
add esp, 4
leave
ret

%pop

CBlah_CBlah:
%push
%stacksize flat
%arg this:DWORD

push ebp
mov ebp, esp
mov ecx, [this]
mov edx, strAuthor
mov [ecx + CBlah.m_who], edx
leave
ret

%pop

CBlah_Hi:
%push
%stacksize flat
%arg this:DWORD

push ebp
mov ebp, esp
mov ecx, [this]
push dword [ecx + CBlah.m_who]
push dword strHello
call printf
add esp, 8
leave
ret

%pop

CBlah_Say:
%push
%stacksize flat
%arg this:DWORD, msg:DWORD

push ebp
mov ebp, esp
mov ecx, [this]
push dword [msg]
push dword strCBS
call printf
add esp, 8
leave
ret

%pop


CTest_CTest:
%push
%stacksize flat
%arg this:DWORD, msg:DWORD

push ebp
mov ebp, esp
mov ecx, [this]
mov edx, [msg]
mov [ecx + CTest.m_who], edx
leave
ret

%pop

CTest_Say:
%push
%stacksize flat
%arg this:DWORD, msg:DWORD

push ebp
mov ebp, esp
mov ecx, [this]
push dword [msg]
call puts
add esp, 4
leave
ret

%pop

CTest_Hello:
%push
%stacksize flat
%arg this:DWORD

push ebp
mov ebp, esp
mov ecx, [this]
push dword [ecx + CTest.m_who]
push dword strHello
call printf
add esp, 8
leave
ret

%pop

CTest_GoodBye:
%push
%stacksize flat
%arg this:DWORD

push ebp
mov ebp, esp
mov ecx, [this]
push dword [ecx + CTest.m_who]
push dword strGoodBye
call printf
add esp, 8
leave
ret

%pop

GLOBAL main
main:
push ebp
mov ebp, esp

new CTest, dword strAuthor
mov [pObject], eax

vcall [pObject], CTest,Say, strTitle
mcall [pObject], CTest,Hello
mcall [pObject], CTest,GoodBye

delete [pObject]

new CBlah
mov [pObject], eax

mcall [pObject], CBlah,Hi
vcall [pObject], CBlah,Say, strTitle

delete [pObject]

new MYA
mov [pObject], eax
mcall [pObject], MYA,Say, strTitle
delete [pObject]

xor eax, eax
leave
ret

SECTION .data
pObject DD 0 ;; Our Object Pointer

strHello DB "Hello, %s", 10, 0
strGoodBye DB "GoodBye, %s", 10, 0
strTitle DB "NASM OOP Demo", 0
strAuthor DB "Bryant Keller", 0
strCBS DB "CBS: %s", 10, 0
Title: Re: NASM OOP - Work In Progress
Post by: Frank Kotler on July 12, 2010, 06:44:04 AM
Thanks, Bryant!

Already, I'm enlightened. I see that this has inserted some "ret 4"s behind my back - much like that accursed "XCB" library that Brainiac and I were struggling with. I suspected that must be "OOP".

The purpose of this is, like, job security, right?

Best,
Frank

Title: Re: NASM OOP - Work In Progress
Post by: Bryant Keller on July 12, 2010, 08:00:12 AM
Thanks, Bryant!

I was happy to do this one. It's been on my todo-list for a long time and I've procrastinated on it for quite long enough. I'll continue to work on it (add features, fix things) as time permits. The direct download to constantly updated file is http://assembly.ath.cx/code/objects.inc but I'll attempt to update this attachment as well.

Already, I'm enlightened. I see that this has inserted some "ret 4"s behind my back - much like that accursed "XCB" library that Brainiac and I were struggling with. I suspected that must be "OOP".

That it has, and I might actually create a toggle to disable this "feature" because personally I don't like it either. You see, both VCALL and MCALL put the object pointer in EDX before it's pushed onto the stack so you could technically just use EDX directly and avoid the "[this]" argument and subsequent stack clean-up. However, for the sake of portability with C++ I wrote this initial release to push the object pointer onto the stack. C++ does this as a convention and so did I. Like I was saying, I might add a toggle of some kind that enables/disables "CPP_COMPAT" or something along those lines. But for now I thought it would be safer just show the example using the stack and avoid the argument over which register should be used.. keep in mind, VCALL and MCALL destroy EDX.

The purpose of this is, like, job security, right?

That depends on how well things go from here. I have a lot of optimizations and a few "ideas" I'd like to implement (like abstract classes) that I've not completely figured out how I'm going to do it. Once this core objects.inc file is done and tested, there are several people who have been on my case to get this thing up and running in order to allow for their own larger scale object oriented projects. In which case I might assist in the porting of these projects.

As for job security, not even. For objects.inc to make your life that much easier you would need to build a fairly large framework over top of it, and for that I'll probably need to figure out this abstract classes idea.
Title: Re: NASM OOP - Work In Progress
Post by: Bryant Keller on July 12, 2010, 10:53:49 PM
In an attempt to keep to my word about keeping this copy current, I've updated the above attachment and example to reflect my most recent work.

Change 1 - BugFix(001)
Okay, so I'm not perfect. lol It's not a really major bug (no security problem or anything) it's just something that creeped up because of my personal coding style. When I do OOP development, I put classes in a file by themselves and link the resulting .OBJ files together. Because of this tendency, when I tested my objects.inc I didn't check to see if two classes with methods/members of the same name might cause a conflict, they did. That has been fixed in my first official bugfix. :)

Change 2 - Ctor/Dtor Generator
Having the user be forced to write a Ctor/Dtor for every single class just seems a bit excessive.. So I've come up with a much simpler solution which mimics the way that C++ does. Unless the user declares a Ctor/Dtor, then you don't have to worry about defining one. This will reduce the overall executable size dramatically from the first version of objects.inc and I'm really happy about how this feature has turned out.
Title: Re: NASM OOP - Work In Progress
Post by: Frank Kotler on July 13, 2010, 12:05:14 AM
"first0" is with the original "objects.inc" (which I did not keep a copy of, more the fool). "first" is with the current "objects.inc".

Code: [Select]
-rwxr-xr-x 1 fbk users 10891 2010-07-12 19:53 first*
-rwxr-xr-x 1 fbk users 10766 2010-07-12 19:52 first0*

Seems to have increased the file size, though not dramatically. Did the "example" change, too? Maybe that's what I did wrong...

Best,
Frank

Title: Re: NASM OOP - Work In Progress
Post by: Bryant Keller on July 13, 2010, 12:26:12 AM
First, I've just re-updated the code again. I didn't think anyone would check it out so soon but I did some last minute clean-up to the Ctor and I changed the fallback-Dtor design to a single test in the delete macro which also seems to help me sort out bugs a little better because if a Dtor never initializes for some reason or another you would otherwise get thrown off into 0x00000000, this way that doesn't happen.

"first0" is with the original "objects.inc" (which I did not keep a copy of, more the fool). "first" is with the current "objects.inc".

Code: [Select]
-rwxr-xr-x 1 fbk users 10891 2010-07-12 19:53 first*
-rwxr-xr-x 1 fbk users 10766 2010-07-12 19:52 first0*

Seems to have increased the file size, though not dramatically. Did the "example" change, too? Maybe that's what I did wrong...

Best,
Frank

Yea, with each objects.inc I post I basically just post the objtest.asm file which I have been using to test the capabilities (to make sure what I'm wanting to work actually works). So with each release the example does include quite a bit more code. In this most recent one, there are a full two extra procedures added so of course the size will be larger. If you are looking to do a side-by-side comparison, you'll need the older objects.inc. Here is the first demo I posted:

Code: [Select]
BITS 32

%include "objects.inc"

EXTERN puts
EXTERN printf

CLASS CTest
virtual method, Say
static method, Hello
static method, GoodBye
static dword, m_who
ENDCLASS

SECTION .text

CTest_CTest:
; this := ebp + 8
; msg := ebp + 12
push ebp
mov ebp, esp

mov ecx, [ebp + 8]
mov edx, [ebp + 12]
mov [ecx + CTest.m_who], edx

leave
ret 8

CTest_@CTest:
push ebp
mov ebp, esp
;; Nothing really left to do here...
leave
ret 4

CTest_Say:
; this := ebp + 8
; msg := ebp + 12
push ebp
mov ebp, esp
mov ebx, [ebp + 12]
push ebx
call puts
add esp, 4
leave
ret 8

CTest_Hello:
push ebp
mov ebp, esp
push dword [ecx + CTest.m_who]
push dword strHello
call print
add esp,
leave
ret 4

CTest_GoodBye:
push ebp
mov ebp, esp
push dword [ecx + CTest.m_who]
push dword strGoodBye
call printf
add esp, 8
leave
ret 4

GLOBAL main
main:
push ebp
mov ebp, esp

new CTest, dword strAuthor
mov [pObject], eax

vcall [pObject], CTest,Say, strTitle
mcall [pObject], CTest.Hello
mcall [pObject], CTest.GoodBye

delete [pObject]

xor eax, eax
leave
ret

SECTION .data
pObject DD 0 ;; Our Object Pointer

strHello DB "Hello, %s", 10, 0
strGoodBye DB "GoodBye, %s", 10, 0
strTitle DB "NASM OOP Demo", 0
strAuthor DB "Bryant Keller", 0

Then use this new one and test it against this version:

Code: [Select]
BITS 32

%include "objects.inc"

EXTERN puts
EXTERN printf

CLASS CTest
virtual method, Say
static method, CTest ;; Ctor
static method, Hello
static method, GoodBye
static dword, m_who
ENDCLASS

SECTION .text

CTest_CTest:
; this := ebp + 8
; msg := ebp + 12
push ebp
mov ebp, esp

mov ecx, [ebp + 8]
mov edx, [ebp + 12]
mov [ecx + CTest.m_who], edx

leave
ret 8

CTest_Say:
; this := ebp + 8
; msg := ebp + 12
push ebp
mov ebp, esp
mov ebx, [ebp + 12]
push ebx
call puts
add esp, 4
leave
ret 8

CTest_Hello:
push ebp
mov ebp, esp
push dword [ecx + CTest.m_who]
push dword strHello
call print
add esp,
leave
ret 4

CTest_GoodBye:
push ebp
mov ebp, esp
push dword [ecx + CTest.m_who]
push dword strGoodBye
call printf
add esp, 8
leave
ret 4

GLOBAL main
main:
push ebp
mov ebp, esp

new CTest, dword strAuthor
mov [pObject], eax

vcall [pObject], CTest,Say, strTitle
mcall [pObject], CTest.Hello
mcall [pObject], CTest.GoodBye

delete [pObject]

xor eax, eax
leave
ret

SECTION .data
pObject DD 0 ;; Our Object Pointer

strHello DB "Hello, %s", 10, 0
strGoodBye DB "GoodBye, %s", 10, 0
strTitle DB "NASM OOP Demo", 0
strAuthor DB "Bryant Keller", 0

These two programs should essentially do the same thing but the newer one does a lot more stuff compile-time rather than run-time. That's really all I'm trying to do right now is find a decent balance between compile-time code and run-time code. My VERY first implementation, almost the entire object was generated at run-time, which was horrible. Now I have almost everything generated at compile-time, which I really like. :)
Title: Re: NASM OOP - Work In Progress
Post by: c051n3 on July 13, 2010, 01:16:05 AM
This looks like something I've been looking for.  I have a few questions Bryant:

How do you plan on handling scope visibility of class methods and member variables (ie: public, private, protected)?

Are you going to implement structed exception handling SEH as well?

Finally, I posted a thread elsewhere asking about a 64-bit framework.  Is this in your project plan?

I realize this is a work in progress and I would be more than happy to help.
Title: Re: NASM OOP - Work In Progress
Post by: Frank Kotler on July 13, 2010, 01:20:24 AM
Getting errors in your latest example, which I called "second.asm". Maybe I'd better wait for a stable version... Thanks Bryant!

Best,
Frank

Title: Re: NASM OOP - Work In Progress
Post by: Bryant Keller on July 13, 2010, 02:56:41 AM
How do you plan on handling scope visibility of class methods and member variables (ie: public, private, protected)?

I haven't really given it much thought actually. Public/private/protected are concepts which are probably going to have to be left up to the programmer. I can't really think of a way to do something like that using macros/equates, for the most part the code generated for one visibility is no different than the code generated for another, so at the moment I don't really see a reason for adding visibility support. It would be like trying to add namespace support, it just doesn't really seem important to me at the assembler level.

Are you going to implement structed exception handling SEH as well?

Probably not. At least not as part of the core of the project. I want to keep the core as "raw" as possible to allow for it to be easily extended to different platforms. I think implementation of SEH could be done as a separate include as part of a larger framework.

Finally, I posted a thread elsewhere asking about a 64-bit framework.  Is this in your project plan?

Actually yes. If you look in the header of the objects.inc file, you will see my TODO list. In that list one of my objectives is to abstract away 32/64-bit from the back-end. Eventually I would like for this to work across 16/32/64-bit DOS/Win/Linux but that will be quite some time away. Even still, it is on my todo list.

I realize this is a work in progress and I would be more than happy to help.

I'll keep that in mind. Thanks!

Getting errors in your latest example, which I called "second.asm". Maybe I'd better wait for a stable version... Thanks Bryant!

Best,
Frank

Heh, that's not a problem with the objects.inc, that's a problem with the copy I had on backup. I fixed it and double checked it. Sorry about that. lol

Code: [Select]
BITS 32

%include "objects.inc"

EXTERN puts
EXTERN printf

CLASS CTest
virtual method, Say
static method, CTest ;; Ctor
static method, Hello
static method, GoodBye
static dword, m_who
ENDCLASS

SECTION .text

CTest_CTest:
; this := ebp + 8
; msg := ebp + 12
push ebp
mov ebp, esp
mov ecx, [ebp + 8]
mov edx, [ebp + 12]
mov [ecx + CTest.m_who], edx
leave
ret 8

CTest_Say:
; this := ebp + 8
; msg := ebp + 12
push ebp
mov ebp, esp
mov ebx, [ebp + 12]
push ebx
call puts
add esp, 4
leave
ret 8

CTest_Hello:
; this := ebp + 8
push ebp
mov ebp, esp
mov ecx, [ebp + 8]
push dword [ecx + CTest.m_who]
push dword strHello
call printf
add esp, 8
leave
ret 4

CTest_GoodBye:
push ebp
mov ebp, esp
mov ecx, [ebp + 8]
push dword [ecx + CTest.m_who]
push dword strGoodBye
call printf
add esp, 8
leave
ret 4

GLOBAL main
main:
push ebp
mov ebp, esp

new CTest, dword strAuthor
mov [pObject], eax

vcall [pObject], CTest,Say, strTitle
mcall [pObject], CTest,Hello
mcall [pObject], CTest,GoodBye

delete [pObject]

xor eax, eax
leave
ret

SECTION .data
pObject DD 0 ;; Our Object Pointer

strHello DB "Hello, %s", 10, 0
strGoodBye DB "GoodBye, %s", 10, 0
strTitle DB "NASM OOP Demo", 0
strAuthor DB "Bryant Keller", 0
Title: Re: NASM OOP - Work In Progress
Post by: Frank Kotler on July 13, 2010, 08:04:29 AM
Okay, that works and is smaller.

You might want to package up "working pairs" of objects.inc and its test case(s). Having examples between code tags is good for looking at and discussing, but kind of a PITA to cut-and-paste it into a file to try... Just a thought...

I think there are 2 kinds of people in the world (10, if you count 'em in binary) - those who "get" OOP, and those who never will. I think I fall into the second category.

Best,
Frank

Title: Re: NASM OOP - Work In Progress
Post by: c051n3 on July 13, 2010, 06:23:09 PM
How do you plan on handling scope visibility of class methods and member variables (ie: public, private, protected)?
I haven't really given it much thought actually. Public/private/protected are concepts which are probably going to have to be left up to the programmer. I can't really think of a way to do something like that using macros/equates, for the most part the code generated for one visibility is no different than the code generated for another, so at the moment I don't really see a reason for adding visibility support. It would be like trying to add namespace support, it just doesn't really seem important to me at the assembler level.

I have some minimalistic working code that currently permits class methods and vars defined with the public attribute to be global. Class methods and vars not marked as such are currently private and not extern.
For example:
Code: [Select]
CLASS CTest public, myclass
     static public, method, hello
     static private, dword, m_who
ENDCLASS

This would enable the hello method to be accessible to external routines
while the m_who variable would not. (eg: in the static macro):
 
Code: [Select]
%ifidn(%1==public)
global %2
 %endif

Of course this requires that all class methods and variables be defined using the public/private attributes when defining a class but my personal opinion is that anyone familiar with OOP principles already expects this. This will especially come into play once you get to inheritance and method overloading/overriding.

Are you going to implement structed exception handling SEH as well?
Probably not. At least not as part of the core of the project. I want to keep the core as "raw" as possible to allow for it to be easily extended to different platforms. I think implementation of SEH could be done as a separate include as part of a larger framework.

Ok.  Then perhaps this will give me something to do in my free time once you've finished the core code ;D

Finally, I posted a thread elsewhere asking about a 64-bit framework.  Is this in your project plan?
Actually yes. If you look in the header of the objects.inc file, you will see my TODO list. In that list one of my objectives is to abstract away 32/64-bit from the back-end. Eventually I would like for this to work across 16/32/64-bit DOS/Win/Linux but that will be quite some time away. Even still, it is on my todo list.

This is a big TODO, especially since Win64 now uses fastcall convention (RCX, RDX, R8, and R9 for the first 4 parameters)
and the method caller is responsible for cleaning up the now 16 byte aligned stack. I'm looking forward to how you implement this.

Title: Re: NASM OOP - Work In Progress
Post by: Bryant Keller on July 13, 2010, 08:15:58 PM
I have some minimalistic working code that currently permits class methods and vars defined with the public attribute to be global. Class methods and vars not marked as such are currently private and not extern.
For example:
Code: [Select]
CLASS CTest public, myclass
     static public, method, hello
     static private, dword, m_who
ENDCLASS

This would enable the hello method to be accessible to external routines
while the m_who variable would not. (eg: in the static macro):
 
Code: [Select]
%ifidn(%1==public)
global %2
 %endif

Of course this requires that all class methods and variables be defined using the public/private attributes when defining a class but my personal opinion is that anyone familiar with OOP principles already expects this. This will especially come into play once you get to inheritance and method overloading/overriding.

Check out http://assembly.ath.cx/weblog/news.php?id=6 ;)

I actually posted this after a conversation I had with a friend earlier today, it's how I intend to deal with multi-file layouts like you are describing.

Ok.  Then perhaps this will give me something to do in my free time once you've finished the core code ;D

Have at it man! In fact, I've been talked out of changing the syntax so if you intend doing anything I can pretty much assure you that the syntax I'm using isn't going to change much. When I implement abstract classes they will look something like this:

Code: [Select]
CLASS ASimpleList
abstract method, Next
abstract method, Last
abstract method, For_Each
abstract dword, ptrData
ENDCLASS

This is a big TODO, especially since Win64 now uses fastcall convention (RCX, RDX, R8, and R9 for the first 4 parameters)
and the method caller is responsible for cleaning up the now 16 byte aligned stack. I'm looking forward to how you implement this.

Actually, this really won't be that big of a deal. 16-byte alignment is easy, just calculate the amount of stack space used by the arguments and then use (((%{$stksz} % 16) + %{$stksz}) to align the stack before and after call. As for 64-bit Fastcall itself, that's already been implemented in Keith and my other project NASMX. Also, when that time comes, I can just pass the object pointer through RBX or RAX. ;)
Title: Re: NASM OOP - Work In Progress
Post by: c051n3 on July 14, 2010, 02:21:27 AM
Bryant,
You may appreciate the elegance of the following solution when including your class definitions .inc file:

The following macro snippet contained in objects.inc
Code: [Select]
%macro import 1
; when we are importing a class definition we do not build
; the vtables and memory space, only define the class characteristics
%define %$_classctx.importing 1
%include %[%1]
%undef %$_classctx.importing
%endmacro ; import

Then simply
Code: [Select]
   import myobject

from the .asm file you want to include the class definitions into.

Now you won't even need the following in your object's .inc file:
Code: [Select]
%ifndef MYOBJECT_METHODS
EXTERN myObject_Hello
EXTERN myObject_Goodbye
%else
GLOBAL myObject_Hello
GLOBAL myObject_Goodbye
%endif

because in your CLASS and METHOD macro you'll know whether you are defining or instantiating, thus relieving the programmer from having to ensure everything is extern'd or global'd properly.

This, along with the keywords public and private, is how I am handling visibility of class methods and vars between multiple files thus far.

It's a shame you've been talked out of syntax change.  I want to be in on the next conversation! ;)

Title: Re: NASM OOP - Work In Progress
Post by: Bryant Keller on July 14, 2010, 02:56:07 AM
my original idea for a syntax change was to have something like:
Code: [Select]
CLASS Blah
virtual method, a
virtual method, b
method First
method Second
variable ddVar, DWORD
ENDCLASS

But it was suggested that I should keep the current syntax because it's actually kinda similar to that of OA32 already which uses StaticMethod, VirtualMethod, AbstractMethod macros to define it's methods. This will make it easier for users with experience in MASM/OA32.
Title: Re: NASM OOP - Work In Progress
Post by: c051n3 on July 14, 2010, 05:32:37 AM
But it was suggested that I should keep the current syntax because it's actually kinda similar to that of OA32 already which uses StaticMethod, VirtualMethod, AbstractMethod macros to define it's methods. This will make it easier for users with experience in MASM/OA32.

Is your plan to make a nasm version compatible with OA32? I can see some benefits in this from both windows, linux, and OS X users. A portable nasm oop framework to create applications for all environments. A nice goal provided we don't become too constrained by OA32's model.
Title: Re: NASM OOP - Work In Progress
Post by: Bryant Keller on July 14, 2010, 09:39:11 AM
I'm not really trying for anything 1 to 1. But since it's the most used assembly/OOP implementation, it's good to try to pair up with it whenever possible to make things easier for users. Being realistic, however, I don't expect objects.inc to ever be anything as grand as OA32 nor would I even try.
Title: Re: NASM OOP - Work In Progress
Post by: c051n3 on July 14, 2010, 03:07:45 PM
OK.  What are your thoughts on the following?
Code: [Select]
;all classes inherit from CRootObject
;a defined class without a specified parent class
;automatically inherits from CRootObject
;thus the following two lines are effectively identical
;   class CMyClass
;   class CMyClass, CRootObject
;
class CAppMutex
; scope is default public until private keyword encountered
     static qword, m_tid
private
; variables and methods from this point are private to the class
     static lptr, m_mutex
     static qword, m_refcount
public
; variables and methods from this point are publicly accessible
     static method, lock
; multiple method signatures
     static method, lock, qword:timeout
     static method, lock, qword:timeout, qword:tid
     static method, unlock
     static method, isLocked
endclass

I'm assuming that macro pair method/endmethod, when invoked in the user source, will automatically handle the 32/64 bit differences, name mangling, and calling convention issues based upon __OUTPUT_FORMAT__ correct?
Title: Re: NASM OOP - Work In Progress
Post by: Bryant Keller on July 14, 2010, 05:37:27 PM
Sure, I have quite a few thoughts on the above code.

First, the CRootObject (or CPrimer as it's probably going to be called if I decide to implement it) has already been put into the discussion by Homer. I'm not a fan on this method, I like how things work internally already but he also has suggested that the base object that everything inherits from is more popular. I'll leave that as a suggestion under consideration but I'm still not convinced that it won't just be a whole lot of redesigning for very little (if any) benefit.

As far as private/public, I still don't really see the point. Keep in mind that our class is just being allocated on the heap. Other than our VMT/VDT, everything else exists within that heap space. So it's not like we can actually block anything from having access to that memory, this isn't a compiler where I can do syntactical checks to make sure someone doesn't access the variables, it's just a macro set.

Multiple method signatures will not be implemented, nor will any method/endmethod macros. At least not by me. I did my HL stuff when I worked on NASMX, I might see if Keith wants to extend NASMX to support methods and objects.inc which would then probably support these features fairly easily, but I have no intention of doing it. Multiple method signatures can be implemented using the "Win32-ish" style of naming methods where you have the <MethodName>@<StackSize>. If you want to extend objects.inc to support this feature, you are more than welcome to. But I see no reason to.

Remember, my goal is "raw". I want objects.inc to be efficient and stable. I'm not really concerned about creating a feature rich OOP framework, I don't use OOP that much. But when I do use it, I would like it to be reliable. That's really what I'm aiming for. That's why I still haven't implemented icall (Interface Call [for COM]) and acall (Ancestor Call), because these are things which target a more specific need.

I have, however, made use of your import macro (renamed it to "use" to avoid conflicts with the IMPORT directive -- and "use" kinda reminds me of PERL). This does make things a great deal better under multi-file builds, however single file builds wouldn't work. To correct this, I set it so now users must %define SINGLE_FILE_BUILD before they include if they wish to use the class in a single file build environment. I don't see this as a problem since classes by design are meant to be used in multiple files. I'll update the mft.tar.gz on the server after I update the objects.inc here on the forum. :)
Title: Re: NASM OOP - Work In Progress
Post by: c051n3 on July 14, 2010, 09:43:40 PM
Ok. Hopefully Keith will decide to extend it. Not sure if he would design in cross-platform support as that is not nasmx's raison d'etre. But it would be nice if the core itself were modified to enable a framework to be built that would compile on both Windows and Linux 32 and 64 bit systems. Having the core kept separate from nasmx would allow this.

If not, then I will be extending it in order to provide the necessary foundation to truly support a portable oop framework ( which has been my own personal goal all along ) and you probably wouldn't recognize it when I'm done with it. ;)
Title: Re: NASM OOP - Work In Progress
Post by: Bryant Keller on July 14, 2010, 11:02:58 PM
Ok. Hopefully Keith will decide to extend it. Not sure if he would design in cross-platform support as that is not nasmx's raison d'etre. But it would be nice if the core itself were modified to enable a framework to be built that would compile on both Windows and Linux 32 and 64 bit systems. Having the core kept separate from nasmx would allow this.

You're kidding right? Have you actually used NASMX? Cross platform support was always taken into consideration, and with great pains, since it's earliest versions. Currently it supports Windows, Linux, XBox, and technically MacOSX support is finished but it's not been published as I didn't ever sit down and integrate the update into the nasmx.inc header. And thanks to Keith's insanely hard work it had 64-bit support for both Windows and Linux before NASM officially did. :p

Sorry for sounding like I was advertising, but it seems like the only things I ever hear people complain about what NASMX can't do, are the things that it was designed to do (same can be said for NASM actually). I think you've gotten a hold of some bad information.

If not, then I will be extending it in order to provide the necessary foundation to truly support a portable oop framework ( which has been my own personal goal all along ) and you probably wouldn't recognize it when I'm done with it. ;)

Yea, have at it man! I've always supported people extending/forking from my work. And truthfully, you seem more enthusiastic about it than I am, as I'm doing this mostly targeting as a lower-end project and, as you mentioned, you are looking for a framework. :)
Title: Re: NASM OOP - Work In Progress
Post by: c051n3 on July 15, 2010, 06:01:10 AM
I hope that didn't come across as a complaint as that was not my intention. I think what you guys have done is great stuff and I admire your work. You are correct in that I was under a false impression about nasmx. I need to revisit the package and examine it more thoroughly.
Title: Re: NASM OOP - Work In Progress
Post by: Frank Kotler on July 15, 2010, 06:46:04 AM
"I think you've gotten a hold of some bad information."

Or not enough information, perhaps. I see no indication anywhere how NASMX would be used to create a cross-platform app. Where should we be looking?

Best,
Frank

Title: Re: NASM OOP - Work In Progress
Post by: Bryant Keller on July 15, 2010, 01:39:02 PM
"I think you've gotten a hold of some bad information."

Or not enough information, perhaps. I see no indication anywhere how NASMX would be used to create a cross-platform app. Where should we be looking?

Best,
Frank

I think your right... both of you actually. Somewhere along the line the project was divided amongst Linux and Windows based explicitly on the archive file it's stored in (this was probably one of the many times the directory structure changed due to us having to change linkers on the Windows branch for various reasons, cause the Linux branch looks about the same). During this time it seems the cross platform demo appears to have vanished... It's still totally possible to do cross platform development however. It's just not totally apparent, or documented since we never bothered to write any documentation. ::)  Just make use of libc or another cross platform library when requesting any system dependant service (I/O, Mem, etc). To be honest, it wouldn't be that hard to change objects.inc to use NASMX, just change this:

Code: [Select]
%ifidni __OUTPUT_FORMAT__,win32
EXTERN GetProcessHeap
EXTERN HeapAlloc
EXTERN HeapFree
%else
EXTERN malloc
EXTERN free
%endif

to read this instead:

Code: [Select]
%include "nasmx.inc"
IMPORT malloc
IMPORT free

Then change the nasm_alloc and nasm_free macros to:

Code: [Select]
%macro nasm_alloc 1
invoke malloc, %{1}
%endm

%macro nasm_free 1
invoke free, %{1}
%endm

And the core is now powered by NASMX. You could go one step further by changing the internal constructor to use the proc/endproc and you're half-way to full 64-bit support since both invoke and proc/endproc handle 64-bit.

But yeah... by design, it can do cross platform development. In fact that's about the only thing I use NASMX for (which is why I wasn't up to speed on the windows branch).
Title: Re: NASM OOP - Work In Progress
Post by: Frank Kotler on July 15, 2010, 05:37:14 PM
Okay. After posting that, I realized that "nasmx.inc" *will* work cross-platform. Pretty good trick in itself! I was thrown off by the two different distributions. If you'll recall, you had to tar up the Windows version for me, 'cause I couldn't find an archiver that would decompress the .exe (probably possible, but I don't know how). The two versions overlay each other nicely, without apparent conflict.

In the Linux branch of the "inc" directory, you've got a fairly limited "libc.inc"... which includes some constants which apply even if you're not using C. And "syscall.inc" appears to be just 32-bit... but could be expanded, I guess.

There's going to be a slight "issue" with that, in that "-f elf" and "-f elf32" are the same thing, but result in different "__OUTPUT_FORMAT__"s which don't match. Make 'em use "-f elf32" is probably the easiest workaround to that...

The Linux "demo1" uses sys_calls, so wouldn't be portable, but a "printf" version probably would...

I guess I've actually done a cross-platform example, in a way... Nathan sent me some "experiments" he's doing, using the nasmx include files for the Windows version, and using some of the "socket" APIs. I wrote a "fakeapi.asm", which includes routines of the same name, same parameters, which do "something roughly similar", using syscalls. To my astonishment, it works! I didn't use your "syscall.inc", but I could probably alter it so it did... This is only going to work for a very limited subset of APIs - I don't have much hope for portable GUI apps - but it shows some promise for "console" and "socket" stuff.

So yeah... you should maybe "advertise" more. There's more to NASMX than I realized!

Best,
Frank

Title: Re: NASM OOP - Work In Progress
Post by: Bryant Keller on July 15, 2010, 10:47:56 PM
Okay. After posting that, I realized that "nasmx.inc" *will* work cross-platform. Pretty good trick in itself! I was thrown off by the two different distributions. If you'll recall, you had to tar up the Windows version for me, 'cause I couldn't find an archiver that would decompress the .exe (probably possible, but I don't know how). The two versions overlay each other nicely, without apparent conflict.

The NASMX windows executable file will expand in WINE if you have that installed. The reason that archive readers like file-roller can't open the windows executable is because it's a custom installer, not a compressed .exe file. The file sets up various windows specific environment variables and then extracts everything into the system. I remember when Keith made the installer, it was a wise decision because we were repeatedly bombarded with questions about how to configure NASM and NASMX to work properly under windows, even to the point that many users were claiming that NASMX didn't work on various systems.

In the Linux branch of the "inc" directory, you've got a fairly limited "libc.inc"... which includes some constants which apply even if you're not using C. And "syscall.inc" appears to be just 32-bit... but could be expanded, I guess.

The system dependant syscall.inc was an idea I had back when I was running things that I don't think ever really continued. I was going to make the NASM32 project support two modes; Portable and Platform Dependant. Portable mode was reliant heavily on C based libraries which could be imported as needed. The Platform dependant mode however would have individual include files which extended NASM32 to support each platform's specific features (like system calls), this was more for the asm purists. I got about as far as getting Windows and Linux done but never got around to doing BSD before Keith took over and I don't think he was ever really interested in that aspect of the project, of course most people weren't.

There's going to be a slight "issue" with that, in that "-f elf" and "-f elf32" are the same thing, but result in different "__OUTPUT_FORMAT__"s which don't match. Make 'em use "-f elf32" is probably the easiest workaround to that...

The first thing in NASMX is:
Code: [Select]
%ifidn __OUTPUT_FORMAT__,elf
%elifidn __OUTPUT_FORMAT__,elf32
%elifidn __OUTPUT_FORMAT__,elf64
%elifidn __OUTPUT_FORMAT__,win32
%define __UNDERSCORE__
%elifidn __OUTPUT_FORMAT__,win64
%define __UNDERSCORE__
%else
%define __CDECL_UNDERSCORE__
%define __UNDERSCORE__
%endif

He could do the same thing in the top of his objects.inc modification but have it make things more specific for him:

Code: [Select]
%ifidn __OUTPUT_FORMAT__,elf
%define __BASE_FORMAT__ elf
%elifidn __OUTPUT_FORMAT__,elf32
%define __BASE_FORMAT__ elf
%elifidn __OUTPUT_FORMAT__,elf64
%define __BASE_FORMAT__ elf
%elifidn __OUTPUT_FORMAT__,win
%define __BASE_FORMAT__ win
%elifidn __OUTPUT_FORMAT__,win32
%define __BASE_FORMAT__ win
%elifidn __OUTPUT_FORMAT__,win64
%define __BASE_FORMAT__ win
%elifidn __OUTPUT_FORMAT__,macho
%define __BASE_FORMAT__ macho
%elifidn __OUTPUT_FORMAT__,macho32
%define __BASE_FORMAT__ macho
%elifidn __OUTPUT_FORMAT__,macho64
%define __BASE_FORMAT__ macho
%else
%error "unsupported output format."
%endif

This would probably be a good idea anyway as you really don't need to know the difference between 32bit and 64bit OUTPUT_FORMAT in most instances since you can determine your current bit-mode via %[__BITS__] which is more important than the object bit-mode when doing headers.

The Linux "demo1" uses sys_calls, so wouldn't be portable, but a "printf" version probably would...

Heh, yea. There were tons of complains about the demos, but they do what they were designed for. I just tried to show the syntax the best I could since there was no documentation. Also, speaking of the demos, it looks like Keith has been doing some work on the windows demos, there are some new ones I've not seen. :)

I guess I've actually done a cross-platform example, in a way... Nathan sent me some "experiments" he's doing, using the nasmx include files for the Windows version, and using some of the "socket" APIs. I wrote a "fakeapi.asm", which includes routines of the same name, same parameters, which do "something roughly similar", using syscalls. To my astonishment, it works! I didn't use your "syscall.inc", but I could probably alter it so it did... This is only going to work for a very limited subset of APIs - I don't have much hope for portable GUI apps - but it shows some promise for "console" and "socket" stuff.

Remember, just use a cross platform C library for the system dependant stuff. Things like GTK, Allegro, NCurses, OpenGL, OpenAL, and other cross platform libraries allow you to write code that will build across multiple system without changes to the source.

So yeah... you should maybe "advertise" more. There's more to NASMX than I realized!

Best,
Frank

And here I thought most of these features were pretty well known, like I said, it's the only reason I use it. Other than for cross platform development, I tend to just code using straight NASM. ;D
Title: Re: NASM OOP - Work In Progress
Post by: c051n3 on July 21, 2010, 03:01:30 PM
And the core is now powered by NASMX. You could go one step further by changing the internal constructor to use the proc/endproc and you're half-way to full 64-bit support since both invoke and proc/endproc handle 64-bit.

But yeah... by design, it can do cross platform development. In fact that's about the only thing I use NASMX for (which is why I wasn't up to speed on the windows branch).

Digging deeper into NASMX uncovered a slew of issues regarding handles, pointers, and structure size changes from win32 to win64 as currently defined in the NASMX windows include files (dated 2009-01-12). Many of these have been promoted from dwords to qwords. This is the main reason why Microsoft recommends using INT_PTR macro for C/C++ coders. Are there any plans to update NASMX's support of 64-bit Windows? Or am I misinformed yet again ???
Title: Re: NASM OOP - Work In Progress
Post by: Bryant Keller on July 22, 2010, 03:04:14 AM
Well, I've not really looked into the changes between Win32 and Win64, like I said - Keith was the magic man who got 64-bit Windows working. I wouldn't hold my breath for any updates, I believe we both agreed to take a break from working on NASMX with our personal lives becoming more demanding (him with an addition to his family and me with medical issues to deal with). This is the same reason why I'm not looking to turn the objects.inc into a major project, atm I'm only able to work on it in spurts of about an hour a week which wouldn't really promote a lot of growth. :D
Title: Re: NASM OOP - Work In Progress
Post by: Keith Kanios on July 22, 2010, 03:35:15 AM
I suppose it is time to make an appearance :)

I've had some time to think about the direction of NASMX, and here are my thoughts/decisions.

I don't have any [active] plans of advancing NASMX in the direction of trying to accommodate all of the different platforms, types, headers and whatnot. Such a direction would require proper high-level typing, and ultimately force NASMX to turn into an ugly/hacked-up version of C... if it is to be done right.

If I am able to, and do, ever pick back up on NASMX, it will be most likely geared toward NASMX as a platform library.

If cosine or someone else wants to contribute and advance the official NASMX, feel free.
Title: Re: NASM OOP - Work In Progress
Post by: Rob Neff on July 23, 2010, 06:12:11 PM
Long time lurker, first time poster.  ;D
I am currently in the midst of developing a project that touches upon all topics being discussed in this thread (64bit, nasmx, and oop). I have some code which defines handles,structs, and ptrs to be bitsize relative in nasmx windows.inc file  and make the appropriate 32/64bit selection for using __OUTPUT_FORMAT__ and __BITS__ .

I would be willing to submit mods for "official" nasmx code rather than maintain a nasmx fork if you desire. The code itself is still being developed and is far from full Win SDK emulation but it's a start.

If you are looking for a contributor I am willing pitch in. For an example, the coding can be done two different ways.

Using typedefs:

Code: [Select]
%ifidni __OUTPUT_FORMAT,win32
%define RESHWND RESD
%define RESWPARAM RESD
%define RESLPARAM RESD
%elifidni __OUTPUT_FORMAT,win64
%define RESHWND RESQ
%define RESWPARAM RESQ
%define RESLPARAM RESQ
%endif

STRUC MSG
.hwnd RESHWND 1
.message RESD 1
.wParam RESWPARAM 1
.lParam RESLPARAM 1
.time RESD 1
.pt RESB POINT_size
ENDSTRUC

Or, without adding extra typedefs we can use:

Code: [Select]
%ifidni __OUTPUT_FORMAT,win32
STRUC MSG
.hwnd RESD 1
.message RESD 1
.wParam RESD 1
.lParam RESD 1
.time RESD 1
.pt RESB POINT_size
ENDSTRUC
%elifidni __OUTPUT_FORMAT,win64
STRUC MSG
.hwnd RESQ 1
.message RESD 1
.wParam RESQ 1
.lParam RESQ 1
.time RESD 1
.pt RESB POINT_size
ENDSTRUC
%endif

Note that for pointer type conversions my preference is for typedefs that mimic the MS SDK:

Code: [Select]
%ifidni __OUTPUT_FORMAT,win32
%define INT_PTR RESD
%ifidni __OUTPUT_FORMAT,win64
%define INT_PTR RESQ
%endif

Let me know your preferences and how you wish to receive any mods.
Title: Re: NASM OOP - Work In Progress
Post by: Bryant Keller on July 23, 2010, 09:53:13 PM
Personally, I tend to use the typedef method in my code. And I would probably do the same thing in NASMX if I was to do any internal updates. My personal 'base.asm' file (which gets pre-included via NASMENV) contains the following lines.

Code: [Select]
%define sizeof(_x_) _x_ %+ _size
%define reserve(_x_) _x_ %+ _res

%idefine byte_size 1
%idefine word_size (byte_size * 2)
%idefine dword_size (word_size * 2)
%idefine qword_size (dword_sized * 2)
%idefine tword_size 10
%idefine oword_size (qword_size * 2)

%idefine byte_res RESB
%idefine word_res RESW
%idefine dword_res RESD
%idefine qword_res RESQ
%idefine tword_res REST
%idefine oword_res RESO

%define int8_t byte
%define int16_t word
%define int32_t dword
%define int64_t qword
%define int80_t tword
%define int128_t oword

%define int8_t_size 1
%define int16_t_size (int8_t_size * 2)
%define int32_t_size (int16_t_size * 2)
%define int64_t_size (int32_t_size * 2)
%define int80_t_size 10
%define int128_t_size (int64_t_size * 2)

%define int8_t_res RESB
%define int16_t_res RESW
%define int32_t_res RESD
%define int64_t_res RESQ
%define int80_t_res REST
%define int128_t_res RESO

%define iax8 al
%define iax16 ax
%define iax32 eax
%define iax64 rax
%define iax128 xmm0

%define ibx8 bl
%define ibx16 bx
%define ibx32 ebx
%define ibx64 rbx
%define ibx128 xmm1

%define icx8 cl
%define icx16 cx
%define icx32 ecx
%define icx64 rcx
%define icx128 xmm3

%define idx8 dl
%define idx16 dx
%define idx32 edx
%define idx64 rdx
%define idx128 xmm4

%define ibp8 sp
%define ibp16 sp
%define ibp32 esp
%define ibp64 rsp
%define ibp128 rsp

%define isp8 sp
%define isp16 sp
%define isp32 esp
%define isp64 rsp
%define isp128 rsp

This gives me very C-ish style types and allows me to do some really cool stuff like:

Code: [Select]
STRUC MSG
.hwnd reserve( int%[__BITS__]_t ) 1
.message reserve( dword ) 1
.wParam reserve( int%[__BITS__]_t ) 1
.lParam reserve( int%[__BITS__]_t ) 1
.time reserve( dword ) 1
.pt reserve( byte ) POINT_size
ENDSTRUC

Which will change it to the correct RESD/RESQ based on the BITS n definition in your code.

And..

Code: [Select]
push ibp%[__BITS__]
mov ibp%[__BITS__], isp%[__BITS__]
;...
leave
ret

I don't use these register mods a whole lot, but they do come in handy in some projects... the type mods however I use in almost everything.. definitely useful. :)
Title: Re: NASM OOP - Work In Progress
Post by: Keith Kanios on July 23, 2010, 10:53:23 PM
If you are looking for a contributor I am willing pitch in.

On my behalf, and to be honest, I am looking for someone to completely take over primary maintenance of the project.

See http://www.asmcommunity.net/board/index.php?topic=30111.0 (http://www.asmcommunity.net/board/index.php?topic=30111.0) for more details.
Title: Re: NASM OOP - Work In Progress
Post by: Rob Neff on July 23, 2010, 11:07:27 PM
Turn on PMs for us newbie posters plz  ;D
Title: Re: NASM OOP - Work In Progress
Post by: Keith Kanios on July 24, 2010, 02:46:38 AM
I think it eases up at 5 posts. I've had experiences in the past with spamers/bots getting through and flooding everyone via PM... even despite send limits... and that is something I would rather avoid :)

You can PM me at this forum too, if you'd like.
Title: Re: NASM OOP - Work In Progress
Post by: Rob Neff on July 24, 2010, 01:01:15 PM
Well I don't want to spam the forums just to increase post count...
Title: Re: NASM OOP - Work In Progress
Post by: Rob Neff on July 24, 2010, 01:01:54 PM
but sometimes a guy's gotta do what a guys gotta do  ;D
Title: Re: NASM OOP - Work In Progress
Post by: Rob Neff on July 24, 2010, 01:14:37 PM
To me NASMX has a bright future. I would like to maintain the 32/64bit Windows development portion in the role of a co-maintainer. A git/svn would be set up to provide for other individuals to nuture it's development on other platforms.
Title: Re: NASM OOP - Work In Progress
Post by: Rob Neff on July 24, 2010, 07:36:19 PM
Personally, I tend to use the typedef method in my code. And I would probably do the same thing in NASMX if I was to do any internal updates. My personal 'base.asm' file (which gets pre-included via NASMENV) contains the following lines.

Code: [Select]
%define sizeof(_x_) _x_ %+ _size
%define reserve(_x_) _x_ %+ _res

%idefine byte_size 1
%idefine word_size (byte_size * 2)
%idefine dword_size (word_size * 2)
%idefine qword_size (dword_sized * 2)
%idefine tword_size 10
%idefine oword_size (qword_size * 2)

%idefine byte_res RESB
%idefine word_res RESW
%idefine dword_res RESD
%idefine qword_res RESQ
%idefine tword_res REST
%idefine oword_res RESO

%define int8_t byte
%define int16_t word
%define int32_t dword
%define int64_t qword
%define int80_t tword
%define int128_t oword

%define int8_t_size 1
%define int16_t_size (int8_t_size * 2)
%define int32_t_size (int16_t_size * 2)
%define int64_t_size (int32_t_size * 2)
%define int80_t_size 10
%define int128_t_size (int64_t_size * 2)

%define int8_t_res RESB
%define int16_t_res RESW
%define int32_t_res RESD
%define int64_t_res RESQ
%define int80_t_res REST
%define int128_t_res RESO

%define iax8 al
%define iax16 ax
%define iax32 eax
%define iax64 rax
%define iax128 xmm0

%define ibx8 bl
%define ibx16 bx
%define ibx32 ebx
%define ibx64 rbx
%define ibx128 xmm1

%define icx8 cl
%define icx16 cx
%define icx32 ecx
%define icx64 rcx
%define icx128 xmm3

%define idx8 dl
%define idx16 dx
%define idx32 edx
%define idx64 rdx
%define idx128 xmm4

%define ibp8 sp
%define ibp16 sp
%define ibp32 esp
%define ibp64 rsp
%define ibp128 rsp

%define isp8 sp
%define isp16 sp
%define isp32 esp
%define isp64 rsp
%define isp128 rsp

This gives me very C-ish style types and allows me to do some really cool stuff like:

Code: [Select]
STRUC MSG
.hwnd reserve( int%[__BITS__]_t ) 1
.message reserve( dword ) 1
.wParam reserve( int%[__BITS__]_t ) 1
.lParam reserve( int%[__BITS__]_t ) 1
.time reserve( dword ) 1
.pt reserve( byte ) POINT_size
ENDSTRUC

Which will change it to the correct RESD/RESQ based on the BITS n definition in your code.

And..

Code: [Select]
push ibp%[__BITS__]
mov ibp%[__BITS__], isp%[__BITS__]
;...
leave
ret

I don't use these register mods a whole lot, but they do come in handy in some projects... the type mods however I use in almost everything.. definitely useful. :)

That is beautiful code. I had to quote the entire post to give it the proper attention it deserves since it is exactly what I have in mind for updating NASMX with. ;D
Title: Re: NASM OOP - Work In Progress
Post by: Klod on July 26, 2010, 01:41:34 AM
Hi Bryan,
Thanks very much for sharing your oop implementation. For some time have I been interested to do oop in Nasm. I have downloaded the example from http://assembly.ath.cx/code/objects.inc. I use nasm with goasm and modified slightly to make it work. I have tried your second example from earlier in this post and wonder if there is an updated objects.inc file. I do get a compile time ERROR from line      new CTest, dword strAuthor

Quote
C:\NasmEd\Project\NasmObject>mak
Assembling main.asm
main.asm:15: error: symbol `CTest_CTest' undefined
Assembling myObject.asm
project file attached


Title: Re: NASM OOP - Work In Progress
Post by: Bryant Keller on July 26, 2010, 02:47:19 AM
Hi Bryan,
Thanks very much for sharing your oop implementation. For some time have I been interested to do oop in Nasm. I have downloaded the example from http://assembly.ath.cx/code/objects.inc. I use nasm with goasm and modified slightly to make it work. I have tried your second example from earlier in this post and wonder if there is an updated objects.inc file. I do get a compile time ERROR from line      new CTest, dword strAuthor

Quote
C:\NasmEd\Project\NasmObject>mak
Assembling main.asm
main.asm:15: error: symbol `CTest_CTest' undefined
Assembling myObject.asm
project file attached

I've uploaded a new version which should take care of that little problem. The issue is simply that I forgot to add a Global/Extern for the user-ctor in the event it exists. Now, just a note.. this is marked as a "Work in Progress" for a reason, there are going to be bugs... probably lots of them. p1ranha and I were just recently discussing on asmcommunity about an issue with the inheritance system (it doesn't recursively call parent constructors, but I posted on that same thread a possible fix for later on). I'm just letting you know, don't do any mission critical stuff with this OOP kit just yet, it's not up to par for anything like that, it's ultra-alpha-ware.

http://assembly.ath.cx/code/objects.inc
Title: Re: NASM OOP - Work In Progress
Post by: Klod on July 27, 2010, 04:05:47 AM
Thanks Briant
The updated objects.inc file did the trick. As always, I am intrigued by your macros. I have been working on a simplistic implementation of an oop model in Nasm but alas not very successful. I will study yours with more attention to the details.

You mentioned a work around  the ctor bug and I assume this would be to mandatory defining a ctour for each class?
Klod
Title: Re: NASM OOP - Work In Progress
Post by: Bryant Keller on July 27, 2010, 07:17:05 PM
Thanks Briant
The updated objects.inc file did the trick. As always, I am intrigued by your macros. I have been working on a simplistic implementation of an oop model in Nasm but alas not very successful. I will study yours with more attention to the details.

You mentioned a work around  the ctor bug and I assume this would be to mandatory defining a ctour for each class?
Klod

Well, the version you are using now doesn't require you to have a ctor or a dtor at all. No, the bug I'm talking about is because I don't support ancestor ctor calls. My temporary fix was just to recurse over the %{$parent} definitions like I do when generating the symbol table for the class itself in the first place and look for the presence of an %{$parent}_has_ctor symbol with a value of '1', then placing a cdecl call to the Ctor for that parent. This would require that all Ctor's be written with the Cdecl calling convention and that ctor parameters couldn't change, only extend per inherited class... So it's not really a solution as much as a hack-fix.
Title: Re: NASM OOP - Work In Progress
Post by: Klod on August 02, 2010, 04:02:52 AM
Hi Bryant,

I have been playing around with your code sample for the last few days.


C:\NasmEd\Project\NasmObject>mak
Assembling main.asm
MyObject.inc:11: warning: (static:20) CTest_static_data_0_size     4
MyObject.inc:13: warning: (endclass:8) CTest_total_virtual_methods     1
MyObject.inc:13: warning: (endclass:9) CTest_total_static_methods     2
Assembling myObject.asm
myObject.inc:11: warning: (static:20) CTest_static_data_0_size     4
myObject.inc:13: warning: (endclass:8) CTest_total_virtual_methods     1
myObject.inc:13: warning: (endclass:9) CTest_total_static_methods     2

I noticed that CTest_total_static_methods  = 2, yet there are 3 static methods defined. I assume that ctor is handled different?

I could not quite figure out how you implemented the class definition so that its members can be inherited by derived classes. I expected similar definitions like for struc definitions. I assume CTest_static_data_0_size  (4) and CTest_static_data_N_size  to be  offsets  and _total_static_methods be the upper limit.  The parent class had been defined in an other context but it can be inherited by means of the above defines? The Total size of the Class is then the sum of number_of_static_methods, number_of_virtual_methods, number_of_static_members, number_of_virtual_members.

.vmt and vdt would be the first 2 elements (pointers) to their respective tables.

Call %{1}_%{1} call to ctor either default or user defined

I haven't yet build a project using your model but think it is a good start. Waiting to see your next update.
Klod







Title: Re: NASM OOP - Work In Progress
Post by: Bryant Keller on August 02, 2010, 06:14:13 AM
Hi Bryant,

Hi Klod, Always good to hear from you man. :)

I have been playing around with your code sample for the last few days.


C:\NasmEd\Project\NasmObject>mak
Assembling main.asm
MyObject.inc:11: warning: (static:20) CTest_static_data_0_size     4
MyObject.inc:13: warning: (endclass:8) CTest_total_virtual_methods     1
MyObject.inc:13: warning: (endclass:9) CTest_total_static_methods     2
Assembling myObject.asm
myObject.inc:11: warning: (static:20) CTest_static_data_0_size     4
myObject.inc:13: warning: (endclass:8) CTest_total_virtual_methods     1
myObject.inc:13: warning: (endclass:9) CTest_total_static_methods     2

I noticed that CTest_total_static_methods  = 2, yet there are 3 static methods defined. I assume that ctor is handled different?

That's right. This is because there are two possible ctors. There is an internal ctor which is created for every class %{1}___%{1} and a user defined ctor which only appears when the user wishes to preform some run-time initialization , %{1}_%{1}.

The internal ctor handles setting up all the pointers that the class will be dependent on for invoking methods. The user ctor, although it is a static method, doesn't appear as part of the CTest_total_static_methods definition because it doesn't need to be. The internal constructor uses those symbols (%{$name}_*_static_* and %{$name}_*_virtual_*) to preform the updating of the pointers of the class memory. Because the user ctor is invoked directly, it's not required to be updated as part of this and is not included.

I could not quite figure out how you implemented the class definition so that its members can be inherited by derived classes. I expected similar definitions like for struc definitions. I assume CTest_static_data_0_size  (4) and CTest_static_data_N_size  to be  offsets  and _total_static_methods be the upper limit.  The parent class had been defined in an other context but it can be inherited by means of the above defines? The Total size of the Class is then the sum of number_of_static_methods, number_of_virtual_methods, number_of_static_members, number_of_virtual_members.

Well, the idea is pretty simple, as you have no doubt figured out, I'm creating a description of the class using these symbols, and when I reach the ENDCLASS macro I use ABSOLUTE directly to create a structure (basically the way STRUC does internally).

For inheritance, I'm keeping a list of what parents, if any, each class has. At the beginning of the definition in the CLASS macro, I loop through all the parents and copy the values of these symbols into the symbols for my current class. This basically extends my class automatically.

Code: [Select]
%if %0 = 2
%[%{$name}]_has_parent equ 1
%define %[%{$name}]_parent %{2}
%define %$parent %2
%if %{1}_has_parent > 0
%[%{$name}]_parent_count equ (%[%{$parent}]_parent_count + 1)
%else
%[%{$name}]_parent_count equ 1
%endif
%assign %$number_of_virtual_methods %[%{$parent}]_total_virtual_methods
%assign %$number_of_virtual_members %[%{$parent}]_total_virtual_members
%assign %$ii 0
%rep %{$number_of_virtual_methods}
%define %[%{$name}]_virtual_method_%[%{$ii}]_full %[%{$parent}]_virtual_method_%[%{$ii}]_full
%define %[%{$name}]_virtual_method_%[%{$ii}]  %[%{$parent}]_virtual_method_%[%{$ii}]
%assign %$ii %{$ii} + 1
%endrep
%assign %$ii 0
%rep %{$number_of_virtual_members}
%define %[%{$name}]_virtual_data_%[%{$ii}]_size %[%{$parent}]_virtual_data_%[%{$ii}]_size
%define %[%{$name}]_virtual_data_%[%{$ii}]  %[%{$parent}]_virtual_data_%[%{$ii}]
%assign %$ii %{$ii} + 1
%endrep
%else
%[%{$name}]_has_parent equ 0
%[%{$name}]_parent_count equ 0
%endif

Also take a look at the BUILD_CLASS_STRUCTURE macro which creates the actual memory imprint for the class (and makes use of the inherited symbols). You'll notice in that macro a call to another macro called INHERIT_PARENT_DATA, this ensures that our inherited classes come before our current class data in memory, but our current class's VDT/VMT and Dtor come before our inherited data.

.vmt and vdt would be the first 2 elements (pointers) to their respective tables.

Call %{1}_%{1} call to ctor either default or user defined

I haven't yet build a project using your model but think it is a good start. Waiting to see your next update.
Klod

I'm actually working on something else atm, so an update won't be real soon. This project is something I've been doing off and on for some time now. I just thought since it was showing some form of progress I would post it.
Title: Re: NASM OOP - Work In Progress
Post by: Klod on August 03, 2010, 03:55:16 AM
Hi Bryant,
Thanks for sharing your methodology behind your OOP model. I had to buckle down and "work" on understanding how it all works.

Quote
Also take a look at the BUILD_CLASS_STRUCTURE macro which creates the actual memory imprint for the class (and makes use of the inherited symbols). You'll notice in that macro a call to another macro called INHERIT_PARENT_DATA, this ensures that our inherited classes come before our current class data in memory, but our current class's VDT/VMT and Dtor come before our inherited data.

I did have a look at these macros. I missed however the order of inheritance, vdt/vmt and dtpr. Isn't this causing some difficulties later in addressing? some people suggest to inherit/include parent classes in structure fashion by appending only at the end. In this way ptr to vmt would always be at offset 0.

Quote
I'm actually working on something else atm, so an update won't be real soon. This project is something I've been doing off and on for some time now. I just thought since it was showing some form of progress I would post it.

Time is a precious commodity and as time goes on becomes scarcer. My coding time has been shorted lately, other projects moved to the foreground. I still try to visit the forums a few times a week. Whenever I see a post of yours, I'm all over it. You are a very gifted programmer and especially your knowledge and skill shine through your posts. Your macros have dazzled me quite a few times and helped me a great deal in my quest for better programming with Nasm.

thanks
Klod
Title: Re: NASM OOP - Work In Progress
Post by: Bryant Keller on August 04, 2010, 12:41:23 AM
For the most part, that is what's happening. The structure I'm creating does append the child to the parent, with the exception of the pointers to the VMT/VDT which is at the beginning. As for the VMT/VDT itself, the entries have to support overloading, therefore new entries are appended to the table while entries which already exist are simply overwritten.

The only actual difficulty is that I don't support an ancestor call method or any technique to descend through parent ctor/dtor (both are a related issue).