Objects Won't Assemble In EasyCode

Started by devilhorse, September 27, 2010, 03:23:12 PM

Previous topic - Next topic

devilhorse

This is some sample code I got that will not compile in EasyCode. I know there is a new ObjAsm Model but i am just learning objects in assemble so I thought I could start here to ease the learning curve. The problem with this code is I always get error messages that say "undefined symbol" for the object instance and the object methods. If I don't create an object it builds fine. Any help on what I must do to get this working is appreciated.

;CIRCLE.ASM
IFNDEF _Circle_
_Circle_ equ 1

include Shape.asm  ; Inherited class info file
; --=====================================================================================--
; #CLASS:    Circle
; #VERSION:  1.0
; --=====================================================================================--
; Built by NaN's Object Class Creator
; © Sept 19, 2001
;
; By NaN ( jaymeson@hotmail.com )
; http://nan32asm.cjb.net
;
; --=====================================================================================--
; #AUTHOR: NaN
; #DATE:   Aug 5, 2001
;
; #DESCRIPTION:
;
;          Multi-Line Description, followed by double period to end.
;          (<b>HTML TAGS ALLOWED!</b>) ..
;
; --=====================================================================================--
; CLASS METHOD PROTOS
; --=====================================================================================--
   Circle_Init    PROTO  :DWORD

; --=====================================================================================--
; FUNCTION POINTER PROTOS
; --=====================================================================================--
   Circ_destructorPto    TYPEDEF  PROTO  :DWORD
   Circ_setRadiusPto    TYPEDEF  PROTO  :DWORD, :DWORD

   Circ_getAreaPto  TYPEDEF PROTO :DWORD
   
; --=====================================================================================--
; CLASS STRUCTURE
; --=====================================================================================--
   CLASS Circle, Circ
      Shape     <>         ; Inherited Class
      CMETHOD setRadius
      Radius     DD    ?
   Circle ENDS

.data

   BEGIN_INIT
      dd offset Circ_destructor_Funct
      dd offset Circ_setRadius_Funct
      dd NULL
   END_INIT

.code
; --=====================================================================================--
; #METHOD:      CONSTRUCTOR (NONE)
;
; #DESCRIPTION: MultiLine Description.  <b>HTML TAGS ALLOWED</b>.
;               End with double period..
;
; #PARAM:       ParamName  MultiLine Param.  <b>HTML TAGS ALLOWED</b>.
;                          First word is paramname, rest is description.
;                          End with double period..
;
; #RETURN:      MultiLine Description.  <b>HTML TAGS ALLOWED</b>.
;               End with double period..
; --=====================================================================================--
Circle_Init  PROC uses edi esi lpTHIS:DWORD
   SET_CLASS Circle INHERITS Shape
   SetObject edi, Circle
   
     OVERRIDE getArea, CirleAreaProc

     DPrint "Circle Created (Code in Circle.asm)"

   ReleaseObject edi
   ret
Circle_Init ENDP

; --=====================================================================================--
; #METHOD:      destructor (NONE)
;
; #DESCRIPTION: MultiLine Description.  <b>HTML TAGS ALLOWED</b>.
;               End with double period..
;
; #PARAM:       ParamName  MultiLine Param.  <b>HTML TAGS ALLOWED</b>.
;                          First word is paramname, rest is description.
;                          End with double period..
;
; #RETURN:      MultiLine Description.  <b>HTML TAGS ALLOWED</b>.
;               End with double period..
; --=====================================================================================--
Circ_destructor_Funct  PROC uses edi lpTHIS:DWORD
   SetObject edi, Circle

     DPrint "Circle Destroyed (Code in Circle.asm)"
     
     SUPER destructor

   ReleaseObject edi
   ret
Circ_destructor_Funct  ENDP

; --=====================================================================================--
; #METHOD:      setRadius (ParamSize)
;
; #DESCRIPTION: MultiLine Description.  <b>HTML TAGS ALLOWED</b>.
;               End with double period..
;
; #PARAM:       ParamName  MultiLine Param.  <b>HTML TAGS ALLOWED</b>.
;                          First word is paramname, rest is description.
;                          End with double period..
;
; #RETURN:      MultiLine Description.  <b>HTML TAGS ALLOWED</b>.
;               End with double period..
; --=====================================================================================--
Circ_setRadius_Funct  PROC uses edi lpTHIS:DWORD, DATA:DWORD
   SetObject edi, Circle

   mov eax, DATA
   mov [edi].Radius, eax
   
     DPrint "Circle Radius Set (Code in Circle.asm)"

   ReleaseObject edi
   ret
Circ_setRadius_Funct  ENDP

