flat assembler
Message board for the users of flat assembler.
Index
> Projects and Ideas > OOP extension - request for comments. Goto page Previous 1, 2, 3 Next |
Author |
|
m3ntal 22 May 2014, 13:55
Note: Syntaxes like this can be automated:
Code: create TDog mov [Dog1], eax Code: create [Dog1]=new TDog ; in create macro (where p=[]) match [m]== =new type, p { create type mov [m], eax } Code: create John=new User 'John' destroy fresh.lib |
|||
22 May 2014, 13:55 |
|
revolution 22 May 2014, 14:07
m3ntal wrote: Note: Syntaxes like this can be automated: The problem with custom macros is the documentation. They might, or might not, do weird things with memory and/or registers that is hidden from view. Will macro XYZ corrupt eax or edx or some memory below esp? It is already bad enough with lods, div and loop having hidden registers, and now we have to contend with macros on top of that. It took me many years just to get comfortable with stdcall, so you can imagine how hard it is to cope with create and exec, or that newfangled call. Last edited by revolution on 22 May 2014, 15:46; edited 1 time in total |
|||
22 May 2014, 14:07 |
|
edfed 22 May 2014, 14:34
Code: DrawImage x,y,[content] i don't get why a esi reference is needed. |
|||
22 May 2014, 14:34 |
|
JohnFound 22 May 2014, 14:58
revolution wrote: The problem with custom macros is the documentation. They might, or might not, do weird things with memory and/or registers that is hidden from view. Will macro XYZ corrupt eax or edx or some memory below esp? I am fully agree with you here. I always tried to keep the macros as non-intrusive and predictable, as possible. And to write some documentation of course. Sometimes... _________________ Tox ID: 48C0321ADDB2FE5F644BB5E3D58B0D58C35E5BCBC81D7CD333633FEDF1047914A534256478D9 |
|||
22 May 2014, 14:58 |
|
m3ntal 22 May 2014, 16:01
Quote: i don't get why a esi reference is needed Code: DrawImage esi, x, y call Image:Draw, x, y int DrawImage(Image *this, int x, int y); Quote: It took me many years just to get comfortable with stdcall |
|||
22 May 2014, 16:01 |
|
typedef 22 May 2014, 16:15
m3ntal wrote:
hahahah |
|||
22 May 2014, 16:15 |
|
revolution 22 May 2014, 16:23
m3ntal wrote: I thought the new call would make DOS programmers feel more comfortable about the transition to Windows. m3ntal wrote: It was never a good idea to RE-specify conventions: stdcall/invoke/cinvoke/ccall/pinvoke/pcall/etc. |
|||
22 May 2014, 16:23 |
|
m3ntal 22 May 2014, 16:26
LOL. Check out this C code:
Code: USER *john=NULL; TRASH *fresh_lib=USELESS; for (;;) { recommend_to_dummies(fresh_lib); } |
|||
22 May 2014, 16:26 |
|
m3ntal 22 May 2014, 16:46
Quote: It is never a good idea to override native CPU instructions |
|||
22 May 2014, 16:46 |
|
revolution 22 May 2014, 16:54
I have never liked proc either. A lot is hidden inside proc also. But at least it isn't named the same as a native instruction.
|
|||
22 May 2014, 16:54 |
|
r22 22 May 2014, 17:51
PRAJ - Push Return-address And Jump, would be a superior name for CALL.
1) Easier to type 2) Means what it does 3) Can be shortened to PRJ and still retain meaning 4) Can alias with RPJ and RPAJ for when you're too lazy to type correctly I win. |
|||
22 May 2014, 17:51 |
|
revolution 23 May 2014, 01:13
No, it should be this:
Code: lea esp,[esp-4] | mov [esp],eip | lea eip,[eip+offset] |
|||
23 May 2014, 01:13 |
|
JohnFound 23 May 2014, 04:50
Please, on topic. Some test cases and possible problems in the discussed library are welcome.
|
|||
23 May 2014, 04:50 |
|
JohnFound 28 May 2014, 13:38
After several days of work, I managed to write short reference manual of the OOP macro library. Please, read it and comment:
Code: # Object oriented programming with FreshLib ## Objects definition The objects are defined using macro pair "object" and "endobj". The syntax of these macros is following: object OBJ_NAME [, PARENT_NAME] ; here object members are to be defined. endobj The object can contain three types of members: * Fields. They are simply some local labels with data definition, very similar to the structure fields. The fields are defined the same way as the structure fields: object TAnimal .length dd ? .height dd ? .weight dd ? endobj The fields are aimed to provide storage of private for the object data. Of course, it is assembly language and the fields are not hidden from the user, but a good practice is to not use them as an interface. (There are other members that are to be used as an interface). * Methods. The methods are procedures that provide an object engine - the code that to be executed on the object data. They are defined following way: object TAnimal .length dd ? .height dd ? .weight dd ? method .Jump, .height endobj Here we defined a method TAnimal.Jump that will make our animal to jump. The methods can have any number of arguments. Besides the user defined arguments, the method always contain one implicitly defined argument, named .self, containing a pointer to the object itself. The user should not define this argument, neither set it during the method invocation. The object engine itself handle it. Of course the user can use this argument on the method implementation code. Once defined, the method needs to be implemented. Not implemented methods are considered "abstract". They are allowed, but attempt to call them will generate exception. The method implementation is similar to the procedures, but uses a macro "method" instead of "proc". Also, no arguments need to be defined in the method implementation, because they are already known from the object type definition: method TAnimal.Jump begin push eax ecx mov eax, [.self] mov ecx, [eax+TAnimal.height] add ecx, [.height] pop ecx eax return endp * Parameters. The parameters are, similar to the fields, data members. But unlike the fields, they can contain a code, that to generate the data value. The definition of the parameter is by the macro "param": param .ParamName, GET_METHOD, SET_METHOD The GET_METHOD and SET_METHOD define how the value of the parameter is to be get or set by the user. These arguments can have one of the following values: * Name of a field - it means that the value of the parameter is to be get and/or set directly from the object field member. * Name of a method - instead of read or write the value of the parameter from the memory, some object method is called. The GET method should have none arguments (but there is always implicitly defined .self argument). It should return the computed value in EAX register. The SET method should have one argument for the value that have to be set in the parameter. (and .self) * NONE keyword - it means the parameter does not support reading or writing. This way, the user can define read-only or write-only parameters. (And also, parameters that can't be neither read nor write). object TAnimal .length dd ? .height dd ? .weight dd ? .speed dd ? param .Energy, .ComputeEnergy, NONE method .GetEnergy method .Jump, .height endobj method TAnimal.GetEnergy begin mov ecx, [.self] mov eax, [ecx+TAnimal.speed] imul eax, eax imul eax, [ecx+TAnimal.weight] sar eax, 1 ; E = m.v^2/2 return endp ## Object inheritance All objects can be inherited by other method definition. The child object contains all members of the parent object and allows adding new members as well. The methods of the child object can be inherited in the child object. The happens when the user defines a method with the same name as already existing method: object TCat, TAnimal method .Jump, .height endobj method TCat.Jump begin ; code that makes the cat jump not as other animals. return endp ## Object use Once defined, the object can be created and destroyed, a values can be set or get and methods call. This functionality is provided by several macros. Notice that they are made to have syntax very similar to CPU instructions and this way to not affect the "look&feel" of the assembly language program. ### Creating object instance. Once defined, the user can create any number of object instances using the macro "create": create TARGET, OBJECT_TYPE This macro creates an object of type OBJECT_TYPE and put it into TARGET. TARGET can be register or memory location create eax, TCat ; put in EAX a pointer to the object instance. create [MyCat], TCat ; put the pointer in [MyCat] The macro create allocates memory for the instance, sets the proper pointer to the methods table and (if defined) executes the method .Create of the object. Create does not change any registers, unles one is set as TARGET. ### Destroying objects If the object instance is no longer needed, it have to be destroyed by using "destroy" macro. destroy OBJECT For example: destroy [MyCat] If the object is descendent of TObject, the method .Destroy is to be called. TObject is some special name that is aimed to be the root type for all objects in FreshLib. Hardcoding this name is because "destroy" method can't know the type of the destroyed object and this way can't check existing of the method .Destroy; ### Object method execution The method of a object can be executed by using "exec" macro: exec OBJECT, TYPE:METHOD, [ARGUMENTS] For example: exec [MyCat], TCat:Jump, 100 There is another macro "pexec" that acts exactly as "exec", but calls not the object method, but the same method from the parent object type (of course if defined). pexec [MyCat], TCat:Jump, 100 ; it will call TAnimal.Jump, instead of ; the re-defined TCat.Jump ### Object parameter get and set: The parameter getting or setting values is by the macros "get" and "set": get TARGET, OBJECT, TYPE:PARAMETER set OBJECT, TYPE:PARAMETER, NEW_VALUE The TARGET and NEW_VALUE can be register or memory variable (as in mov instruction): get ecx, [MyCat], TAnimal:Energy This line will compute the current energy (see the definition of .Energy above) of [MyCat] and will return it in ECX register. Notice, that the code, generated by this macro is optimal. For example if the parameter is associated with a field and the object is passed by register, the whole line will generate single "mov" instruction. "get" and "set" macros will preserve all registers, except TARGET of course. ### Check object type The user can check whether the object belongs to some type by using "istype" macro: istype OBJECT, TYPE This macro returns ZF flag set if the object belongs to the type or ZF cleared if not. It will not change any registers. For example, see following code: ; object types definitions object TAnimal endobj object TCat, TAnimal endobj object TDog, TAnimal endobj ; instance creation create eax, TCat istype eax, TCat je .yes_cat ; ZF=1 It is a TCat int3 .yes_cat: istype eax, TAnimal je .yes_animal ; ZF=1 Also, it is TAnimal int3 .yes_animal: istype eax, TDog je .yes_dog ; ZF=0 but is it NOT TDog. int3 ; will stop here .yes_dog: ## Objects polymorphism. Polymorphism is one of the main properties of the OOP. It is the ability of the object to execute different code on the same method call, depending on its type. In the context of our library, as long as the types inherit all the methods of its parents and can redefine it, it means, that in the above example, TCat and TDog both have method .Jump, inherited from TAnimal. (In this mean, they are both of type TAnimal), but the implementation of TCat.Jump and TDog.Jump differs. This way, we can use only one code to process both types. create eax, TCat create ebx, TDog exec eax, TAnimal:Jump, 100 exec ebx, TAnimal:Jump, 100 You can see, that the same code will call in the first case TCat.Jump and in the second case TDog.Jump _________________ Tox ID: 48C0321ADDB2FE5F644BB5E3D58B0D58C35E5BCBC81D7CD333633FEDF1047914A534256478D9 |
|||
28 May 2014, 13:38 |
|
revolution 28 May 2014, 14:00
Can you remove the requirement for "begin". This was long ago removed from fasm's "proc" macro and replaced by "local" and "locals".
Which raises this suggestion: Show an example of using local variables in method bodies. |
|||
28 May 2014, 14:00 |
|
JohnFound 28 May 2014, 14:20
revolution wrote: Can you remove the requirement for "begin". This was long ago removed from fasm's "proc" macro and replaced by "local" and "locals". The syntax with "begin" is needed, because FreshLib uses slightly different structure of the local variables frame. This structure is impossible to be made without "begin" macro. Or at least it is syntactically better. (FASM macros can't create such type of local variables). Read more in the FreshLib reference manual. In addition, the macro syntax used in FASM library, because of too heavy use of preprocessor symbols is not able to support some advanced features of Fresh IDE - for example code completion and cross reference functions. There is nothing special in the local variables handling. Here is an example of local variables and arguments use in the method implementation. (and also, parameter set): Code: method MyObj.SetTop, .arg1 .rect RECT begin mov eax, [.arg1] mov [.rect.top], eax set [.self], MyObj:Top, eax return endp _________________ Tox ID: 48C0321ADDB2FE5F644BB5E3D58B0D58C35E5BCBC81D7CD333633FEDF1047914A534256478D9 |
|||
28 May 2014, 14:20 |
|
revolution 28 May 2014, 14:46
I think "impossible" is too strong a word here. For example you could simply make a macro (called localc or clocals or something) instead of begin:
Code: proc ... xor eax,eax clocals common_var1 dd ? endl mov ecx,[common_var1] clocals common_var2 dd ? endl mov edx,[common_var2] ;... |
|||
28 May 2014, 14:46 |
|
JohnFound 28 May 2014, 15:02
revolution wrote: I think "impossible" is too strong a word here. For example you could simply make a macro (called localc or clocals or something) instead of begin: I wrote also "Or at least it is syntactically better". Or you can argue, that two macros is better than one? Quote: BTW: omission of the leading dot in local variable names is also something that is visually more appealing. No, it is not. Omission of the leading dot will make the local variables look the same way as global and this way will lower the code legibility. _________________ Tox ID: 48C0321ADDB2FE5F644BB5E3D58B0D58C35E5BCBC81D7CD333633FEDF1047914A534256478D9 |
|||
28 May 2014, 15:02 |
|
revolution 28 May 2014, 15:07
"begin" only allows the common variables to be declared in one place. Whereas something like clocals/endl allows definitions in any, and multiple, places (or all at the top if so desired).
Do your macros allow for names without the dot, and give the user the choice to use them or not? If you force it then I'd suggest to make to more flexible for the user. |
|||
28 May 2014, 15:07 |
|
Goto page Previous 1, 2, 3 Next < Last Thread | Next Thread > |
Forum Rules:
|
Copyright © 1999-2025, Tomasz Grysztar. Also on GitHub, YouTube.
Website powered by rwasa.