home *** CD-ROM | disk | FTP | other *** search
/ Amiga ISO Collection / AmigaUtilCD2.iso / Programming / Assembler / DVD!OMA1.DMS / in.adf / OOMA / test.asm < prev   
Encoding:
Assembly Source File  |  1994-10-13  |  9.3 KB  |  351 lines

  1.  
  2. ;****************************************************************************
  3. ; Beispiel für die Benutzung der objektorientierten Assemblerprogrammierung.
  4. ;
  5. ; Diese Datei darf nur in Benutzung mit dem Optimierenden Makro-Assembler
  6. ; verwendet werden.
  7. ;****************************************************************************
  8.  
  9.     INCLUDE    "exec/types.i"
  10.     INCLUDE    "macros.i"
  11.     INCLUDE    "OOMA.i"
  12.  
  13.  
  14.     IMPORT    InitObjectModule,RegisterClass,InitializeClasses
  15.     IMPORT    CreateObject
  16.     IMPORT    ClassObject
  17.  
  18.     ; Springe den Startcode an.
  19.     jmp    Start
  20.  
  21.  
  22.  
  23.  
  24.  
  25.  
  26.  
  27.  
  28.  
  29.  
  30. ;****************************************************************************
  31. ; Hier folgt die komplette Rechteck-Klasse. Sie erbt von Object.
  32.  
  33.  
  34.     ; Erst einmal müssen die Instanzvariablen der Klasse Rechteck
  35.     ; plaziert werden. Dies geschieht immer hinter den Variablen der
  36.     ; Superklasse, in diesem Fall "Object". Hier wird also ein Objekt
  37.     ; "Rechteck" definiert.
  38.  STRUCTURE Rechteck,object_SIZEOF    ; wir erben von Object
  39.  UWORD    rechteck_Höhe
  40.  UWORD    rechteck_Breite
  41.  LABEL    rechteck_SIZEOF            ; Größe eines Rechtecks
  42.  
  43.     ; Definiere Methodennamen der Superklasse für unsere Klasse. Dies
  44.     ; entlastet uns davon, sich daran erinnern zu müssen, in welcher
  45.     ; Superklasse die Methode tatsächlich deklariert ist. Damit ist
  46.     ; jede MethodenID mit dem Präfix "Rechteck_" ansprechbar. Jede
  47.     ; MethodenID sollte mit dem Klassennamen als Präfix beginnen.
  48.  SAMEMETHOD    Rechteck_Initialize,Object_Initialize
  49.  SAMEMETHOD    Rechteck_Delete,Object_Delete
  50.     ; Definiere neue Methoden, die es in der Superklasse noch nicht gab.
  51.     ; Dies beginnt immer bei der Klassengröße der Superklasse.
  52.  BEGINMETHOD    Object_ClassSize
  53.  DEFINEMETHOD    Rechteck_SetzeHöhe
  54.  DEFINEMETHOD    Rechteck_SetzeBreite
  55.  DEFINEMETHOD    Rechteck_BerechneUmfang
  56.  DEFINEMETHOD    Rechteck_BerechneFläche
  57.     ; Zum Abschluß muß immer die Klassengröße definiert werden. Sie gibt
  58.     ; von Rechteck erbenden Klassen einen Aufsetzpunkt für neue Methoden.
  59.     ; Wir selber haben dies oben per Object_ClassSize im Makroaufruf
  60.     ; BEGINMETHOD ausgenutzt.
  61.  ENDMETHOD    Rechteck_ClassSize
  62.  
  63.  
  64.  
  65.     ; Jetzt kennen wir die Größe der Klassenstruktur (dies ist nämlich
  66.     ; Rechteck_ClassSize) und können den Platz für die Klassenstruktur
  67.     ; anlegen. Zweckmäßigerweise ist der in einem BSS-Hunk.
  68.     ; Der Name einer Klasse sollte immer mit "Class" beginnen.
  69.     BSS
  70.     CNOP    0,4
  71.     DEFINECLASS    ClassRechteck,Rechteck_ClassSize
  72.     CODE
  73.  
  74.  
  75.  
  76.     ; Melde die Rechteck-Klasse an.
  77. MeldeRechteckAn
  78.     PROC    d0-d1/a0-a2
  79.     lea    ClassRechteck,a0    ; Klassenzeiger
  80.     lea    ClassObject,a1        ; Superklasse
  81.     lea    .array,a2        ; InitArray
  82.     moveq    #rechteck_SIZEOF,d0    ; Objektgröße
  83.     moveq    #Rechteck_ClassSize,d1    ; Klassengröße
  84.     jsr    RegisterClass
  85.     ENDPROC
  86.  
  87.     ; Dieses Feld legt fest, welche Methoden in der Klasse Rechteck
  88.     ; selber vorhanden sind. Es wird immer mit dem ENDOVERWRITE-Makro
  89.     ; abgeschlossen. Wird eine Methode der Klasse hier vergessen, dann
  90.     ; ist entweder der Zeiger der Superklasse oder ein Nullzeiger in der
  91.     ; Methodentabelle eingetragen. Dies führt dann beim Methodenaufruf zu
  92.     ; einem Fehler.
  93. .array    OVERWRITE    Rechteck_Initialize
  94.     OVERWRITE    Rechteck_SetzeHöhe
  95.     OVERWRITE    Rechteck_SetzeBreite
  96.     OVERWRITE    Rechteck_BerechneUmfang
  97.     OVERWRITE    Rechteck_BerechneFläche
  98.     ENDOVERWRITE    ; Abschluß
  99.  
  100.  
  101.  
  102.     ; Dies ist die Methode zum Setzen der Höhe. Jede Methode wird mit
  103.     ; dem Zeiger auf das Objekt in A5 aufgerufen, dieser heißt auch Self.
  104.     ; Das Label dieser Methode hat zusätzlich das Präfix "m_". Daher
  105.     ; lautet es hier "m_Rechteck_SetzeHöhe".
  106.     ; Eingabe:  A5: Self.
  107.     ;        D0: neue Höhe.
  108.  METHODBODY    Rechteck_SetzeHöhe
  109.     PROC
  110.     move    d0,rechteck_Höhe(a5)
  111.     ENDPROC
  112.  
  113.  
  114.  
  115.     ; Das gleiche noch einmal für die Breite.
  116.     ; Eingabe:  A5: Self.
  117.     ;        D0: neue Breite.
  118.  METHODBODY    Rechteck_SetzeBreite
  119.     PROC
  120.     move    d0,rechteck_Breite(a5)
  121.     ENDPROC
  122.  
  123.  
  124.  
  125.     ; Berechne den Umfang des Rechtecks.
  126.     ; Eingabe:  A5: Self.
  127.     ; Ausgabe:  D0: Umfang.
  128.  METHODBODY    Rechteck_BerechneUmfang
  129.      PROC    d1
  130.     move    rechteck_Höhe(a5),d1
  131.     add    d1,d1
  132.     move    rechteck_Breite(a5),d0
  133.     add    d0,d0
  134.     add    d1,d0            ; ergibt Umfang
  135.     ENDPROC
  136.  
  137.  
  138.  
  139.     ; Berechne die Fläche des Rechtecks.
  140.     ; Eingabe:  A5: Self.
  141.     ; Ausgabe:  D0: Fläche.
  142.  METHODBODY    Rechteck_BerechneFläche
  143.      PROC
  144.     move    rechteck_Höhe(a5),d0
  145.     mulu    rechteck_Breite(a5),d0    ; ergibt Fläche
  146.     ENDPROC
  147.  
  148.  
  149.  
  150.     ; Diese Methode gibt es schon in der Superklasse Object. Sie sorgt
  151.     ; hier noch für eine Standardeinstellung eines neuen Rechtecks.
  152.     ; Eingabe:  A5: Self.
  153.  METHODBODY    Rechteck_Initialize
  154.     PROC
  155.     SUPER    a5,Rechteck_Initialize    ; erst Superklasse aufrufen
  156.     move    #1,rechteck_Höhe(a5)    ; jetzt Höhe auf 1
  157.     move    #1,rechteck_Breite(a5)    ; und Breite auch
  158.     ENDPROC
  159.  
  160.  
  161.  
  162.  
  163.  
  164.  
  165.  
  166.  
  167.  
  168.  
  169. ;****************************************************************************
  170. ; Hier folgt die komplette Quadrat-Klasse. Sie erbt von Rechteck. Der Quell-
  171. ; text hier ist einem Format gehalten, das wegen guter Lesbarkeit als Vorbild
  172. ; genommen werden sollte, Prozeduren und Methoden zu deklarieren und zu
  173. ; dokumentieren.
  174.  
  175.  
  176.  
  177. ; Die Objektstruktur für Quadrate.
  178.  
  179.  STRUCTURE Quadrat,rechteck_SIZEOF    ; wir erben von Rechteck
  180.  LABEL    quadrat_SIZEOF            ; keine zusätzlichen Variablen nötig
  181.  
  182. ; Quadrat_SetzeHöhe und Quadrat_SetzeBreite werden hier nicht definiert, da
  183. ; ein Quadrat nur eine Kantenlänge hat.
  184.  SAMEMETHOD    Quadrat_Initialize,Rechteck_Initialize
  185.  SAMEMETHOD    Quadrat_Delete,Rechteck_Delete
  186.  SAMEMETHOD    Quadrat_BerechneUmfang,Rechteck_BerechneUmfang
  187.  SAMEMETHOD    Quadrat_BerechneFläche,Rechteck_BerechneFläche
  188.  BEGINMETHOD    Rechteck_ClassSize
  189.  DEFINEMETHOD    Quadrat_SetzeKante    ; neue Methode
  190.  ENDMETHOD    Quadrat_ClassSize    ; Abschluß
  191.  
  192.  
  193.  
  194.     ; Die Quadrat-Klasse.
  195.     BSS
  196.     CNOP    0,4
  197.     DEFINECLASS    ClassQuadrat,Quadrat_ClassSize
  198.     CODE
  199.  
  200.  
  201.  
  202. ; Melde die Quadratklasse an.
  203.  
  204. MeldeQuadratAn
  205.     PROC    d0-d1/a0-a2
  206.     lea    ClassQuadrat,a0        ; Klassenzeiger
  207.     lea    ClassRechteck,a1    ; Superklasse
  208.     lea    .array,a2        ; InitArray
  209.     moveq    #quadrat_SIZEOF,d0    ; Objektgröße
  210.     moveq    #Quadrat_ClassSize,d1    ; Klassengröße
  211.     jsr    RegisterClass
  212.     ENDPROC
  213.  
  214. .array    OVERWRITE    Quadrat_SetzeKante
  215.     OVERWRITE    Quadrat_BerechneUmfang
  216.     ENDOVERWRITE    ; Abschluß
  217.  
  218.  
  219.  
  220. ;****************************************************************************
  221. ; Berechne den Umfang des Rechtecks. Diese Methode ist schneller als die der
  222. ; Rechteck-Klasse und ersetzt diese daher vollständig.
  223. ; Eingabe:  A5: Self.
  224. ; Ausgabe:  D0: Umfang.
  225.  
  226.  METHODBODY    Quadrat_BerechneUmfang
  227.      PROC
  228.     move    rechteck_Höhe(a5),d0    ; oder rechteck_Breite
  229.     lsl    #2,d0            ; * 4 ergibt Umfang
  230.     ENDPROC
  231.  
  232.  
  233.  
  234. ;****************************************************************************
  235. ; Setze Kantenlänge.
  236. ; Eingabe:  A5: Self.
  237. ;        D0: neue Länge.
  238. ; Ausgabe:  Keine.
  239.  
  240.  METHODBODY    Quadrat_SetzeKante
  241.     PROC
  242.     IFEQ    0
  243.      ; Erste Implementierungsalternative.
  244.      move    d0,rechteck_Höhe(a5)
  245.      move    d0,rechteck_Breite(a5)
  246.     ELSE
  247.      ; Zweite Implementierungsalternative.
  248.      METHOD    a5,Quadrat_SetzeHöhe
  249.      METHOD    a5,Quadrat_SetzeBreite
  250.     ENDC
  251.     ENDPROC
  252.  
  253.  
  254.  
  255.  
  256.  
  257.  
  258.  
  259.  
  260.  
  261.  
  262. ;****************************************************************************
  263.  
  264. Start
  265.     PROC
  266.     LOCAL    einQuadrat,quadrat_SIZEOF    ; Platz auf dem Stack
  267.     SETLOC
  268.  
  269.     ; Zuerst muß das Objektmodul initialisiert werden.
  270.     jsr    InitObjectModule
  271.  
  272.     ; Melde alle Klassen an. Dabei ist die Reihenfolge völlig egal.
  273.     ; Es ist wichtig, vor der Benutzung alle Klassen anzumelden und zu
  274.     ; initialisieren.
  275.     bsr    MeldeQuadratAn
  276.     bsr    MeldeRechteckAn
  277.  
  278.     ; Nun müssen alle Klassen initialisiert werden. Wurde eine Klasse
  279.     ; beim Anmelden vergessen, bekommen wir hier den Zeiger auf diese
  280.     ; Klasse als Fehleranzeige zurück. Der Vererbungsbaum muß also
  281.     ; zusammenhängen.
  282.     jsr    InitializeClasses
  283.     tst.l    d0
  284.     bne    .ende            ; Fehler !!!
  285.  
  286.     ; Nun erzeugen wir ein Rechteck. Sein Speicher wird mit AllocMem
  287.     ; belegt.
  288.     lea    ClassRechteck,a0
  289.     jsr    CreateObject
  290.     move.l    d0,d7
  291.     beq    .ende            ; Fehler !!!
  292.     ; Initialisiere das Rechteck.
  293.     METHOD    d7,Rechteck_Initialize
  294.     ; Jetzt ist das Objekt gebrauchsfähig. Je nach Definition kann eine
  295.     ; Initialize-Methode einer Klasse auch einen Erfolgswert o.ä. zurück-
  296.     ; liefern.
  297.  
  298.     ; Jetzt einmal ein Objekt auf dem Stack. Es ist diesmal ein Quadrat.
  299.     lea    einQuadrat(SP),a4
  300.     INITOBJECT    a4,ClassQuadrat
  301.     METHOD    a4,Quadrat_Initialize
  302.     ; Es wäre auch möglich, den Methodenaufruf wie folgt zu machen:
  303. ;    METHOD    einQuadrat(SP),Quadrat_Initialize
  304.     ; Dies zeigt, daß eine beliebige Adressierungsart als Objektzeiger
  305.     ; erlaubt ist.
  306.  
  307.     ; Setze die Breite des Rechtecks auf 2 und berechne den Umfang.
  308.     ; Der Methodenaufruf landet bei SetzeBreite der Rechteck-Klasse bzw.
  309.     ; bei BerechneUmfang der Rechteck-Klasse.
  310.     moveq    #2,d0
  311.     METHOD    d7,Rechteck_SetzeBreite
  312.     METHOD    d7,Rechteck_BerechneUmfang
  313.     ; Ergebnis in D0.
  314.  
  315.     ; Setze die Kantenlänge des Quadrats auf 3 und berechne die Fläche.
  316.     ; Der Methodenaufruf landet bei SetzeKante der Quadrat-Klasse bzw.
  317.     ; bei BerechneFläche der Rechteck-Klasse, da die Quadrat-Klasse
  318.     ; keine eigene Methode zur Flächenberechnung hat.
  319.     moveq    #3,d0
  320.     METHOD    a4,Quadrat_SetzeKante
  321.     METHOD    a4,Quadrat_BerechneFläche
  322.     ; Ergebnis in D0.
  323.  
  324.     ; Das Rechteck muß noch wieder freigegeben werden. Wäre beim
  325.     ; Initialisieren weiteres Belegen vorgekommen, dann müßte eine
  326.     ; Methode "Rechteck_Cleanup" definiert sein, die nun hier vor dem
  327.     ; Löschen aufgerufen würde.
  328.     ; METHOD  d7,Rechteck_Cleanup   (entfällt hier)
  329.     METHOD    d7,Rechteck_Delete
  330.     ; Das Quadrat hat Speicherplatz auf dem Stack, braucht also nicht
  331.     ; freigegeben zu werden. Hätten wir für dieses Objekt Zusatzspeicher
  332.     ; per AllocMem belegt und in einer Instanzvariablen vermerkt, müßte
  333.     ; wie oben gesagt noch eine Aufräummethode "Quadrat_Cleanup" aufgerufen
  334.     ; werden.
  335.  
  336.     ; Ende des Tests.
  337. .ende    moveq    #0,d0
  338.     ENDPROC
  339.  
  340.  
  341.  
  342.  
  343.  
  344.  
  345.  
  346.  
  347.  
  348.  
  349.     END
  350.  
  351.