%
% Weiter unten ist eine Tabelle der reservierten Worte de Assemblers,
% bitte formatiere das etwas sch"oner!
%		Bernd
%
\section{Der M2Amiga-Assembler}
\label{refAsm}

Obwohl der Compiler sehr schnellen und kompakten Code erzeugt,
% w"urg!! sind wir hier auf'm Wochenmarkt??/bp
gibt es doch F"alle, in denen bestimmte Aufgaben nicht schnell genug
erledigt werden oder in \mtwo{} gar nicht l"osbar sind.
F"ur derartige Aufgaben wurde M2Amiga um einen eingebauten
{\bf"`Inline"'-Assembler} erweitert.

Im folgenden werden Syntax, Zugriff auf Objekte des
\mtwo-Raums und die Besonderheiten dieses Assemblers beschrieben.

Dieser im Compiler integrierte Assembler beherrscht den kompletten
Befehlssatz und alle Adressierungsarten einer 68030-CPU sowie
zus"atzlich die Befehle der 68881/68882-FPU. Damit sind fast alle
M"oglichkeiten bis
zum 68040-Prozessor abgedeckt.
Der integrierte Assembler bietet im Gegensatz zu einem eigenst"andigen
Assembler Zugriff auf die gesamte \mtwo-Welt --- ein nicht zu
untersch"atzender Vorteil.

Wie der Compiler auch, arbeitet der Assembler ausschliesslich im
Ein\-pass-Modus. Es ist trotzdem ohne weiteres m"oglich,
Vorw"artsreferenzen und -spr"unge zu benutzen.
\begin{warning}
Der Assembler macht keinen  Unterschied
zwischen den per Compiler-Option eingestellten Prozessoren; hier
ist immer alles erlaubt. Man sollte die bedingte Compilierung
benutzen, um den optimalen Code f"ur den jeweils eingestellten
Prozessor zu erzeugen. Lesen Sie hierzu bitte Abschnitt \ref{prozComp}
auf Seite \pageref{prozComp}.
\end{warning}

\subsection{Die Syntax}

Im Assembler wird Gross-/Kleinschreibung unterschieden, d.h.\ alle
Mnemonics und
Registerbezeichnungen m"ussen gross geschrieben werden!
Dies mag zu Beginn etwas
st"orend wirken, aber man gew"ohnt sich schnell daran. Immerhin
ist dies kein normaler Assembler, sondern ein Teil eines
\mtwo-Compilers!

Im Pseudomodul {\tt SYSTEM} (siehe \ref{SysMod}) existiert der
Standardbezeichner {\tt ASSEMBLE}, welcher an die
Stelle des fr"uher existierenden {\tt INLINE} tritt.
Der Aufruf des Assemblers geschieht als Standardprozedur auf
folgende Weise:
\begin{quote} \tt
\verb|"|ASSEMBLE\verb|"| \verb|"|(\verb|"| \{{\cmsltt befehl\/}\}
\verb|"|END\verb|"| \verb|"|)\verb|"|.
\end{quote}

Durch diese Anweisung betritt man einen von \mtwo{} v"ollig verschiedenen
Syntax-Raum. Die Liste der reservierten Worte ist weit gr"osser und g"anzlich
verschieden von derjenigen in \mtwo{} (siehe Tabellen \ref{FigWords}
und \ref{figWordsZ}). Diese Bezeichner "uberlagern die Namen aus dem
\mtwo-Raum, als w"are {\tt ASSEMBLE} eine lokale Prozedur. Ist z.B.\ im
aktuellen Sichtbarkeitsbereich eine Konstante "`{\tt MOVE}"' deklariert,
so hat man im Assembler darauf keinen Zugriff!

Einige "`Laxheiten"' und Besonderheiten bestehen in der Abweichung von der
Motorola-Syntax: statt {\tt MOVEA} darf {\tt MOVE} geschrieben werden.
Analog darf {\tt CMPA}
und {\tt CMPI} durch {\tt CMP},  {\tt SUBA} und {\tt SUBI} durch {\tt SUB},
sowie {\tt ADDA} und {\tt ADDI} durch {\tt ADD}
ersetzt werden. Zus"atzlich erkennt er bei den Condition Codes des
68000
{\tt HS} als {\tt CC} und {\tt LO} als {\tt CS} an. So
sind die Instruktionen {\tt BHS \cmsltt Label} und {\tt BCC \cmsltt Label}
 also gleichwertig.
Schliesslich sind {\tt A4} und {\tt SB}\footnote{static base},
{\tt A5} und {\tt MP}\footnote{mark pointer},
{\tt A7} und {\tt SP}\footnote{stack pointer} synonym.

% Lieber René! Diese Tabelle hat 395 W"orter, was 79 Zeilen ergibt, die ich
% nicht auf eine Seite bekomme. Bitte Hilfe! Als \table geht es nun
% einigermassen, ist aber nicht sch"on formatiert!

\begin{table}
\begin{center}
\small \tt
\tabcolsep5pt
\begin{tabular}{llllllll}
A0&BLE&DBCS&FATANH&FDBEQ&FGETMAN&FSGT&FTRAPF\\
A1&BLO&DBEQ&FBEQ&FDBF&FINT&FSIN&FTRAPGE\\
A2&BLS&DBF&FBF&FDBGE&FINTRZ&FSINCOS&FTRAPGL\\
A3&BLT&DBGE&FBGE&FDBGL&FLOG10&FSINH&FTRAPGLE\\
A4&BMI&DBGT&FBGL&FDBGLE&FLOG2&FSLE&FTRAPGT\\
A5&BNE&DBHI&FBGLE&FDBGT&FLOGN&FSLT&FTRAPLE\\
A6&BPL&DBHS&FBGT&FDBLE&FLOGNP1&FSNE&FTRAPLT\\
A7&BRA&DBLE&FBLE&FDBLT&FMOD&FSNGE&FTRAPNE\\
ABCD&BSET&DBLO&FBLT&FDBNE&FMOVE&FSNGL&FTRAPNGE\\
ADD&BSR&DBLS&FBNE&FDBNGE&FMOVECR&FSNGLE&FTRAPNGL\\
ADDA&BTST&DBLT&FBNGE&FDBNGL&FMOVEM&FSNGT&FTRAPNGLE\\
ADDI&BVC&DBMI&FBNGL&FDBNGLE&FMUL&FSNLE&FTRAPNGT\\
ADDQ&BVS&DBNE&FBNGLE&FDBNGT&FNEG&FSNLT&FTRAPNLE\\
ADDX&CAAR&DBPL&FBNGT&FDBNLE&FNOP&FSOGE&FTRAPNLT\\
AND&CACR&DBRA&FBNLE&FDBNLT&FP0&FSOGL&FTRAPOGE\\
ANDI&CAS&DBT&FBNLT&FDBOGE&FP1&FSOGT&FTRAPOGL\\
ASL&CAS2&DBVC&FBOGE&FDBOGL&FP2&FSOLE&FTRAPOGT\\
ASR&CCR&DBVS&FBOGL&FDBOGT&FP3&FSOLT&FTRAPOLE\\
BCC&CHK&DC&FBOGT&FDBOLE&FP4&FSOR&FTRAPOLT\\
BCHG&CHK2&DFC&FBOLE&FDBOLT&FP5&FSQRT&FTRAPOR\\
BCLR&CLR&DIVS&FBOLT&FDBOR&FP6&FSSEQ&FTRAPSEQ\\
BCS&CMP&DIVSL&FBOR&FDBSEQ&FP7&FSSF&FTRAPSF\\
BEQ&CMP2&DIVU&FBSEQ&FDBSF&FPCR&FSSNE&FTRAPSNE\\
BFCHG&CMPA&DIVUL&FBSF&FDBSNE&FPIAR&FSST&FTRAPST\\
BFCLR&CMPI&END&FBSNE&FDBST&FPSR&FST&FTRAPT\\
BFEXTS&CMPM&EOR&FBST&FDBT&FREM&FSUB&FTRAPUEQ\\
BFEXTU&CRP&EORI&FBT&FDBUEQ&FRESTORE&FSUEQ&FTRAPUGE\\
BFFFO&D0&EVEN&FBUEQ&FDBUGE&FSAVE&FSUGE&FTRAPUGT\\
BFINS&D1&EXG&FBUGE&FDBUGT&FSCALE&FSUGT&FTRAPULE\\
BFSET&D2&EXT&FBUGT&FDBULE&FSEQ&FSULE&FTRAPULT\\
BFTST&D3&EXTB&FBULE&FDBULT&FSF&FSULT&FTRAPUN\\
BGE&D4&FABS&FBULT&FDBUN&FSGE&FSUN&FTST\\
BGT&D5&FACOS&FBUN&FDIV&FSGL&FTAN&FTWOTOX\\
BHI&D6&FADD&FCMP&FETOX&FSGLDIV&FTANH&ILLEGAL\\
BHS&D7&FASIN&FCOS&FETOXM1&FSGLE&FTENTOX&ISP\\
BKPT&DBCC&FATAN&FCOSH&FGETEXP&FSGLMUL&FTRAPEQ&JMP\\
\end{tabular}
\caption{\label{FigWords} Reservierte Worte des Assemblers (A--J)}
\end{center}
\end{table}

\begin{table}
\begin{center}
\small \tt
\begin{tabular}{llllllll}
JSR&MULS&PLOADR&RTE&SLE&SUBI&TRAPGT&TST\\
LEA&MULU&PLOADW&RTR&SLO&SUBQ&TRAPHI&TT0\\
LINK&NBCD&PMOVE&RTS&SLS&SUBX&TRAPHS&TT1\\
LSL&NEG&PMOVEFD&SB&SLT&SVC&TRAPLE&UNLK\\
LSR&NEGX&PSR&SBCD&SMI&SVS&TRAPLO&UNPK\\
MOVE&NOP&PTESTR&SCC&SNE&SWAP&TRAPLS&USP\\
MOVEA&NOT&PTESTW&SCS&SP&TAS&TRAPLT&VBR\\
MOVEC&OR&RELOCATION&SEQ&SPL&TC&TRAPMI&XREF\\
MOVEM&ORI&RESET&SF&SR&TRAP&TRAPNE&ZPC\\
MOVEP&PACK&ROL&SFC&SRP&TRAPCC&TRAPPL&\\
MOVEQ&PC&ROR&SGE&ST&TRAPCS&TRAPT&\\
MOVES&PEA&ROXL&SGT&STOP&TRAPEQ&TRAPV&\\
MP&PFLUSH&ROXR&SHI&SUB&TRAPF&TRAPVC&\\
MSP&PFLUSHA&RTD&SHS&SUBA&TRAPGE&TRAPVS&\\
\end{tabular}
\caption{\label{figWordsZ}Reservierte Worte des Assemblers (J--Z)}
\end{center}
\end{table}

Als "`{\cmsltt befehl}"' sind alle 68030- oder 68881/68882-Befehle,
einer der unten
beschriebenen Pseudo-Befehle oder ein Label erlaubt.

\begin{description}
\item[Ein Label] ist ein unbekannter Bezeichner, direkt gefolgt von einem
Doppelpunkt.
Unbekannt bedeutet, dass es sich nicht um ein reserviertes Wort oder
einen Bezeichner aus dem
\mtwo-Raum handeln darf. Die reservierten Worte von \mtwo{} sind hier
unbekannt, bis auf {\tt END}, welches im Assembler ebenfalls
 definiert ist.
Ein Label hat nur G"ultigkeit innerhalb des aktuellen Assembler-Teils, l"asst
sich also weder von \mtwo{} noch von einem anderen Assembler-Abschnitt
ansprechen.\footnote{Dadurch werden auch ganz bewusst
"`GOTO"'-Anweisungen unterbunden}

{\bf Definierte} Label d"urfen in Ausdr"ucken vorkommen,
{\bf undefinierte} Label hingegen {\em nicht\/}.
 Jeder unbekannte Bezeichner
 --- beispielsweise auch jeder Schreibfehler --- wird zun"achst
 als Label angenommen,
 das innerhalb
 des Textes noch definiert werden muss. Dies f"uhrt leider unter bestimmten
 Umst"anden zu verwirrenden Fehlermeldungen. Ein Beispiel: In der Instruktion
 \begin{quote}
 "`{\tt MOVE.L \#2000,d0}"'
 \end{quote}
 wird "`{\tt d0}"' als undefiniertes Label
 erkannt, da es f"alschlicherweise klein geschrieben wurde. Da die
 Adressierungsart aber absolut, und nicht --- wie es einem Label geb"uhrt ---
 PC-relativ ist, erscheint die Fehlermeldung
 "`{\tt Relokation nicht eingeschaltet}"'. Am Ende des Textes kommt zus"atzlich
 der Fehler "`{\tt Label nicht definiert:\ d0}"'.

\item[Ein Pseudo-Befehl] ist eines der folgenden Mnemonics:
  \begin{ttscript}{RELOCATION}
  \item[END] beendet den Assembler-Text, danach muss noch
    eine abschliessende Klammer "`{\tt )}"' folgen.

  \item[RELOCATION] erlaubt es, PC-relative Objekte absolut zu adressieren.
  Hierbei wird ein "'{\tt RELOC32}"' oder "`{\tt REF32}"'
  f"ur den Linker und AmigaDos
  erstellt.
  Dies ist dann sehr n"utzlich, wenn Zeiger gleich beim Programmstart
  initialisiert sein sollen. Schreibt man z.B.\ {\tt DC.L MenuItem1}, so
  befindet sich an dieser Position im Objektcode die absolute Adresse
  von {\tt MenuItem1}. Dieser Modus bleibt bis
  zum Ende des aktuellen Assembler-Textes g"ultig.
  Nun h"atte man dies nat"urlich
  {\em immer\/} erlauben k"onnen, doch die Erfahrung hat gezeigt,
  dass Schreibfehler
  leicht zu unbeabsichtigten Adressierungsarten f"uhren k"onnen!
  \item[EVEN] zwingt den n"achsten Befehl auf eine gerade Adresse, z.B.\
  nach {\tt DC.B \verb|"|Text\verb|"|,0}. Falls diese Anweisung vergessen
  wird, erzeugt der Compiler eine Fehlermeldung!

  \item[XREF] hat beliebig viele Parameter, durch Kommata getrennt. Die\-se
  Parameter sind Bezeichner, die ausserhalb des Moduls definiert sein
  m"ussen und im Assembler wie Label, absolute 
  oder globale \near- oder \far-Variablen
  benutzt werden k"onnen.

  \item[DC] ist die wohl von jedem anderen Assembler bekannte M"og"-lich"|keit,
  Daten als Byte, Worte oder Langworte in den Code einzuf"ugen.
  "`{\tt DC.B}"' bietet ausserdem die M"oglichkeit, Zeichenketten zu definieren,
  wobei hier die gleiche Syntax wie in \mtwo{} gilt. Es wird allerdings
  kein Null-Byte am Ende angef"ugt!
  \end{ttscript}
\item[Opcodes] werden ganz normal der Prozessor-Syntax entsprechend
ge\-schrie\-ben, im Gegensatz zu vielen anderen Assemblern aber
{\em ausschliesslich\/} in Grossbuchstaben.

\item[Das Zeilenende] hat f"ur den Assembler wie auch in \mtwo{}
keine besondere Bedeutung. Eine Trennung der Befehle durch den
Beginn einer neuen Zeile ist {\em nicht\/} n"otig, auch ein Semikolon
hat hier nichts zu suchen!
Ein ganzer Assembler-Text kann also durchaus in  eine einzige
Zeile geschrieben werden.

Bei der Fehleranzeige im Editor oder mit dem Fehlerlister
steht der Cursor meist am Beginn des n"achsten Befehls, wobei
sich die tats"achliche Fehlerposition im vorigen Befehl befindet.
Andererseits kann sich eine einzige Assembler-Anweisung  "uber beliebig
viele Zeilen erstrecken; dies f"ordert gewiss nicht die Lesbarkeit, ist
aber unter anderem bei Daten ({\tt DC.\cmsltt x\/}) sehr n"utzlich.

\item[Kommentare] werden wie in \mtwo{} angegeben, also durch "`{\tt (*}"'
und "`{\tt *)}"', wobei hier wie sonst auch Compiler-Optionen angegeben
werden k"onnen. Kommentare werden also {\em keinesfalls\/} durch ein
Semikolon eingeleitet, wie sonst bei Assemblern "ublich.

\item[Modula-2-Bezeichner] werden je nach Art des Importes qualifiziert
oder unqualifiziert angegeben, genau wie in \mtwo:
\begin{verbatim}
  IMPORT Terminal;
  FROM Terminal IMPORT waitCloseGadget;
  ...
    JSR    Terminal.Write(PC)
    TST.B  waitCloseGadget(A4)
  ...
\end{verbatim}
\end{description}

\subsection{Ausdr"ucke}
  Ausdr"ucke werden mit Hilfe bestimmter Operationen aus jeweils
  zwei Faktoren gebildet. Zus"atzlich gibt es das "`monadische"' Minus,
  das einer Negation gleichkommt:

\begin{table}[h]
\begin{center}
  \begin{tabular}{|l|c|c|} \hline
  Operation 	& Operator	& Priorit"at\\ \hline \hline
  Monadisches Minus & "`\verb|-|"'& 4 \\ \hline
  Klammerung	& "`\{"'\ldots"`\}"'& 3 \\ \hline
  Multiplikation& "`\verb|*|"'	& 2 \\ \hline
  Division	& "`\verb|/|"'	& 2 \\ \hline
  Bitweises UND & "`\verb|&|"'	& 2 \\ \hline
  Addition	& "`\verb|+|"'	& 1 \\ \hline
  Subtraktion	& "`\verb|-|"' & 1 \\ \hline
  Bitweises ODER& "`\verb-|-"' & 1 \\ \hline
  \end{tabular}
\end{center}
\caption{Operationen des Assemblers}
\end{table}

Operationen gleicher Priorit"at werden von links nach rechts abgearbeitet.
Alle Operationen arbeiten mit 32 Bit. Arithmetische "Uberl"aufe
werden ignoriert.

\begin{example}
Ein paar Beispiele:
\begin{verbatim}
  {3+4}*5            (* = 35 *)
  30 & $F -7 | {3+5} (* = 15 *)
  -4*{-6}            (* = 24 *)
\end{verbatim}
\end{example}

\subsubsection{Faktoren}

Faktoren sind die elementaren Bestandteile eines Ausdrucks.
Diese k"onnen sein:
\begin{description}

\item[Geklammerte Ausdr"ucke]. Die Klammerung erfolgt in
  diesem Assembler durch {\em geschweifte\/} ("`\{"' und "`\}"'),
  und nicht durch runde Klammern! Eine "`normale"' Klammerung ist
  wegen der erweiterten Adressierungsarten des 68020 und h"oherer
  Prozessoren syntaktisch
  un"-m"og\-lich ({\tt MOVE.L (2+2),A6} w"are zweideutig,
  indirekt oder absolut).
\item[Ganze Zahlen] k"onnen bin"ar, oktal, dezimal, hexadezimal oder als
 einzelnes Zeichen angegeben werden. Gleitkommazahlen
 sind {\em nicht\/} erlaubt.
  \begin{itemize}
  \item
    Bin"arzahlen werden durch "`\verb|%|"' eingeleitet.
  \item
    Oktalzahlen beginnen mit "`\verb|@|"'.
  \item
    Dezimalzahlen haben keinen Pr"afix.
  \item
    Hexadezimalzahlen sind durch ein f"uhrendes "`\verb|$|"' gekennzeichnet.
  \item
    Zeichen sind durch einfache oder doppelte Hochkommata eingeschlossene
    {\em Einzel\/}-Zeichen. Ihr Wert ergibt sich aus dem Amiga-Zeichensatz.
  \end{itemize}
  Die Schreibweisen "`{\tt \verb|%|1000010}"', "`{\tt \verb|@|102}"',
   "`{\tt 66}"',
  "`{\tt \$42}"' und "`{\tt \verb|"|B\verb|"|}"' re"-pr"a"|sen"|tieren
  dieselbe Zahl 66.
\item[Zeichenketten] sind nur bei der Instruktion "`{\tt DC.B}"' erlaubt.
\item[Label], die im Assemblertext definiert sind oder noch definiert werden.
\item[Modula-2-Konstanten], die im aktuellen Sichtbarkeitsbereich liegen:
  \begin{itemize}
  \item
   Ganzzahlige und {\tt CHAR}-Konstanten.
  \item
   Zeichenketten des {\em eigenen\/} Moduls. Diese werden PC-relativ adressiert.
  \item
   Zeichenketten eines implementationslosen Moduls sind ebenfalls
   PC-relativ, da sie in den Konstanten-Bereich des eigenen Moduls aufgenommen
   werden, z.B. {\tt DosD.dosName}.
  \item
   Zeichenketten eines fremdem Moduls mit Implementation werden absolut lang
   adressiert. Hier ist zu beachten, dass Library-Moduln neuerdings ein
   Objektfile besitzen. So ist etwa die
   Zeichenkette "`{\tt DosL.dosName}"' lang zu adressieren.
  \end{itemize}
\item[Record-Bezeichner] k"onnen benutzt werden, um die Offsets bestimmter
   Felder innerhalb eines {\tt RECORD}s anzugeben,
    \begin{quote} "`{\tt DosD.Process.task.sigWait}"' \end{quote}
    ergibt beispielsweise den absoluten Wert 22.
    Um nun ein Feld einer {\tt RECORD}-Variablen anzusprechen, schreibt man
    ebenso einfach
    \begin{quote} "`{\tt myProcess.task.sigWait(A4)}"', \end{quote}
    vorausgesetzt, {\tt myProcess} ist eine \near-Variable.
\item[\near-Variablen] m"ussen 16Bit-relativ zu einem Adressregister
   adressiert werden. In M2Amiga ist dies immer A4. Nachdem ein anderes
   Register mit dem Inhalt von A4 geladen wurde, darf es nat"urlich auch
   relativ zu diesem Register sein. Dies gilt sowohl f"ur moduleigene
   wie auch f"ur importierte Variablen.
   Auch wenn der Offset einer
   Variablen bekannt ist, darf {\em keinesfalls\/} einfach
    "`\verb!10(A4)!"' geschrieben werden, da hier sehr wichtige
   Information verloren geht. Die Folge w"are, dass vom Linker falscher Code
   erzeugt w"urde!
\item[\far-Variablen] werden absolut adressiert. Der Programmierer
   muss wissen, welchen Modus (\near\ oder \far) eine Variable hat;
   der Assembler erzeugt bei falscher Benutzung eine Fehlermeldung.
\item[Lokale Variablen und Parameter] werden im allgemeinen relativ zum
   Register A5 adressiert. Der Wert ist im Gegensatz zu den \near-Variablen
   eine absolute Zahl, die den Offset zum Basisregister A5 {\em der
   zugeh"origen Prozedur\/} in einer  normalen Laufzeitumgebung
   --- also {\em mit\/} Eingangs- und Ausgangscode --- angibt.

   Eine Besonderheit stellt hier die Adressierung von offenen Feldern
   dar. Angenommen {\tt arr1} sei ein Parameter vom Typ
   {\tt ARRAY OF \cmsltt typename},
   so bezeichnet {\tt arr1} die Adresse des Feldes und
   der {\tt HIGH}-Wert (Anzahl
   der Elemente--1) liegt in ${\tt arr1}+4$. Dies gilt sowohl f"ur 
   Referenz- wie auch
   f"ur Werte-Parameter!
\begin{example}
\begin{verbatim}
   PROCEDURE OADemo(VAR arr1: ARRAY OF INTEGER;
                    arr2: ARRAY OF CHAR);
   ...
   MOVE.L  arr1(A5),A0   (* ADR(arr1)  *)
   MOVE.L  arr1+4(A5),D0 (* HIGH(arr1) *)
   MOVE.L  arr2(A5),A1   (* ADR(arr2)  *)
   MOVE.L  arr2+4(A5),D1 (* HIGH(arr2) *)
   ...
\end{verbatim}
\end{example}

   Falls die Variable oder der Parameter in einer "ausseren Prozedur
   definiert ist, muss man sich zun"achst den Inhalt des Registers
   A5 der zugeh"origen Prozedur beschaffen! Dazu muss je Level der
   {\bf statische Link} aus 8(A5) geladen werden. Beispiel:
\begin{example}
\begin{verbatim}
  PROCEDURE Lev0(int:INTEGER);
    PROCEDURE Lev1;
      PROCEDURE Lev2;
        ...
        MOVE.L  8(A5),A0   (* A0:=A5  von Lev1 *)
        MOVE.L  8(A0),A0   (* A0:=A5  von Lev0 *)
        MOVE.W  int(A0),D0 (* D0:=int von Lev0 *)
        ...
\end{verbatim}
% 68020:        MOVE.W  ([8,A0],int),D0
\end{example}

\item[Moduln] k"onnen nur dann adressiert werden, wenn es sich
   um Schnitt\-stel\-len-Moduln handelt. Hier bezeichnet der Name des Moduls
   eine \near-Variable,
   die wie oben relativ zu A4 adressiert werden muss. Der Inhalt ist der
   Zeiger auf die Library. Beispiel:
\begin{example}
\begin{verbatim}
  MOVE.L  DosL(A4),A6
  MOVEQ   #50,D1
  JSR     Delay(A6) (* warte 1 Sekunde *)
\end{verbatim}
\end{example}

\item[Prozeduren] werden beim Aufruf immer {\tt d16(PC)} adressiert.
   Um es einheitlich zu halten,
   sollte
   man Prozeduren des eigenen Moduls via {\tt BSR~\cmsltt Proc\/} aufrufen,
   modulfremde
   Prozeduren mittels {\tt JSR~{\cmsltt Proc\/}(PC)}.
   M"ochte man jedoch die Adresse einer
   modulfremden Prozedur ansprechen, muss absolut adressiert werden,
   beispielsweise durch {\tt LEA~{\cmsltt Proc},\ A0}.
   Dies ist durch die Methoden des Linkers bedingt.
\item[CODE-Prozeduren] ergeben den absoluten Offset, so dass man z.B.\ einfach
    {\tt JSR~Forbid(A6)} schreiben kann.
\item[XREF-Bezeichner] erzeugen je nach Art der Benutzung eine 16- oder
32Bit Referenz ({\tt REF16}, {\tt DREF16}, {\tt REF32}) f"ur den Linker.
\item["`\verb|*|"'] bezeichnet den aktuellen Programmz"ahler. Dieser Faktor ist
   allerdings nur bei "`{\tt DC.\cmsltt x\/}"' erlaubt, um Differenzen zwischen
   Labeln bilden zu k"onnen! Die andere denkbare Nutzung, wie z.B.\ in
   "`{\tt BRA \verb|*|+4}"', ist in diesem Assembler nicht m"oglich,
   da die nachtr"agliche Optimierung durch den Compiler diesen Sprung
   ins "`Nirwana"'\footnote{laut \cite{Duden-Fremd} "`im Bud\-dhis\-mus
   die v"ollige, selige Ruhe als erhoffter Endzustand"'. Das
   passt zwar gut zum "`Guru"', der dann auch die Folge sein wird.
   Dies ist aber auf dem Amiga wohl weniger erhofft.} 
   schicken k"onnte! Man sollte also strikt mit Labeln
   arbeiten.
\end{description}

\subsubsection{Erlaubte Operationen}
  Nicht alle Operationen nach der oben beschriebenen Syntax sind erlaubt!
  Faktoren werden hier unterschieden nach:

  \begin{description}
  \item["`absolut"':] Zahlen, Einzelzeichen (konstante Zeichenketten
   der L"ange 1,
  die im Assembler-Quelltext angegeben werden), Parameter, lokale Variablen,
   {\tt CODE}-Prozeduren, absolute Variablen, Record-Felder, importierte
   Zeichenkettenkonstanten aus implementationsbehafteten\footnote{normale,
   aus Definition und Implementation bestehende Moduln} Moduln.
  \item["`PC-relativ"':] Label, Prozeduren, 
  Zeichenkettenkonstanten des eigenen Moduls sowie
  aus implementationslosen\footnote{nur
  aus der Definition bzw.\ der Symboldatei bestehende Moduln}
  Moduln importierte.
  \item["`Sonstiges"':] globale Variablen, {\tt XREF}s, Schnittstellen-Moduln,
  externe Variablen (sowohl \near{} als auch \far{}, hier ist Vorsicht
  geboten!)
  \end{description}

\subsubsection{Resultate von Ausdr\protect"ucken}

Operationen, die in der Tabelle \ref{AssOps}
nicht auftreten, sind
{\em verboten\/} und erzeugen eine Fehlermeldung!
Insbesondere ist jegliche Operation mit undefinierten Labeln verboten.

\begin{table}[hbt]
\begin{center}
\begin{tabular}{|c|c|c||c|} \hline
 Operand A & Operation & Operand B & Resultat \\ \hline \hline
 absolut  & jede  & absolut & absolut \\ \hline
 PC-relativ &  -- & PC-relativ & absolut \\ \hline
 PC-relativ & $\pm$ & absolut & PC-relativ \\ \hline
 sonstiges & $\pm$ & absolut & sonstiges \\ \hline
\end{tabular}
\end{center}
\caption{\label{AssOps}Adressmodus von Assembler-Operationen}
\end{table}

\subsection{Die Register-Benutzung im Assembler}

\label{refAsmRegs}
Wie man im Abschnitt "uber die Register (\ref{refRegs},
Seite \pageref{refRegs})
nachlesen kann, muss sich jede Prozedur an die Amiga-Konvention halten,
kein Register ausser D1, D1, A0, A1, FP0 und FP1 zu ver"andern. Dies hat beim
Schreiben von {\tt ASSEMBLE}-Code normalerweise keine Auswirkungen, da der
Assembler dem Compiler mitteilt, welche Register benutzt wurden. Diese
werden
somit innerhalb der umgebenden Prozedur in die Sicherung auf den Stack zum
Prozedurbeginn und Wiederherstellung vom Stack am Prozedurende
mit einbezogen.

\begin{warning}
 Die Register A4 und A5 werden {\em niemals\/} automatisch auf den Stack
 gerettet, auch wenn sie innerhalb eines Assembler-Teils ver"andert
 wurden! Diese beiden Register sollten daher auch nie ver"andert werden.
\end{warning}

Wenn allerdings die gesamte Prozedur ohne Eingangs- und Ausgangscode
in Assembler implementiert wird, ist der Programmierer f"ur die Rettung
und Wiederherstellung
der benutzten Register (ebenso wie f"ur die Parameter-Deallokation) selbst
verantwortlich! Zudem ist A5 nicht initialisiert und gerettet. W"ahrend
man in einer "`normalen"' Umgebung z.B. schreiben kann:
\begin{alltt}
       MOVE.L  {\cmsltt parameter1\/}(A5),D2
\end{alltt}
so m"usste man ohne Eintrittscode z.B. schreiben:
\begin{alltt}
       MOVEM.L  D2/D6/A6,-(A7)
       ...
       MOVE.L  {\cmsltt parameter1\/}-4+3*4(A7),D2
\end{alltt}
vorausgesetzt, der Stackrahmen ist noch in Ordnung. Der Wert $-4$ kommt dadurch
zustande, dass A5 nicht durch eine {\tt LINK}-Instruktion
auf dem Stack liegt, $+3*4$ ergibt sich
aus den drei geretteten Registern.

Ein anderer Aspekt betrifft k"urzere Assembler-Teile innerhalb l"angerer
Prozeduren. Hier kann kaum eine Aussage getroffen werden, welche Register
momentan belegt sind und keinesfalls ver"andert werden d"urfen. F"ur jeden
{\tt WITH}-Level --- drei sind maximal erlaubt ---
wird je ein Adressregister reserviert, welche
dies sind, ist jedoch unbestimmt.
In einer {\tt CASE}- oder {\tt FOR}-Umgebung ist zudem der
Stackpointer "`verstellt"', was aber wenig ausmacht,
da Parameter und lokale Variablen relativ zu A5 adressiert werden k"onnen.
Ausserdem d"urfen Register-Variablen und -Parameter nicht versehentlich
ver"andert werden. Sicherste Methode ist hier, einfach die benutzten
Register auf dem Stack zu retten, eine andere w"are, sich den erzeugten
Code mit dem Dekoder anzusehen. Im letzteren Fall kann es nat"urlich
passieren, dass eine sp"atere Compilerversion den Code anders generiert.
Darum kann diese Methode nicht empfohlen werden.

\begin{example}
Ein Beispiel, das die Problematik erl"autert:
\begin{verbatim}
PROCEDURE Extreme(ptr:RecPtr; y{R.D3}:LONGINT);
VAR i{R.D7}:CARDINAL;
BEGIN
  WITH ptr^ DO
    FOR i:=1 TO max+3 DO
      CASE value OF
      | 3:
          ASSEMBLE(
          (* simuliert: * y:=ptr^.field1 *)
            MOVE.L A0,-(A7)
            MOVE.L ptr(A5),A0
            MOVE.L Rec.field1(A0),y
            MOVE.L (A7)+,A0
          END);
      | ELSE
      END;
    END;
  END;
\end{verbatim}
\noindent
Beim Start von {\tt ASSEMBLE} weiss man nur sicher, dass
{\tt D3} und {\tt D7} belegt sind,
irgendein Adressregister den Zeiger "`{\tt ptr}"' enth"alt und {\tt A7}
unbekannt
ist. Da aber nicht bekannt ist, {\em welches\/} Adressregister {\tt ptr}
 enth"alt,
muss ein Adressregister "`freigemacht"' und {\tt ptr} neu geladen werden.
\end{example}

\subsection{Optimierungen im Assembler}
\label{refOptiAsm}
Der Assembler selbst f"uhrt nur zwei Arten von Optimierungen durch:
\begin{itemize}
\item
  Die Adressierungsart {\tt d16(A\cmsltt x\/\tt)} bzw.\
  {\tt (d16,A\cmsltt x\/\tt)} wird in {\tt (A\cmsltt x\/\tt)}
  umgewandelt, wenn d{\tt 16}=0 ist. Man kann also durchaus der Klarheit
  halber
\begin{verbatim}
  MOVE.L Node.succ(A0),A1
\end{verbatim}
  schreiben, statt
\begin{verbatim}
  MOVE.L (A0),A1
\end{verbatim}
  Ersteres ist ausserdem auch noch g"ultig, wenn die {\tt RECORD}-Struktur
  der Variablen {\tt Node} mal ge"andert werden
  sollte.
\item
  Die Adressierungsart absolut lang wird in absolut kurz umgewandelt,
  wenn die Adresse nicht mehr als 16 Bit beansprucht.
  Dies wird auf dem Amiga nur die Adresse 4 (execBase) betreffen.
\end{itemize}

Zus"atzlich f"uhrt der Compiler am Schluss --- wie auch f"ur
den \mtwo-Code --- eine {\bf Sprung}- und "`{\bf Deadcode}"'-Optimierung durch, wenn
die entsprechende Compiler-Option eingeschaltet ist (\ref{refOpti},
Seite \pageref{refOpti}).
S"amtliche vom Assembler generierten PC-relativen Referenzen werden
an den globalen Optimierer gemeldet.
Dies ist im allgemeinen zu begr"ussen, da z.B.\ {\tt BRA} wo immer m"oglich
in {\tt BRA.S} optimiert und "`toter"'\footnote{Code, der nie durchlaufen
wird} Code entfernt wird.

\begin{warning}
Es gibt
auch eine kleine Falle, wie folgendes Beispiel zeigt:
\begin{verbatim}
      BRA   weiter
      ...
      DC.W  fehlerFall
FehlerTabelle:
      DC.W ok1
      ...
weiter:
      ADD.W D1,D1
      MOVE.W FehlerTabelle(PC,D1.W),D2
      ...
\end{verbatim}
Hier soll der Eintrag "`{\tt fehlerFall}"'f"ur den Fall \hbox{{\tt D1}=--1}
geladen werden. Da aber
keine Referenz auf den Bereich zwischen der Anweisung {\tt BRA}
und dem Label {\tt FehlerTabelle}
vorhanden ist, scheint dieser Teil f"ur den Optimierer unbenutzt und er
l"oscht ihn! Somit wird das Programm dann fehlerhaft laufen.
Auch ein
\begin{verbatim}
      ADDQ.W #2,D1
      MOVE.W FehlerTabelle-2(PC,D1.W),D2
\end{verbatim}
hilft hier {\em nicht\/} weiter! Solche Konstrukte m"ussen unterbleiben.
Eine L"o\-sung des Problems w"are:
\begin{verbatim}
FehlerTabelle:
      DC.W  fehlerFall
      DC.W ok1
      ...
weiter:
      ADD.W D1,D1
      MOVE.W FehlerTabelle+2(PC,D1.W),D2
      ...
\end{verbatim}
\end{warning}

\subsection{Daten als ASSEMBLE-Code}
Mit Hilfe des Assemblers ist es sehr einfach, initalisierte Daten in
Prozeduren zu "`verstecken"'. Hierzu wird einfach eine Prozedur
ohne Eingangs- und Ausgangscode compiliert ({\tt EntryExitCode := FALSE}),
die ausschliesslich aus
{\tt ASSEMBLE}-Anweisungen des Typs {\tt DC.\cmsltt x\/} besteht.

\subsubsection{Selbstmodifizierender Code}
\begin{warning}
 Hierzu gibt es
Folgendes zu bedenken: Prozeduren gelten als CODE, d.h.\ die darin
enthaltenen Daten d"urfen w"ahrend des Programmlaufes {\em nicht ver"andert
werden\/}! Nun ist so etwas auf den momentan existierenden Amigas
zwar doch m"oglich, aber eine sp"atere Version k"onnte mit Hilfe einer
Memory Management Unit diese Tatsache als Programmfehler dem Guru
"ubergeben. Bereits heute ist es {\em unm"oglich},
dieses in einem {\em residenten\/}
Programm zu tun.

Beispielsweise werden {\tt NewWindow}-Strukturen von
Intuition nicht ver"-"an\-dert,
{\tt Menu}- oder {\tt Gadget}-Strukturen hingegen sehr wohl.

In der aktuellen Compiler-Version ist das Anlegen initialisierter,
{\em ver"-"ander\-licher\/} Daten nur mit Hilfe
eines fremden Assemblers und der Deklaration externer Variablen m"oglich,
wobei diese initialisierten Daten als {\tt DATA} abgelegt sein m"ussen.
\end{warning}

\begin{example}
Auf der Demo-Diskette befindet sich im Verzeichnis {\tt Trails} ein
ausf"uhrliches Beispiel f"ur eine initialisierte Menu-Struktur,
die mit Hilfe eines fremden Assemblers erstellt und durch den
Gebrauch externer Variablen in den \mtwo-Code eingebunden wurde.

Ein Beispiel f"ur eine {\tt IntuitionD.NewWindow}-Struktur folgt hier:
\begin{verbatim}
PROCEDURE MyNewWin; (*$ EntryExitCode:=FALSE *)
CONST myIDCMP=CAST(LONGINT,IDCMPFlagSet{closeWindow})
      myWinFlags=CAST(LONGINT,WindowFlagSet{windowDrag});
      wbWin=CAST(INTEGER,ScreenFlagSet{wbenchScreen});
BEGIN
  ASSEMBLE(
    RELOCATION (* nur wegen DC.L title *)
    DC.W  0,0,300,100
    DC.B  2,3
    DC.L  myIDCMP, myWinFlags,
          0,0,
          title,
          0,0
    DC.W  100,50,640,256
    DC.W  wbWin
title:
    DC.B  "Mein Fenster",0 EVEN
  END);
END MyNewWin;
\end{verbatim}
\end{example}

\subsection[INLINE nach ASSEMBLE]{Umstellung von INLINE auf ASSEMBLE}

\label{refINLASS}
In der vorg"angigen Version von \mtwoamiga\ existierte
die Anweisung {\tt INLINE}, mit der explizit Maschinensprache
in den Code eingef"ugt werden konnte. Diese Anweisung ist
nun nicht mehr vorhanden. Programme, welche diese Anweisung
verwenden, m"ussen gem"ass den folgenden Richtlinien ge"andert
werden.

Um alte INLINE-{\em Daten\/} auf ASSEMBLE umzustellen hat man nur folgendes
zu tun:
\begin{itemize}
\item ersetze "`{\tt INLINE}"' durch "`{\tt ASSEMBLE}"'; dies
  muss auch in der {\tt IMPORT}-Anweisung geschehen!
\item setze zu Beginn ein "`{\tt DC.W}"'
\item f"uge vor der abschliessenden Klammer ein "`{\tt END}"' ein
\item stelle konstante Zahlen so um, dass aus "`{\cmsltt xxxx\/\tt H}"'
 "`{\tt \$\cmsltt xxxx\/}"' wird, aus  "`{\cmsltt ooooo\/\tt B}"'
  "`{\tt @\cmsltt ooooo\/}"' und aus "`{\cmsltt bbbbbb\/\tt L}"'
   "`{\tt \%\cmsltt bbbbbb}"'.
\end{itemize}
Nat"urlich hat man nun ganz neue M"oglichkeiten, wie aus dem vorigen
Abschnitt ersichtlich. Diese sollte man auch nutzen.

Alten INLINE-{\em Code\/} nach ASSEMBLE umzustellen erfordert
dagegen weit mehr.
Man darf {\em keinesfalls\/} einfach das gleiche wie bei den Daten
tun, da
\begin{itemize}
\item wahrscheinlich nicht an die Register-Rettung
 gedacht wurde,
\item  alle Spr"unge dem Compiler bekannt sein m"ussen,
\item viele Objekte nun ganz anders adressiert werden und
\item die Laufzeitumgebung (Stackframe) anders ist!
\end{itemize}
Man muss vielmehr den urspr"unglichen Assembler-Quelltext
in den Text einf"ugen und entsprechend anpassen.
Falls diese Anweisungen mit Hilfe des Moduls {\tt Assembler}
erstellt wurden, f"allt die Umstellung leichter. Wegen
den obigen Einschr"ankungen ist dieses Modul in dieser
Version nicht mehr enthalten; der eingebaute Assembler macht es
auch unn"otig.

\subsection{Verschiedene Prozessoren}

Da der Compiler bei entsprechend gesetzter Option  prozessorbezogenen
Code erzeugt, kann man hiervon auch im Assembler Gebrauch machen,
um optimalen Code zu generieren. Hierzu ist die bedingte
Compilierung ein sehr n"utzliches Hilfsmittel. Es folgt ein kleines
Beispiel einer Prozedur,
das f"ur den 68020 und h"ohere Prozessoren den {\tt MULS.L}-Befehl und f"ur den
68010 und h"ohere den {\tt RTD}-Befehl verwendet. F"ur einen 68881/882 wird
direkt die FPU angesprochen; im anderen Fall muss "uber die Library
{\tt mathieeedoubtrans.library} gegangen werden. Man k"onnte sogar so
weit gehen, innerhalb des ganzen Moduls f"ur den 68881 nur {\tt LONGREAL}s
zu verwenden, um die bestm"ogliche Kombination
von Geschwindigkeit und Genauigkeit zu erlangen.

\begin{example}
Das folgende Beispiel zeigt gleichzeitig die Ausnutzung eines
Coprozessors, einer 68020-CPU und die ausdr"uckliche
Erzeugung von Eingangs- und
Ausgangscode, falls vor dem {\tt BEGIN} der Prozedur die Compiler-Anweisung
{\tt EntryExit:=FALSE} angegeben wurde.

Zun"achst wird "uberpr"uft, ob der Eingangscode bereits 
automatisch erzeugt wurde.
War dies nicht der Fall ({\tt EntryExitCode=FALSE}), so muss der Code selbst
erzeugt werden. Hierzu "`linken"' wir das Register A5, um einfach
auf die Parameter zugreifen zu k"onnen und retten alle im folgenden
ver"anderten Register auf den Stack.

Danach soll die Anweisung {\tt Zahl2:=Zahl1*Para0} ausgef"uhrt werden. Da es
sich in diesem Beispiel um {\tt LONGINT}s handelt, k"onnen wir f"ur die
Prozessoren ab 68020 den {\tt MULS.L}-Befehl verwenden, andernfalls
rufen wir die Arts-Prozedur {\tt Muls32} auf.

Drittens soll eine Gleitkommazahl-Berechnung, die etwa der \mtwo-Anweisung
{\tt longr1:=sin(longr1)} --- {\tt longr1} vom Typ {\tt LONGREAL} ---
entspricht,
durchgef"uhrt werden. Eine 68881-FPU
kann diese Berechnung direkt ausf"uhren. Ist keine vorhanden,
genauer gesagt, sofern nicht f"ur die FPU compiliert wird,
muss eine Prozedur der {\tt mathieeedoubtrans.library} genutzt werden.

Schliesslich beenden wir die Prozedur. Wird der Ausgangscode vom
Compiler erzeugt , ist nichts zu tun, andernfalls
m"ussen wir den Code selbst erzeugen. Dazu stellen wir die Register
wieder her, "`befreien"' A5, bauen die Parameter ab und kehren
zu der aufrufenden Prozedur zur"uck. In diesem
Beispiel nehmen wir an, die Parameter der Prozedur belegen 10 Byte.
Alle Prozessoren ab 68010 beherrschen den {\tt RTD}-Befehl, f"ur eine
einfache 68000-CPU m"ussen wir hier etwas mehr Aufwand treiben.

\begin{verbatim}
(*$ IF NOT EntryExitCode *)
  LINK   A5,#0 (* der Einfachheit halber! *)
  MOVEM.L Dx.../A6,-(SP)
(*$ ENDIF *)
  ...
  MOVE.L Zahl1(A4),D0 (* globale NEAR-VAR *)
(*$ IF m68020 *)
  MULS.L Para0(A5),D0 (* Parameter *)
(*$ ELSE *)
  MOVE.L Para0(A5),D1
  JSR    Arts.Muls32(PC)
(*$ ENDIF *)
  MOVE.L D0,Zahl2  (* globale FAR-VAR,importiert *)
  ...
(*$ IF m68881 AND NOT m68040 *)
  FSIN.D  longr1(A4),FP0
  FMOVE.D FP0,longr1(A4)
(*$ ELSE *)
  MOVEM.L longr1(A4),D0-D1
  MOVE.L  MathIEEEDoubTrans(A4),A6
  JSR     MathIEEEDoubTrans.Sin(A6)
  MOVEM.L D0-D1,longr1(A4)
(*$ ENDIF *)
  ...
(*$ IF NOT EntryExitCode *)
  MOVEM.L (A7)+,Dx.../A6
  UNLK   A5
(*$ IF m68010 *)
  RTD    #10 (* 10 Byte Parameter *)
(*$ ELSE *)
  MOVE.L (A7)+,A0
  LEA    10(A7),A7
  JMP    (A0)
(*$ ENDIF *) (* m68010 *)
(*$ ENDIF *) (* EntryExit *)
\end{verbatim}
\end{example}

\subsection{Was kann er nicht?}

Wie man gesehen hat, beherrscht dieser Assembler weit mehr als 
herk"ommliche Assembler. Insbesondere sind die F"ahigkeiten
besonders angenehm, die nur dadurch m"oglich sind, dass der
Assembler vollst"andig integriert ist.
Dennoch bestehen Leistungsgrenzen. Der Assembler unterst"utzt {\em nicht\/}:
\begin{itemize}
\item
  Makros
\item
  Dereferenzierung von Zeigern (\verb|ptr^.x|)
\item
   Adressierung von Array-Komponenten (\verb|arr[i]|)
\item
   Real- und Longreal-Konstanten kann man nicht direkt angeben, man muss
   sich z.B. im Prozedurkopf mit einer Konstantendefinition behelfen:
   \begin{quote} \verb|CONST myReal=CAST(LONGINT,REAL(1.2345));| \end{quote}
   Da {\tt CAST} nicht zu Records konvertieren kann, ist diese Methode leider
   nur bei {\tt REAL} und {\tt FFP} m"oglich (beide belegen jeweils vier Byte im
   Speicher), {\tt LONGREAL}-Konstanten bleiben dem Assembler-Programmierer
   somit verschlossen.
\item
   "`{\tt EQU}"' wird nicht unterst"utzt.
   Konstanten m"ussen in \mtwo{} deklariert
   werden.

\end{itemize}

