Object Oriented Assembly Programming by Walter de Jong WJ96 Object Oriented Programming (OOP) has become immensely populair over the past few years. Nowadays, many programming languages have object oriented variants; for instance C (C++, Objective C), Pascal (Object Oriented Pascal, Delphi). Even the interpreted language Perl (Perl version 5), SQL, and the classic BASIC (Visual Basic) have been extended to object oriented languages. When I first proposed to turn assembly into an object oriented language, people laughed in my face. It is a somewhat insane thought, but when the compiler creates object code, it creates machine instructions which the processor can execute; which is exactly what an assembler does. So nothing magically is happening, really. Some C++ compilers first convert the object oriented code to standard C and compile the code using a generic C compiler. Other compilers internally convert the source code to assembly and assemble that code to machine code. Either way, executable machine code is produced from an object oriented language, so at this point it is not that insane anymore to believe that assembly can be object oriented as well. In this paper I will tell you how object oriented assembly can be implemented using a normal assembler, thus showing you how highlevel object oriented language compilers internally work. The Class Declaration In TASM you can declare structures: STRUC RecordName field1 db ? field2 db ? field3 dw ? prev dd ? next dd ? ENDS I guess it should be possible to declare a class in a similar way: CLASS ClassName member1 db ? member2 dw ? Constructor dd ? Destructor dd ? ; virtual table of member functions memberfunction1 dd ? memberfunction2 dd ? ENDC Because the assemblers we use right now don't understand the keywords CLASS and ENDC, we will have to use EQUs to define these keywords for now. Access to the fields in a TASM STRUC is done like this: mov ax, [MyStruc.w_field] You could access member variables of a class in exactly the same way. Constructors and Destructors Constructors are called whenever an instance of a class (an object) is created, destructors are called when the instance is destroyed. The OO compiler creates this code for you. In assembly, you can write a macro that does something like this; MACRO new mov ax, sizeof MyClass call malloc call [bx + MyClass.Constructor] ENDM MACRO delete call [bx + MyClass.Destructor] call free ENDM Copy Constructors Works exactly the same a 'normal' constructor in object oriented assembly. However, converting the following C++ constructors to OO assembly requires some more: MyClass() { a = 1; b = 0; } MyClass(int n) { a = n; b = 1; } MyClass(int n, int m) { a = n; b = m; } See the section 'Polymorphism in Object Oriented Languages' for more about this. Intrinsic Inline Member Functions Intrinsic inline member functions are macro's; since they are _inline_, they are copied into the code each time when used, instead of being called as a subroutine. If you are planning on using my 'new' and 'delete' macros, note that these do not use inline constructors/destructors. Polymorphism in Object Oriented Languages Polymorphism in highlevel object oriented languages come in two flavours: * functions with the same name, but with different number of arguments * overruled member functions that were inherited from a base class Object Oriented Assembly is a polymorphic language, just like the high level object oriented languages. What we'd really like to have is a notation like: call MyClass.memberfunction or: call [MyClass.memberfunction] or even: call [p_MyClass].memberfunction The first form of polymorphism is a bit of a problem to implement using conventional assemblers. I suggest you simply use different names for the functions. If we'd really want to imitate this feature of highlevel OO languages, we'd need to have a special sort of assembler. The second form of polymorphism is created almost automatically in OO assembly. It is completely logical: The virtual member functions of a class are really pointers to subroutines, these pointers are kept in what we call the virtual table of a class. Whenever a class is derived from the base class, its virtual table is copied -- so all member functions are inherited from the base class. The derived class may overrule any virtual functions of the base class by writing new addresses in its own copy of the virtual table. Operator Functions Operator functions are nothing more and nothing less than normal subroutines, just like other member functions. If you really want to alter the behaviour of e.g. the 'ADD' mnemonic or the 'AND' mnemonic, I guess you can use either MACROs or EQUs (or both) to achieve this. Templates In assembly, we usually don't have types. Some say the assembler has the types 'byte', 'word', and 'double word' because the CPU can use these, but still I don't think these are real types. A highlevel language compiler will produce warnings or errors when you attempt to mix types to inform the programmer that he is probably making a big mistake; but in assembly this usually is exactly what you are trying to do. Custom types that can be created using structures or classes don't exist in such way in assembly either -- they're just blocks of data. Does this mean that templates do not exist in assembly either? On the contrary, templates have always existed in assembly from the very start. Make sure all your offset of a certain 'type' are okay when used in another 'type' (block of data) and... like OO magic -- your template is done. The 'bool' type and True and False At the time of writing this document, the ANSI C++ committee has registered 'bool', 'true', and 'false' as new keywords. Most compilers use an int (CPU base register size, usually 32 bits or 64 bits, only 16 bits wide on oldies) as a 'bool'. In assembly, we can do much better than this, by using only a single bit as 'bool' (In fact, this can be done in a high level language as well, but most compilers simply aren't smart enough). Whether 'true' (or 'false') is a set bit or a cleared bit, is up to you -- as long as you use it consequently in a program there will be no problems. There are no official rules on whether '1' is true or false; some boolean logic says '1' is true, others say '1' is false. Bye bye Well, that's all folks! Happy coding in object oriented assembly, and don't forget where you saw it first..! :) 'Assembly, zo moeilijk nie' --WJ96 ; EOB