; --=====================================================================================--
; #METHOD:      getArea (NONE) ~ Polymorphic...
;
; #DESCRIPTION: MultiLine Description.  <b>HTML TAGS ALLOWED</b>.
;               End with double period..
;
; #PARAM:       ParamName  MultiLine Param.  <b>HTML TAGS ALLOWED</b>.
;                          First word is paramname, rest is description.
;                          End with double period..
;
; #RETURN:      MultiLine Description.  <b>HTML TAGS ALLOWED</b>.
;               End with double period..
; --=====================================================================================--
CirleAreaProc PROC uses edi lpTHIS:DWORD
  LOCAL TEMP
  SetObject edi, Circle
 
  ; This will show SUPER classing the getArea method, by calling the getArea method
  ; found in the inherited class 'Shape'.  Uncomment and compare how the program's
  ; behavior is changed.
 
  SUPER getArea
 
 
  mov eax, [edi].Radius
  mov TEMP, eax
 
  finit
  fild TEMP
  fimul TEMP
  fldpi
  fmul
  fistp TEMP
 
  mov eax, TEMP
  DPrint "Circle Area (integer Rounded) (Code in Circle.asm)"
 
  ReleaseObject edi
  ret
   
CirleAreaProc ENDP
ENDIF


;MAIN.ASM
.Const

.data

.data?

hCircle DD ?

.code
start:

  ; Recuse all inherited constructors.. and do all inits
  DPrint " "
  DPrint " >>> main.asm <<< [ mov hCircle, $NEW( Circle ) ]"
  mov hCircle, $NEW( Circle )

  DPrint " "
  DPrint " >>> main.asm <<< [ METHOD hCircle, Circle, setColor, 7 ]"
  METHOD hCircle, Circle, setColor, 7
 
  DPrint " "
  DPrint " >>> main.asm <<< [ METHOD hCircle, Circle, setRadius, 2 ]"
  METHOD hCircle, Circle, setRadius, 2 
 
  DPrint " "
  DPrint " ------------ TEST POLYMORPHIC METHOD hCircle.getArea ------------- "
  DPrint " "
  DPrint " >>> main.asm <<< [ DPrintValD $EAX( hCircle, Circle, getArea ) , 'Area of hCircle' ]"
  DPrintValD $EAX( hCircle, Circle, getArea ) , "Area of hCircle"
  DPrint " "

  DPrint " ------------ TEST POLYMORPHIC METHOD hCircle.getArea ------------- "
  DPrint " "
  DPrint " >>> main.asm <<< [   DPrintValD $EAX( hCircle, Shape, getArea ) , 'Area of hCircle' ]"
  DPrint " Typing calling this Ojbect Instance as a SHAPE type only! This is the true value"
  DPrint " of Polymorphism.  We dont need to know its a Circle object in order to get the"
  DPrint " proper area of this instance object, that is inherited from Shape."
  DPrint " "
  DPrintValD $EAX( hCircle, Shape, getArea ) , "Area of hCircle"
  DPrint " "
 
 
  DPrint " "
  DPrint " >>> main.asm <<< [ DESTROY hCircle ]"
  DESTROY hCircle
  DPrint " "
  DPrint " "
  DPrint " NOTE: superclassing here, as each destructor call's the SUPER destructor"
  DPrint "       To properly clean up after each class.  To see SUPER classing in"
  DPrint "       in the Polymorphic getArea Function.  Uncomment the SUPER code in"
  DPrint "       CircleAreaProc, and re-compile"


     


; --SHAPE.ASM
=====================================================================================--
; #CLASS:    Shape
; #VERSION:  1.0
; --=====================================================================================--
; Built by NaN's Object Class Creator
; © Sept 19, 2001
;
; By NaN ( jaymeson@hotmail.com )
; http://nan32asm.cjb.net
;
; --=====================================================================================--
; #AUTHOR: NaN
; #DATE:   Aug 5, 2001
;
; #DESCRIPTION:
;
;          Multi-Line Description, followed by double period to end.
;          (<b>HTML TAGS ALLOWED!</b>) ..
;
; --=====================================================================================--
; CLASS METHOD PROTOS
; --=====================================================================================--
   Shape_Init    PROTO  :DWORD

; --=====================================================================================--
; FUNCTION POINTER PROTOS
; --=====================================================================================--
   Shap_destructorPto    TYPEDEF  PROTO  :DWORD
   Shap_getAreaPto    TYPEDEF  PROTO  :DWORD
   Shap_setColorPto    TYPEDEF  PROTO  :DWORD, :DWORD

; --=====================================================================================--
; CLASS STRUCTURE
; --=====================================================================================--
   CLASS Shape, Shap
      CMETHOD destructor
      CMETHOD getArea
      CMETHOD setColor
      Color     DD    ?
   Shape ENDS

.data

   BEGIN_INIT
      dd offset Shap_destructor_Funct
      dd offset Shap_getArea_Funct
      dd offset Shap_setColor_Funct
      dd NULL
   END_INIT

.code
; --=====================================================================================--
; #METHOD:      CONSTRUCTOR (NONE)
;
; #DESCRIPTION: MultiLine Description.  <b>HTML TAGS ALLOWED</b>.
;               End with double period..
;
; #PARAM:       ParamName  MultiLine Param.  <b>HTML TAGS ALLOWED</b>.
;                          First word is paramname, rest is description.
;                          End with double period..
;
; #RETURN:      MultiLine Description.  <b>HTML TAGS ALLOWED</b>.
;               End with double period..
; --=====================================================================================--
Shape_Init  PROC uses edi esi lpTHIS:DWORD
   SET_CLASS Shape
   SetObject edi, Shape

     DPrint "Shape Created (Code in Shape.asm)"

   ReleaseObject edi
   ret
