© 2017-2019 by Zack Smith. All rights reserved.
Object-oriented programming (OOP) became a dominant paradigm a few decades ago. People think of C++, Java and Objective-C as prominent examples of object-oriented languages. It is easy to assume that OOP requires such an OOP language. This is not the case. OOP is just a paradigm. It is not strictly necessary to use an object-oriented programming language to do object-oriented programming. You can do OOP for instance in C but you can even do it in assembly language. (See my article on Object-Oriented C programming.)
The ideal approach to object-oriented x86 assembly programming
A simple technique for implementing an object and its class in assembly is to have two chunk of RAM for:
- A class
struc, which holds method pointers.
- An object
struc, which holds the instance variables (ivars), and a pointer to a class
structto get access to method pointers.
Because you're coding in assembly, which makes you write out every memory access as another instruction, it is best to have one class struc per class which does not point to a superclass struc, lest accessing method pointers become tedious. Thus each class struct should include all methods' pointers i.e. those of the class you're writing plus all superclass methods.
Likewise, each object struc should have superclass instance variables followed by ivars for subclasses including the class you're writing, so that if you call a superclass method, its idea of where its ivars are matches the layout of your object struc.
Here's an example of a class struct with two superclasses:
- inherits from String
- inherits from Object
The initialization of the class struc calls the superclasses' initializers first, in order.
If any superclass method is to be overridden by a subclass, that subclass's init method must overwrite the superclass method pointer for it to point to its own variant, as I do in OOC.
Each object has to have a memory layout that is compatible with parent and derived classes. Here is an example:
Ease of programming
Assembly language is inherently more difficult and error-prone than coding in a high-level language.
The NASM assembler can make OOP difficult because struc layouts cannot be inherited (same as C).
Calculating indices of ivars and methods is tedious but could be made simpler with macros, in theory.
Object strucs must be carefully laid out so that superclass methods can work on subclass objects.
However if you want to produce the absolute fastest possible object-oriented code, this may be the only way.
While OOA is an interesting curiosity, it does tie you to a particular architecture.
A wiser approach is to use Object-Oriented C (OOC), which achieves the speed of C++ without the need for a 1000-page book to explain the language.
In my variant of OOC, which I use in my bandwidth benchmark, the slightly syntax resembles that of Objective-C.