home *** CD-ROM | disk | FTP | other *** search
- (*---------------------------------------------------------------------------
- :Program. M2ACode
- :Author. Fridtjof Björn Siebert (Amok)
- :Address. Nobileweg 67, D-7000 Stuttgart-40
- :Phone. (0)711/822509
- :Shortcut. [fbs]
- :Version. 0.99
- :Date. 27.03.88
- :Copyright. Intern
- :Language. Modula-II
- :Translator. M2Amiga
- :Imports. none.
- :Contents. Maschinensprache->Modula Converter
- :Bugs. M2Amiga isn't able to convert some Types, such as LONGINT to
- :Bugs. WORD. REG() gives a LONGINT, so a WORD can't be a result.
- ---------------------------------------------------------------------------*)
-
- =============================================================================
- = = = M2ACode = = =
-
- © Copyright 1988 by
- Fridtjof Siebert
- Nobileweg 67
- D-7000 Stuttgart 40 (Stammheim)
- Tel: (0)711/822509
- =============================================================================
-
- M2ACode ist für und mit dem Meier-Vogt-Modula-II-Compiler geschrieben. Es
- ermöglicht, PC-relative Maschinenroutinen in Modulaprogramme einzubinden.
- Dies ist normalerweise nur über Libraries, oder bei kleinen Routinen durch
- direktes Berechnen des Maschinencodes möglich. Nun können mit einem
- Assembler (z.B. Profimat) geschriebene Assemblerprogramme leicht in Module
- umgewandelt werden.
-
- Um PC-relative Maschinenroutinen zu schreiben, muß man lediglich im Assem-
- blermenü `PC-relativ' anwählen. Probleme gibt es nur, wenn man in eine ab-
- solute Addresse schreiben möchte. Dazu muß man sie in ein Addressregister
- laden und dann indirekt addressieren:
- LEA Addresse,Ax
- MOVE yyyy,(Ax)
- Möchte man in mehrere nahe beieinanderliegende Addressen schreiben, kann
- man auch mit Offset addressieren.
-
- M2ACode erzeugt aus Maschinensprachecode compilierbare Definitions- und
- Implementationmodule. Dabei wird der Code mit der von SYSTEM exportierten
- INLINE()-Funktion eingefügt.
-
- Es ist möglich, Werte in beliebigen Registern zu übergeben und von dort
- zurückzuerhalten.
-
- Mit M2ACode ist es nur möglich, maximal eine Maschinenspracheprozedur in
- ein Modul umzuwandeln. Doch kann man leicht mit einem guten Texteditor
- verschiedene Prozeduren in einem Modul zusammenzufassen.
-
- Syntax von M2ACode:
-
- M2ACode Src {-cRx:TYPE|vRx:TYPE|-sRx} [-rRx:TYPE] [-sall] [-d] [-e] [-p]
-
- Die Parameter in den geschweiften Klammern können beliebig oft angegeben
- werden, die in eckigen Klammern sind optional. Die Reihenfolge der
- Parameter ist egal. Wird kein Parameter angegeben, wird eine Kurzbe-
- schreibung der Syntax ausgegeben.
-
- Src ist der Name des PC-relativ assemblierte Maschinencodes. Normal
- assemblierter, ausführbarer Code kann nicht verwendet werden. Dies
- dürfte allerdings nicht allzu schlimm sein, da PC-relativer normal-
- erweise schneller ist als absoluter Code. Die Maschinenroutine muß im
- aktuellen Directory stehen. Der erzeugte Modulname und Procedurename
- wird aus diesem Namen erzeugt, indem ein eventuelles Suffix (.xxx)
- abgeschnitten wird. Für den Namen des Definition- und
- Implementationmoduls wird .def bzw. .mod angehängt.
-
- Rx ist ein 68000-Register. Es kann groß und klein geschrieben werden: D2,
- a5, A2, etc.
-
- TYPE ist ein zum Typ ADDRESS kompatibler Modula-II-Typ. Beispiele sind
- LONGCARD, INTEGER, POINTER, etc.
-
- Die Parameter:
-
- -c teilt M2ACode mit, daß der Maschinenroutine ein konstanter Wert vom Typ
- TYPE im Register Rx übergeben wird. Zur Übergabe wird der Wert in den
- Typ ADDRESS umgewandelt.
-
- -v ist das Gegenstück zu -c für variable Parameter. Nach Beendigung der
- Maschinenroutine wird der dann in Rx stehende Wert zurück in TYPE
- umgewandelt und von der Procedure in die Übergebene Variable
- geschrieben.
-
- -r wird für Routinen verwendet, die ein Ergebnis mit RETURN zurückgeben.
- Der Inhalt von Rx wird nach der Maschinenroutine in TYPE umgewandelt
- und mit RETURN an das aufrufende Modul übergeben.
-
- -s rettet das Register Rx. Damit ist es möglich, für Modula wichtige
- Register auf den Stack zu retten. Die Maschinenroutine braucht sich
- dann nicht um die Zwischenspeicherung der Register zu kümmern.
- Wahrscheinlich können D0, D1, A0 und A1 frei verwendet werden. Die
- anderen Register sollten sicherheitshalber gespeichert werden. Register
- werden zuerst gerettet, bevor ihnen Parameter übergeben werden. Es ist
- also z. B. möglich, die Addresse einer Library in A6 zu übergeben, wenn
- man A6 mit -sA6 rettet. Gespeicherte Register werden nach der
- Beendigung der Maschinenroutine wieder zurückgeladen. Achtung: -s
- funktioniert zusammen mit -r nicht ! (sorry)
-
- -sall ermöglicht es, alle Register, außer A7, ohne jedes einzeln hinzu-
- schreiben, auf den Stack zu retten.
-
- -d löscht ein Nullwort am Ende des Maschinencodes, wenn es auf einer nicht
- durch 4 teilbaren Addresse liegt. Dies ist nötig, da Profimat die Länge
- des Maschinencodes immer auf Vielfache von 4 aufrundet. Das evt.
- angefügte Wort (ein oder drei BYTE sollten es nicht sein !!!) ist eine
- Null. Da 0000H dem Assemblerbefehl `ori.b #xx' entspricht, wird das
- erste Wort des nächsten Befehls übersprungen. Das kann verheerende
- Folgen haben. Es ist also empfehlenswert, wenn man sicher ist, daß
- das letzte Wort des wirklichen Programmes keine 0 ist, -d anzugeben.
- Ansonsten muß man das letzte Wort eventuell von Hand aus dem
- erzeugten Implementation- module entfernen.
-
- -e fügt ein `(*$E-*)' in das Implementation-Module ein. Dadurch wird
- beim Compilieren der normale Code zum Einsteigen und Verlassen einer
- Procedure weggelassen. LINK und UNLNK fällt weg, wodurch keine
- Variablen in der Procedure verwendet werden können. Am Ende der
- Procedure steht kein RTS. Die Assemblerroutine muß also den RTS-Befehl
- enthalten. Register mit -s nicht gespeichert und mit -r nicht
- zurückgegeben werden, da der Rücksprung in der Routine selbst steht.
- Wird -p nicht angegeben darf die Routine kein RTS enthalten. Die
- Routine muß dann so geschrieben sein, daß der PC nach ihrer Beendigung
- hinter ihr steht.
-
- -p Erzeugt eine Prozedur, der die Parameter direkt in die Register
- übergeben werden. Dadurch wird der Programmablauf schneller. Es ist
- jedoch nicht möglich, Register, denen Werte übergeben werden, mit -s
- auf den Stack zu retten, da die Register schon vor dem Eintritt in die
- Prozedur beschrieben werden. Ich habe leider keine Ahnung, welche
- Register wie von M2Amiga benutzt werden. Als ich ausprobiert habe,
- Werte in Registern zu übergeben, und andere Register auf den Stack zu
- retten erhielt ich einen gnadenlosen Absturz (Arts hat versagt). Wer
- etwas über die verwendung der Register weiß schreibe mir!
-
- Beispiel:
-
- M2ACode Bsp. -vA0:ADDRESS -cD0:CARDINAL -vD3:INTEGER -rA3:LONGCARD
-
- erzeugt folgendes Definitionmodul und speichert es als Beispiel.def:
-
- DEFINITION MODULE Beispiel;
-
- FROM SYSTEM IMPORT BYTE,WORD,ADDRESS,BITSET,LONGSET,FFP;
-
- (*------ Beispiel ------*)
-
- PROCEDURE Beispiel(VAR a:ADDRESS;b:CARDINAL;VAR c:INTEGER):LONGCARD;
-
- END Beispiel.
-
- Außerdem wird das Implementationmodul Beispiel.mod erzeugt:
-
- IMPLEMENTATION MODULE Beispiel;
-
- FROM SYSTEM IMPORT BYTE,WORD,ADDRESS,BITSET,LONGSET,FFP,INLINE,SETREG,REG;
-
- (*------ Beispiel ------*)
-
- PROCEDURE Beispiel(VAR a:ADDRESS;b:CARDINAL;VAR c:INTEGER):LONGCARD;
-
- BEGIN
-
- SETREG( 8,ADDRESS(a));
- SETREG( 0,ADDRESS(b));
- SETREG( 3,ADDRESS(c));
-
- INLINE(0xxxxH,0yyyyH, ... ,0zzzzH);
-
- a := ADDRESS(REG( 8));
- c := INTEGER(REG( 3));
-
- RETURN LONGCARD(REG(11));
-
- END Beispiel;
-
- BEGIN
- END Beispiel.
-
- Der mit INLINE Eingefügte Code in der Mitte hängt von dem File `Beispiel'
- ab, das den Maschinencode enthält.
-
- Die Module können jetzt compiliert und in Modulaprogramme eingebunden
- werden.
-
- Im Directory M2ACodeDemo befindet sich ein Beispiel für die Einbindung
- eines Maschinenprogramms. DrawLines.asm ist der Assemblerquelltext für
- DrawLines. DrawLines.def und DrawLines.mod wurden mit `M2ACode
- DrawLines.prg -ca2:ADDRESS -ca6:ADDRESS -sd2 -sd3 -sa6 -d' erzeugt.
- Draw.mod ist der Modula-Quellcode für das Hauptprogramm. Es öffnet einen
- Screen und die Graphicslibrary. Der DrawMode wird auf Complement gesetzt.
- Danach wird DrawLines aufgerufen, was 20480 Linien zeichnet. Zum Schluß
- schließt Draw den Screen und die Graphics- library wieder.
-
- Ein Demo, das sehr schön den Geschwindigkeitsunterschied zwischen Modula
- und Assembler zeigt, ist im M2ACodeDemo2-Directory. Sort.mod enthält eine
- einfache Sortierroutine für ein CardinalFeld. AssSort.asm ist die gleiche
- Routine in Assembler. Aus AssSort.prg wurden die AssSort.def und
- AssSort.mod-Files mit `M2ACode AssSort.prg -ca0:ADDRESS -cD0:LONGCARD -sd2
- -sd3 -sd4 -d -p' erstellt. Die Programme AssSortDemo und SortDemo füllen
- ein Feld mit 1000 zufälligen CARDINALs. Das Feld wird danach mit AssSort
- bzw. SortDemo sortiert und danach ausgegeben. Die Maschinenroutine ist
- fast 6x schneller als die in Modula.
-