Shape_Init ENDP

; --=====================================================================================--
; #METHOD:      destructor (NONE)
;
; #DESCRIPTION: MultiLine Description.  <b>HTML TAGS ALLOWED</b>.
;               End with double period..
;
; #PARAM:       ParamName  MultiLine Param.  <b>HTML TAGS ALLOWED</b>.
;                          First word is paramname, rest is description.
;                          End with double period..
;
; #RETURN:      MultiLine Description.  <b>HTML TAGS ALLOWED</b>.
;               End with double period..
; --=====================================================================================--
Shap_destructor_Funct  PROC uses edi lpTHIS:DWORD
   SetObject edi, Shape

     DPrint "Shape Destroyed (Code in Shape.asm)"
     
   ReleaseObject edi
   ret
Shap_destructor_Funct  ENDP

; --=====================================================================================--
; #METHOD:      setColor (ParamSize)
;
; #DESCRIPTION: MultiLine Description.  <b>HTML TAGS ALLOWED</b>.
;               End with double period..
;
; #PARAM:       ParamName  MultiLine Param.  <b>HTML TAGS ALLOWED</b>.
;                          First word is paramname, rest is description.
;                          End with double period..
;
; #RETURN:      MultiLine Description.  <b>HTML TAGS ALLOWED</b>.
;               End with double period..
; --=====================================================================================--
Shap_setColor_Funct  PROC uses edi lpTHIS:DWORD, DATA:DWORD
   SetObject edi, Shape

   mov eax, DATA
   mov [edi].Color, eax
     
     DPrint "Shape Color Set!! (Code in Shape.asm)"
     
   ReleaseObject edi
   ret
Shap_setColor_Funct  ENDP

; --=====================================================================================--
; #METHOD:      getArea ()
;
; #DESCRIPTION: MultiLine Description.  <b>HTML TAGS ALLOWED</b>.
;               End with double period..
;
; #PARAM:       ParamName  MultiLine Param.  <b>HTML TAGS ALLOWED</b>.
;                          First word is paramname, rest is description.
;                          End with double period..
;
; #RETURN:      MultiLine Description.  <b>HTML TAGS ALLOWED</b>.
;               End with double period..
; --=====================================================================================--
Shap_getArea_Funct  PROC uses edi lpTHIS:DWORD
   SetObject edi, Shape

     DPrint " "
     DPrint "   SuperClassing!!!!! This allows code re-use if you use this method!!"
     DPrint "   Shape's getArea Method! (Code in Shape.asm)"
     
     mov eax, [edi].Color
     DPrint "   Called from Shape.getArea, (Code in Shape.asm)"
     DPrintValH eax, "   This objects color val is"
     DPrint " "
     
   

   ReleaseObject edi
   ret
Shap_getArea_Funct  ENDP



