Author Topic: NASM OOP - Work In Progress  (Read 81976 times)

Offline Bryant Keller

  • Forum Moderator
  • Full Member
  • *****
  • Posts: 360
  • Country: us
    • About Bryant Keller
NASM OOP - Work In Progress
« 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
« Last Edit: July 14, 2010, 08:35:15 PM by Bryant Keller »

About Bryant Keller
bkeller@about.me

Offline Frank Kotler

  • NASM Developer
  • Hero Member
  • *****
  • Posts: 2667
  • Country: us
Re: NASM OOP - Work In Progress
« Reply #1 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


Offline Bryant Keller

  • Forum Moderator
  • Full Member
  • *****
  • Posts: 360
  • Country: us
    • About Bryant Keller
Re: NASM OOP - Work In Progress
« Reply #2 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.

About Bryant Keller
bkeller@about.me

Offline Bryant Keller

  • Forum Moderator
  • Full Member
  • *****
  • Posts: 360
  • Country: us
    • About Bryant Keller
Re: NASM OOP - Work In Progress
« Reply #3 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.

About Bryant Keller
bkeller@about.me

Offline Frank Kotler

  • NASM Developer
  • Hero Member
  • *****
  • Posts: 2667
  • Country: us
Re: NASM OOP - Work In Progress
« Reply #4 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


Offline Bryant Keller

  • Forum Moderator
  • Full Member
  • *****
  • Posts: 360
  • Country: us
    • About Bryant Keller
Re: NASM OOP - Work In Progress
« Reply #5 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. :)

About Bryant Keller
bkeller@about.me

Offline c051n3

  • Jr. Member
  • *
  • Posts: 22
Re: NASM OOP - Work In Progress
« Reply #6 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.

Offline Frank Kotler

  • NASM Developer
  • Hero Member
  • *****
  • Posts: 2667
  • Country: us
Re: NASM OOP - Work In Progress
« Reply #7 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


Offline Bryant Keller

  • Forum Moderator
  • Full Member
  • *****
  • Posts: 360
  • Country: us
    • About Bryant Keller
Re: NASM OOP - Work In Progress
« Reply #8 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

About Bryant Keller
bkeller@about.me

Offline Frank Kotler

  • NASM Developer
  • Hero Member
  • *****
  • Posts: 2667
  • Country: us
Re: NASM OOP - Work In Progress
« Reply #9 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


Offline c051n3

  • Jr. Member
  • *
  • Posts: 22
Re: NASM OOP - Work In Progress
« Reply #10 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.


Offline Bryant Keller

  • Forum Moderator
  • Full Member
  • *****
  • Posts: 360
  • Country: us
    • About Bryant Keller
Re: NASM OOP - Work In Progress
« Reply #11 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. ;)

About Bryant Keller
bkeller@about.me

Offline c051n3

  • Jr. Member
  • *
  • Posts: 22
Re: NASM OOP - Work In Progress
« Reply #12 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! ;)


Offline Bryant Keller

  • Forum Moderator
  • Full Member
  • *****
  • Posts: 360
  • Country: us
    • About Bryant Keller
Re: NASM OOP - Work In Progress
« Reply #13 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.

About Bryant Keller
bkeller@about.me

Offline c051n3

  • Jr. Member
  • *
  • Posts: 22
Re: NASM OOP - Work In Progress
« Reply #14 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.