;DMACROS.INC
;---------------------------------------------------------------------
;  Routines for debugging under assmembly language
;
; Written by E Murphy
;
;  Copyright © March 24, 2000 by the author
;  Complete re-write August 9, 2000
;  Added DLog series September 7, 2000
;
;  Contact author at ernie@surfree.com
;                 or 10206.2341@compuserve.com
;
;---------------------------------------------------------------------
;  USEAGE:
;             The DPrint macros will direct debug information to either
;             a message box (only good for a few messages) or to a console
;             output (even better: show you the program's dynamic action
;             as it happens.
;             
;             Define one of the following BEFORE the include files area:
;
;               DEBUGC  EQU 1       ; console debug print
;
;               DEBUGW  EQU 1       ; windows debug print
;
;
;             DPrint Debug statements may be added as follows:
;
;
;               DPrint "Message here"       ; print a comment
;
;               DPrintValD eax, "EAX"       ; print a comment followed by
;                                           ;  a register value (in decimal)
;
;               DPrintValH eax, "EAX"       ; print a comment followed by
;                                           ;  a register value (in hex)
;
;               DPrintSZ OFFSET szString , "The string is"
;                                           ; print a zero terminated string
;                                           ;  note uses a pointer
;                                           ;  also note also prints a comment string
;
;             To use console output, use the Console build options of Quick Editor
;           This is completely compatable with a windows app, as you will get both
;           the application window, and a console.
;
;             If the console app is started from a dos box, the console output
;           goes there. This output may then be piped to a file.
;
;           IE,
;               c:\somepath>MyApp.exe  >MyApp.txt
;
;             This command dumps the console output to the file MyApp.txt
;
;             When using the windows app option, message boxes will appear. This
;           is only desirable for a very few messages. NOT SUITABLE for 
;           monitoring the message loop for sure.
;         
;             Also note, these functions will work quite happily on displaying
;           value in memory, so that this is quite legal:
;           
;               DPrintValH SomeVar, "SomeVar is" ; print a comment followed by
;                                                ;  a memory variable value (in hex)
;           
;
;
; LOGGING TO FILES:
;           
;           The Dlog series of macros perform the same actions as the DPrint series,
;           but send their output to a text file. 
;           
;           Dlog differs in that the file must be opened and closed, and appropiate
;           macros for this are included
;           
;           
;           DLog Debug statements may be added as follows:
;
;
;             Define the following BEFORE the include files area:
;
;               DEBUGL  EQU 1       ; console debug print
;
;
;               DLogStart "MyApp.txt"     ; opens the file for information
;                                         ;  this exampl names the file
;                                         ;  "MyApp.txt"
;                                         ;  MUST be performed before any
;                                         ;  other DLog statement
;
;               DLogEnd                   ; Closes the file, place just before your
;                                         ;  your app terminates. The file will
;                                         ;  be closed by the OS if your program
;                                         ;  crashes before normal termination.
;
;               DLog "Message here"       ; print a comment
;
;               DLogValD eax, "EAX"       ; print a comment followed by
;                                         ;  a register value (in decimal)
;
;               DLogValH eax, "EAX"       ; print a comment followed by
;                                         ;  a register value (in hex)
;
;               DLogSZ OFFSET szString , "The string is"
;                                         ; print a zero terminated string
;                                         ;  note uses a pointer
;                                         ;  also note also prints a comment string
;
;
;
;---------------------------------------------------------------------

DLogStart MACRO string:REQ
    IFDEF DEBUGL
        .data
        DMacros_szFileName      BYTE    string, 0
        DMacros_hFile           DWORD   ?
        DMacros_bc              DWORD   ?
        .code
        invoke CreateFile, ADDR DMacros_szFileName, GENERIC_WRITE,
                           FILE_SHARE_READ or FILE_SHARE_WRITE,
                           NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL
        mov DMacros_hFile, eax
    ENDIF
ENDM

DLogEnd MACRO
    IFDEF DEBUGL
        invoke SetEndOfFile, DMacros_hFile
        invoke CloseHandle, DMacros_hFile
    ENDIF
ENDM

DLog MACRO string:req
    LOCAL DMacros_szMessage
    IFDEF DEBUGL
        ; do a console version Print Message
        .data
        DMacros_szMessage   BYTE    string, 13, 10, 0
        .code
        pushad
        invoke lstrlen, ADDR DMacros_szMessage
        invoke WriteFile, DMacros_hFile, ADDR DMacros_szMessage, eax, ADDR DMacros_bc, NULL
        popad
    ENDIF
ENDM

DLogValH MACRO value:req, string:req
    LOCAL DMacros_szNumBuffer, DMacros_szMessage, DMacros_crlf
    IFDEF DEBUGL
        .data
        DMacros_szNumBuffer     BYTE 15 DUP(?)
        DMacros_crlf            BYTE 13,10,0
        DMacros_szMessage       BYTE string, ":  ",0
        .code
        pushad
        invoke dw2ah, value, ADDR DMacros_szNumBuffer 
        invoke lstrlen, ADDR DMacros_szMessage
        invoke WriteFile, DMacros_hFile, ADDR DMacros_szMessage, eax, ADDR DMacros_bc, NULL
        invoke lstrlen, ADDR DMacros_szNumBuffer
        invoke WriteFile, DMacros_hFile, ADDR DMacros_szNumBuffer, eax, ADDR DMacros_bc, NULL
        invoke lstrlen, ADDR DMacros_crlf
        invoke WriteFile, DMacros_hFile, ADDR DMacros_crlf, eax, ADDR DMacros_bc, NULL
        popad
    ENDIF
ENDM

DLogValD MACRO value:req, string:req
    LOCAL DMacros_szNumBuffer, DMacros_szMessage, DMacros_crlf
    IFDEF DEBUGL
        .data
        DMacros_szNumBuffer     BYTE 15 DUP(?)
        DMacros_crlf            BYTE 13,10,0
        DMacros_szMessage       BYTE string, ":  ",0
        .code
        pushad
        invoke dwtoa, value, ADDR DMacros_szNumBuffer 
        invoke lstrlen, ADDR DMacros_szMessage
        invoke WriteFile, DMacros_hFile, ADDR DMacros_szMessage, eax, ADDR DMacros_bc, NULL
        invoke lstrlen, ADDR DMacros_szNumBuffer
        invoke WriteFile, DMacros_hFile, ADDR DMacros_szNumBuffer, eax, ADDR DMacros_bc, NULL
        invoke lstrlen, ADDR DMacros_crlf
        invoke WriteFile, DMacros_hFile, ADDR DMacros_crlf, eax, ADDR DMacros_bc, NULL
        popad
    ENDIF
ENDM

DLogSZ  MACRO  pstring:req, string
    LOCAL DMacros_szMessage, DMacros_crlf, DMacros_spaces
    IFDEF DEBUGL
        ; do a console version Print Message
        .data
        DMacros_crlf            BYTE 13,10,0
        IFNB <string>
            DMacros_szMessage   BYTE  string, 0
            DMacros_spaces      BYTE  ":  ", 0
        ENDIF
        .code
        pushad
        IFNB <string>
            invoke lstrlen, ADDR DMacros_szMessage
            invoke WriteFile, DMacros_hFile, ADDR DMacros_szMessage, eax, ADDR DMacros_bc, NULL
            invoke lstrlen, ADDR DMacros_spaces
            invoke WriteFile, DMacros_hFile, ADDR DMacros_spaces, eax, ADDR DMacros_bc, NULL
        ENDIF
        invoke lstrlen, pstring
        invoke WriteFile, DMacros_hFile, pstring, eax, ADDR DMacros_bc, NULL
        invoke lstrlen, ADDR DMacros_crlf
        invoke WriteFile, DMacros_hFile, ADDR DMacros_crlf, eax, ADDR DMacros_bc, NULL
        popad
    ENDIF
ENDM


DPrint MACRO string:req
    LOCAL szMessage
    IFDEF DEBUGW
        ; do a windows version Print Message
        IFNDEF szAppName
            .data
            szAppName   BYTE    "Debug Message", 0
        ENDIF
        .data
        szMessage   BYTE    string,0
        .code
        pushad
        invoke MessageBox, NULL, ADDR szMessage, ADDR szAppName, MB_OK
        popad
    ENDIF
    IFDEF DEBUGC
        ; do a console version Print Message
        .data
        szMessage   BYTE    string, 13, 10, 0
        .code
        pushad
        invoke StdOut, ADDR szMessage
        popad
    ENDIF
ENDM

DPrintValD MACRO value:req, string:req
    LOCAL szNumBuffer, szMessage, crlf
    IFDEF DEBUGW
        ; do a windows version Print Message
        .data
        szNumBuffer     BYTE 15 DUP(?)
        szMessage   BYTE string, ":  ",0
        .code
        pushad
        mov eax, value
        invoke dwtoa, eax, ADDR szNumBuffer
        invoke MessageBox, NULL, ADDR szNumBuffer, ADDR szMessage, MB_OK
        popad
    ENDIF
    IFDEF DEBUGC
        ; do a console version Print Message
        .data
        szNumBuffer     BYTE 15 DUP(?)
        crlf            BYTE 13,10,0
        szMessage       BYTE string, ":  ",0
        .code
        pushad
        invoke dwtoa, value, ADDR szNumBuffer 
        invoke StdOut, ADDR szMessage
        invoke StdOut, ADDR szNumBuffer     
        invoke StdOut, ADDR crlf   
        popad
    ENDIF
ENDM


DPrintValH MACRO value:req, string:req
    LOCAL szNumBuffer, szMessage, crlf
    IFDEF DEBUGW
        ; do a windows version Print Message
        .data
        szNumBuffer     BYTE 15 DUP(?)
        szMessage   BYTE string, ":  ",0
        .code
        pushad
        mov eax, value
        invoke dw2ah, eax, ADDR szNumBuffer
        invoke MessageBox, NULL, ADDR szNumBuffer, ADDR szMessage, MB_OK
        popad
    ENDIF
    IFDEF DEBUGC
        ; do a console version Print Message
        .data
        szNumBuffer     BYTE 15 DUP(?)
        crlf            BYTE 13,10,0
        szMessage       BYTE string, ":  ",0
        .code
        pushad
        invoke dw2ah, value, ADDR szNumBuffer 
        invoke StdOut, ADDR szMessage
        invoke StdOut, ADDR szNumBuffer     
        invoke StdOut, ADDR crlf   
        popad
    ENDIF
ENDM


DPrintSZ  MACRO  pstring:req, string
    LOCAL szMessage, crlf, spaces
    IFDEF DEBUGW
        ; do a windows version Print Message
        IFNDEF szAppName
            .data
            szAppName   BYTE    "Debug Message", 0
        ENDIF
        IFNB <string>
            .data
            szMessage   BYTE    string,0
        ENDIF
        .code
        pushad
        IFNB  <string>
            invoke MessageBox, NULL, pstring, ADDR szMessage, MB_OK
        ELSE
            invoke MessageBox, NULL, pstring, ADDR szAppName, MB_OK
        ENDIF
        popad
    ENDIF
    IFDEF DEBUGC
        ; do a console version Print Message
        .data
        crlf            BYTE 13,10,0
        IFNB <string>
            szMessage   BYTE  string, 0
            spaces      BYTE  ":  ", 0
        ENDIF
        .code
        pushad
        IFNB <string>
            invoke StdOut, ADDR szMessage
            invoke StdOut, ADDR spaces
        ENDIF
        invoke StdOut, pstring
        invoke StdOut, ADDR crlf   
        popad
    ENDIF
ENDM



; OBJECTS.INC                 VERSION:  2.27                                  SEPT 19, 2001
; --=====================================================================================--
; This is the MACRO definitions needed to properly sustain the MASM32 OBJECT model
; developed by NaN (Jaymeson@Hotmail.com) and Thomas (_thomas_@runbox.com).
;
; Copyright © 9/19/01  Jaymeson Trudgen and Thomas Bleeker.  If objects become a major
;                      portion of any project, please make an attempt to acknowledge
;                      the use of our work by any means, thank you.
;
; For educational use only. Any commercial re-use only by written license.
;
;
; NOTE:  MASM OBJECTS RESERVED LABELS ARE:  "Class", "Inher", "AbvNa"

O_WARNINGS equ 1   ; COMPILED WARNING OF MISMATCHED INIT DATA TO CLASS SIZE.
                   ; COMMENT THIS OUT IF NOT WANTED.

; --=====================================================================================--
; MACRO LIST INDEX:
; --=====================================================================================--
;   NEWOBJECT       To create new Object Instances
;   METHOD          To call Instance methods
;   DESTROY         To destroy existing object instances (MUST)
;   SetObject       To set Class to register
;   ReleaseObject   To release Class from register
;   OVERRIDE        To assign a new method offset in any instance
;   SET_CLASS       To assign class inits, and do inheritance if needed. (MUST)
;   SUPER           To provide super classing support of polymorphic methods.
;
;   $EAX()          Accelerated METHOD, returns in eax
;   $EBX()          Accelerated METHOD, returns in ebx
;   $ESI()          Accelerated METHOD, returns in esi
;   $EDI()          Accelerated METHOD, returns in edi
;   $NEW()          Accelerated NEWOBJECT, returns in eax
;   $SUPER()        Accelerated SUPER, returns in eax
;   $DESTROY()      Accelerated DESTROY, returns in eax
;   $invoke()       Accelerated invoke, returns in eax
;
;   BEGIN_INIT      To label Class initialization info in data segment (MUST)
;   END_INIT        To Declair the end of class initialization data (MUST)
;
;   CLASS           To Declair Abbreviated Class Name used in class definitions (MUST)
;   SET_INTERFACE   To Declair Abbreviated Interface and Abv Name (MUST)
;   CMETHOD         TO Declair a Class Method in a Class or Interface structure
;
; --=====================================================================================--
; Set Non case sensitive macros
; --=====================================================================================--
    method     TEXTEQU <METHOD>
    destroy    TEXTEQU <DESTROY>
    newobject  TEXTEQU <NEWOBJECT>
    override   TEXTEQU <OVERRIDE>
    set_class  TEXTEQU <SET_CLASS>
    super      TEXTEQU <SUPER>
    begin_init TEXTEQU <BEGIN_INIT>
    end_init   TEXTEQU <END_INIT>

; --=====================================================================================--
; This macro is used to create a new instance of a class definition.  The instances
; are taken from the local heap.  As well this macro will call the constructor of the
; class to do any needed initializations.
;
; SYNTAX:  NEWOBJECT ClassName, Constructor Arguments (if any)
; RETURN:  eax == Handle of Object Instance
;
; GENERATED CODE:
;
;    invoke GetProcessHeap
;    invoke HeapAlloc, eax, NULL, SIZEOF ObjType
;    push   eax
;    invoke ObjType&_Init, eax (, &args)
;    pop    eax
;   
; --=====================================================================================--
NEWOBJECT MACRO ObjType:REQ, args:VARARG
     invoke GetProcessHeap
     invoke HeapAlloc, eax, NULL, SIZEOF ObjType

     push eax
     IFNB <args>
        invoke ObjType&_Init, eax, &args
     ELSE
        invoke ObjType&_Init, eax
     ENDIF
     pop eax
ENDM

; --=====================================================================================--
; This Macro is used to call instance methods of a given class.  This macro is allows for
; user flexibility of having either and indirect object label or direct registers for the
; object handle.  Some classes are designed to act differently depending on the initialization
; parameters passed to their constructors, so this macro also supports optional arguments
; if the constructor requires it.
;
;    SYNTAX: (INDIRECT)
;
;       METHOD hMyObject, ClassName, MethodName (, Method arguments)
;
;    SYNTAX: (DIRECT)
;     
;       METHOD ecx, ClassName, MethodName (, Method arguments)
;
;    RETURN: eax == the return value from the method called (if provided)
;
;    CODE GENERATED: (INDIRECT)
;       mov edx, hMyObject
;       invoke (ClassName PTR [edx]).Function, edx (, args)
;
;    CODE GENERATED: (DIRECT)
;       invoke (ClassName PTR [reg]).Function, reg (, args)
;
; --=====================================================================================--


METHOD MACRO pInterface:REQ, Interface:REQ, Function:REQ, args:VARARG
   
   IF (OPATTR (pInterface)) AND 00010000b
        IFNB <args>   
           invoke (Interface PTR[&pInterface]).&Function, pInterface, &args
        ELSE
           invoke (Interface PTR[&pInterface]).&Function, pInterface
        ENDIF
    ELSE
        mov edx, pInterface
        IFNB <args>
           FOR arg, <args>
              IFIDNI <&arg>, <edx>
                .ERR <edx is not allowed as a Method parameter with indirect object label>
              ENDIF
           ENDM
           invoke (Interface PTR[edx]).&Function, pInterface, &args
        ELSE
           invoke (Interface PTR[edx]).&Function, pInterface
        ENDIF
    ENDIF
ENDM

; --=====================================================================================--
; This MACRO is used to destroy any class instance.  This macro makes use of the special
; fact that EVERY destructor of ANY class is ALWAYS the first method entry in the instance
; object.  For this reason this macro doesnt need to know what object type the instance
; is to properly destroy it.  This design allows for insurance that clean up will always
; get done for any kind of object nesting.
;
; NOTE: The instance object's destructor is called before the object is returned to the
;       heap.
;
; SYNTAX:  DESTROY hMyInstance  (or)  DESTROY edx (etc.)
; RETURN:  eax == Any return value from the Instance object's destructor.
;
; GENERATED CODE: (Straight forward)
;
; --=====================================================================================--
DESTROY MACRO pName
     mov eax, pName
     push eax
     call dword ptr [eax]
         
     push eax
     invoke GetProcessHeap
     invoke HeapFree, eax, NULL, pName
     pop eax
ENDM     

; --=====================================================================================--
; This macro is used to help method coding.  This macro will assign a class definition
; structure to the register passed.  This will shorten mov's etc. with any private variables
; in the object.
;
; NOTE: You MUST use the corresponding "ReleaseObject" at the end of your method or
;       unpredictable problems/errors/crashes could arise.  Also, only one register
;       should be Set at any point in your code.
;
; SYNTAX:  SetObject edi, MyClass
;          mov [edi].Variable1, NULL         ; NULL Private variable
;          lea eax, [edi].Variable1          ; Get address of private Variable in eax
;          ...
;          ReleaseObject edi                 ; MUST release before leaving method.
;          ret
;
; GENERATED CODE:
;
;          mov reg, lpTHIS
;
; --=====================================================================================--
SetObject MACRO reg:REQ, objtype:REQ
mov  reg, lpTHIS
assume reg:PTR objtype
ENDM

; --=====================================================================================-- 
; This Macro is used to release a register from its class assignment (from SetObject).
; Please refer to the SetObject for more info on its use.
;
; SYNTAX: ReleaseObject edi
;
; GENERATED CODE:  (NONE = Compiler level only)
;
; --=====================================================================================-- 
ReleaseObject MACRO reg:REQ
assume reg: nothing
ENDM

; --=====================================================================================--
; This macro is used mainly for POLYMORPHIC assignments.  It is used to OVERRIDE a
; set method's function pointer to a new one, thus having a new unique method code for
; the same method name.
;
; NOTE: This MACRO is generic, and can alter any METHOD from an instanciated object.  For
;       this reason use with some caution.  Also, function PROTO's must agree with the
;       previous function for this to work.
;
; NOTE: This MACRO must be used in conjunction with the SetObject/ReleaseObject MACROS.
;       and the Register used must be EDI. (This is the default register used in the
;       MASM32 Object Model ~ its best use is in the constructors of class definitions).
;
; SYNTAX: 
;       OVERRIDE MethodName, NewFunctionProc
;
; CODE GENERATED:
;       mov [edi].MethodName, offset NewFunctionProc
;
; --=====================================================================================--
OVERRIDE MACRO AName:REQ, MCode:REQ
     mov [edi].&AName, offset &MCode
ENDM

; --=====================================================================================--
; This MACRO is used for initializing instances with correct function pointing.  It is
; required in the constructor of all object classes definitions.  This macro is complicated
; but the code generated is relatively short.  Its main purpose is to fill a new instance
; with the proper method pointers and initialize variables in the instance structure.
; Previous version of Objects.inc, simply did this by "mov [edi].StuctEntry, Stuff", but
; this version replaces this by using Memory Copy from the .Data segment.  This implies that
; in order for this to work, the "ClassName_initdata" found in the data segment must have
; the proper offsets, and variable initializations in the same order as the Class definition.
;
; Secondly, this also does Inheritance if the key word "INHERITS" is found following the
; class name.  Inheritance recursively digresses to the inherited classes where this macro
; should also exist, thus it becomes recursive, and essentially the same action is take to
; properly initialize the instance structure (with a Memory Copy loop).
;
; NOTE: No polymorphic action is take at this level, you must manual override any methods
;       in the constructor *AFTER* this macro call.  Otherwise the overridden method will
;       be corrected by this macro.
;
; NOTE: For proper inheritance the class to be inherited from must be included in the
;       the class definition previous to this macro.
;
; SYNTAX: (No Inheritance)
;       SET_CLASS Shape                      ; this class is a shape class
;
; SYNTAX: (With Inheritance, no constructor arguments)
;       SET_CLASS Circle INHERITS Shape (, constructor arguments)
;
;   NOTE: 1) There is no comma between the class and the inherited class, only the
;            word "INHERITS"
;         2) The constructor arguments are for the inherited class' constructor, if
;            it was designed to require such.
;
;
; NOTE: 'Class' and 'Inher' are now reserved TEXTEQU's for proper object operations,
;       No other source must alter theses two keywords, or unpredictable results will
;       happen.
;
; RETURN: (Nothing), but ECX is altered.
;
; GENERATED CODE: (Class with no inheritance)
;        push    esi
;     push    edi
;     cld   
;     mov    esi, CONSTANT
;     mov    edi, lpTHIS
;     mov    ecx, CONSTANT
;     shr    ecx, 2
;     rep    movsd
;     mov    ecx, CONSTANT
;     and    ecx, 3
;     rep    movsb
;     pop    edi
;     pop    esi
;
; GENERATED CODE: (Class with inheritance)
;        push    esi
;     push    edi
;      cld
;     mov    edi, lpTHIS
;     mov    esi, CONSTANT
;     mov     eax, [esi]
;     mov     [edi], eax
;      add     esi, 4     
;      add     edi, Inher
;      mov    ecx, CONSTANT
;     shr    ecx, 2
;     rep    movsd
;     mov    ecx, CONSTANT
;     and    ecx, 3
;     rep    movsb
;     pop    edi
;     pop    esi
;
; --=====================================================================================--
SET_CLASS MACRO AName:REQ, args:VARARG
     LOCAL Where, sz1, sz2, sz3, @InitValLabel, @InitValSizeLabel
     LOCAL bk1, bk2, ck1, ck2
     
     Inher TEXTEQU <>

     ; See if there is the word 'INHERITS'
     Where equ @InStr(1,<AName>,<INHERITS> )
     IFE Where eq 0
      Inher SUBSTR <AName>, Where + 9        ; Get Inheriting Class
     ENDIF

     ; Do size equate:  "THIS_CLASS_initsize equ sizeof THIS_CLASS"
     sz1 CATSTR Class,<_initsize equ sizeof >,<Class>
     
     ; If there was no Inheriting class present
     IF Where eq 0
     sz1                                     ; Do it Init Size!!!!!

     ; Do Initializations and Inheriting
     @InitValLabel     CATSTR Class,<_initdata>   ; LABEL: "THIS_CLASS_initdata"
     @InitValSizeLabel CATSTR Class,<_initend>    ; LABEL: "THIS_CLASS_initend"

     ck2 equ &@InitValSizeLabel
     
       ; No inheriting
        push    esi
     push    edi
     cld   
%     mov    esi, offset @InitValLabel
     mov    edi, lpTHIS
%     mov    ecx, @InitValSizeLabel
     shr    ecx, 2
     rep    movsd
%     mov    ecx, @InitValSizeLabel
     and    ecx, 3
     rep    movsb
     pop    edi
     pop    esi
  ELSE           ; it inherits!...

      bk2 INSTR Inher, <INTERFACE>
     IFE bk2 eq 0
        ; Interface, so only set size...
        sz1                                     ; Do it Init Size!!!!!
       
        Inher SUBSTR Inher, 10
       
     ; Do Initializations and Inheriting
     @InitValLabel     CATSTR Class,<_initdata>   ; LABEL: "THIS_CLASS_initdata"
     @InitValSizeLabel CATSTR Class,<_initend>    ; LABEL: "THIS_CLASS_initend"
     
     ck2 equ &@InitValSizeLabel + sizeof Inher - 4     
       
     ELSE
        ; not an interface, do normal inheritance..
       
         sz1 CATSTR sz1,< - sizeof >,Inher
         sz1                                     ; Do it Init Size!!!!!

     ; Do Initializations and Inheriting
     @InitValLabel     CATSTR Class,<_initdata>   ; LABEL: "THIS_CLASS_initdata"
     @InitValSizeLabel CATSTR Class,<_initend>    ; LABEL: "THIS_CLASS_initend"
     
     ck2 equ &@InitValSizeLabel - 4
     
       ; Inheriting Class 'Inher' is present!
       
       ; Build the invoke string: "invoke INHER_CLASS_Init, lpTHIS"
       sz2 CATSTR <invoke >,Inher,<_Init, lpTHIS> 
       IFNB <args>
          sz2 CATSTR sz2, <, >, <&args>
       ENDIF
       sz2                         ; invoke the inherited constructor
     ENDIF     
     
       ; Modify the destructor, and do THIS_CLASS function pointing
        push    esi
     push    edi
       cld
       
       ; replace the destructor...
     mov    edi, lpTHIS
%     mov    esi, offset @InitValLabel
     mov     eax, [esi]
     mov     [edi], eax

       ; now do rest of Class's inits for THIS_CLASS..
       add     esi, 4                        ; mov to next DWORD
%      add     edi, Inher
%     mov    ecx, (@InitValSizeLabel - 4)     
     shr    ecx, 2
     rep    movsd
%     mov    ecx, (@InitValSizeLabel - 4)
     and    ecx, 3
     rep    movsb
    
     pop    edi
     pop    esi
     
     ENDIF   

  IFDEF O_WARNINGS

     ; Do basic checking and provide warning if needed
     ; ----------------------------------------------------
     sz2 CATSTR Class,<_initsize>
     ck1 equ &sz2
     
     IFE ck1 eq ck2
       sz2 CATSTR <# Warning # >,Class
       %echo
       %echo ###########
       %echo sz2 size differs from initialized size
       %echo ###########
       %echo
     endif
     
  ENDIF
     
ENDM     

; --=====================================================================================--
; This macro is used to provide support for super classing of inherited methods.  This can
; be called from within ANY method code.  Its purpose is to call the inherited class method
; that has be overridden in a polymorphic action, such that in some cases code re-use can
; be achieved, since OVERRIDE simply ignores the inherited method code.
;
; SYNTAX:
;     SUPER MethodName (, args )
;
; RETURN: eax == any return from the super classed method.
;
; NOTE:
;   This works by use of the XXX_initdata tables in the data segment that
;   is used to instanciated classes.  It basically checks to see if the method
;   trying to be super'd is within one level of inheritance, and if so, it will
;   calculate the and mov into esi, the function pointer of the super class for this
;   method.
;
;   IE)  If Donut inherits Circle
;           and Circle inherits Shape
;
;&nb

Ramon Sala

Hi devilhorse,

Thanks for using Easy Code.

Could you send the whole project to me (asm@easycode.cat)? I will try to find the problem.

Ramon
Greetings from Catalonia