%%TITLE Bedienungsanleitung Makroassembler AS
%% Try \usepackage[german]{babel} if your Tex distribution does not provide the german sty file:
\sloppy
\evensidemargin 0.5cm
\oddsidemargin 0.5cm
\topsep 1mm
\parskip 0.3cm plus0.2cm minus0.2cm
\hyphenation{Lis-ting-er-zeu-gung}
\hyphenation{back-slash}
\newif\ifelektor
\elektorfalse
\font\mengft=cmss9 scaled \magstep1
\def \rz{\hbox{\mengft{I \hskip -1.7mm R}}}
%%===========================================================================
\begin{document}
\thispagestyle{empty}
\
\begin{raggedright}
{\large Alfred Arnold}\\
{\huge Makroassembler \asname{} V1.42}\\
{\huge Benutzeranleitung}
{\large Stand M"arz 2024}
\end{raggedright}
\clearpage
\thispagestyle{empty}
{\em IBM, PPC403Gx, OS/2} und {\em PowerPC} sind eingetragene Warenzeichen
der IBM Corporation.
{\em Intel, MCS-48, MCS-51, MCS-251, MCS-96, MCS-196} und {\em MCS-296}
sind eingetragene Warenzeichen der Intel Corp. .
{\em Motorola} und {\em ColdFire} sind eingetragene Warenzeichen von
Motorola Inc. .
{\em MagniV} ist ein eingetragenes Warenzeichen von Freescale Semiconductor.
{\em PicoBlaze} ist ein eingetragenes Warenzeichen der Xilinx Inc.
{\em UNIX} ist ein eingetragenes Warenzeichen der Open Group.
{\em Linux} ist ein eingetragenes Warenzeichen von Linus Thorvalds.
{\em Microsoft, Windows} und {\em MS-DOS} sind eingetragene Warenzeichen
der Microsoft Corporation.
Alle anderen Warenzeichen, die nicht ausdr"ucklich in diesem Abschnitt
genannt wurden und in diesem Handbuch verwendet werden, sind Eigentum
der entsprechenden Eigent"umer.
Dieses Dokument wurde mit dem LaTeX-Satzsystem unter dem Betriebssystem
Linux angefertigt und formatiert.
\clearpage
%%===========================================================================
\ifelektor
\thispagestyle{empty} \
\clearpage
\thispagestyle{empty} \
\clearpage
%%===========================================================================
%%===========================================================================
\cleardoublepage
Diese Anleitung wendet sich an Programmierer, die bereits mit der Programmierung in Assembler
vertraut sind und sich dar"uber informieren m"ochten, wie man mit \asname{} umgeht. Sie
hat eher die Form eines Referenz- und nicht Benutzerhandbuches. Als solches
macht sie weder den Versuch, die Sprache Assembler an sich zu erkl"aren, noch
erl"autert sie die Architektur bestimmter Prozessoren. Im Literaturverzeichnis
habe ich weiterf"uhrende Literatur aufgelistet, die bei der Implementation der
einzelnen Codegeneratoren ma"sgebend war. Um Assembler von Grund auf zu
lernen, kenne ich kein Buch; ich habe es im wesentlichen im ,,Trial and
error''-Verfahren gelernt.
%%Nach einer kleineren Diskussion auf der Mailing-Liste und einigen Vorschl"agen
%%habe ich beschlossen, mit ,,ACASM'' einen eigenen Vorschlag f"ur einen besseren
%%Namen zu machen. Es ist in der OpenSource-Szene ja gute Tradition, da"s die
%%Abk"urzungen mehrere Deutungen gestatten. Ein paar Vorschl"age:
%%\begin{itemize}
%%\item{,,AC'' k"onnte einfach f"ur meine Heimatstadt Aachen stehen, denn dies
%% ist Aachens KFZ-Kennzeichen;}
%%\item{,,Another CPU'', wenn (mal wieder) ein neues Target dazugekommen ist;}
%%\item{,,All Crap'', wenn man sich dar"uber ge"argert hat...}
%%\item{...oder ,,Alfreds Cute Assembler'', wenn man unbedingt meinen Namen
%% damit in Verbindung bringen will...}
%%\end{itemize}
%%---------------------------------------------------------------------------
Bevor es in medias res geht, erst einmal der unvermeidliche Prolog:
\asname{} in der vorliegenden Version untersteht der GNU General Public License
(GPL); die Details dieser Lizenz k"onnen Sie in der beiliegenden Datei
COPYING nachlesen. Falls Sie diese nicht mit \asname{} erhalten haben,
beschweren Sie sich bei demjenigen, von dem Sie \asname{} erhalten haben!
Kurz gesagt, beinhaltet die GPL folgende Punkte:
\begin{itemize}
\item{Auf \asname{} aufbauende Programme m"ussen ebenfalls der GPL unterstehen;}
\item{Weiterverbreitung ausdr"ucklich erlaubt;}
\item{expliziter Haftungsausschlu"s f"ur durch die Anwendung dieses
Programms entstehende Sch"aden.}
\end{itemize}
...aber f"ur die Details bitte ich wirklich, in den Originaltext der GPL
zu schauen!
Um eine m"oglichst schnelle Fehlerdiagnose und -korrektur zu erm"oglichen,
bitte ich, Fehlerberichten folgende Angaben beizuf"ugen:
\begin{itemize}
\item{Betriebssystem (DOS, Windows, Linux...) mit Version}
\item{benutzte Version von \asname{} bzw. Datum des EXE-Files}
\item{bei selbst kompilierten Versionen: verwendeter Compiler und Version}
\item{m"oglichst die Quelldatei, bei der der Fehler auftritt}
\end{itemize}
Zu erreichen bin ich folgenderma"sen:
\begin{itemize}
\item{per Post: \begin{description}
\end{description}}
\item{per E-Mail: \tty{alfred@ccac.rwth-aachen.de}}
\end{itemize}
Wer mir pers"onlich Fragen stellen will (und in der N"ahe von Aachen
wohnt), kann dies mit hoher Wahrscheinlichkeit donnerstags von 20.00
bis 21.00 Uhr im Computerclub an der RWTH Aachen (Elisabethstra"se 16,
erster Stock, rechter Flur).
Von Telefonanrufen bitte ich abzusehen. Erstens, weil sich die
komplizierten Zusammenh"ange am Telefon nur "au"serst schwer er"ortern
lassen, und zweitens ist die Telekom schon reich genug...
Die neueste Version von \asname{} (DPMI, Win32, C) findet sich auf folgendem
Server:
\begin{verbatim}
http://john.ccac.rwth-aachen.de:8000/as
\end{verbatim}
oder auch kurz
\begin{verbatim}
http://www.alfsembler.de
\end{verbatim}
Wer "uber keinen FTP-Zugang verf"ugt, kann den Assembler auch von mir
anfordern. Ich werde aber nur Anfragen beantworten, die einen CD-Rohling
und einen passenden, frankierten R"uckumschlag enthalten. \bb{KEIN} Geld
schicken!!!
So. Nach diesem unvermeidlichen Vorwort k"onnen wir wohl beruhigt
zur eigentlichen Anleitung schreiten:
%%---------------------------------------------------------------------------
\section{allgemeine F"ahigkeiten des Assemblers}
\asname{} bietet im Gegensatz zu normalen Assemblern die M"oglichkeit, Code
f"ur v"ollig verschiedene Prozessoren zu erzeugen. Momentan sind
folgende Prozessorfamilien implementiert:
\begin{itemize}
\item{Motorola 68000..68040, 683xx, Coldfire inkl. Koprozessor und MMU}
\item{Motorola DSP5600x,DSP56300}
\item{Motorola/IBM MPC601/MPC505/PPC403/MPC821}
\item{Motorola 6800, 6801, 68(HC)11(K4) sowie Hitachi 6301}
\item{Motorola/Freescale 6805, 68HC(S)08}
\item{Motorola 6809 / Hitachi 6309}
\item{Motorola/Freescale 68HC12(X) inklusive XGATE}
\item{Freescale/NXP S12Z (''MagniV'')}
\item{Hitachi SH7000/7600/7700}
\item{Rockwell 6502, 65(S)C02, Commodore 65CE02, WDC W65C02S, Rockwell 65C19 und
Hudson HuC6280}
\item{Mitsubishi MELPS-740}
\item{Mitsubishi MELPS-7700}
\item{Mitsubishi MELPS-4500}
\item{Western Digital WD16}
\item{Intel MCS-48/41, einschlie"slich Siemens SAB80C382 und der
OKI-Varianten}
\item{Intel MCS-51/251, Dallas DS80C390}
\item{Intel MCS-96/196(Nx)/296}
\item{Siemens 80C166/167}
\item{Zilog Z80 (einschlie"slich undokumentierter Befehle), Z180, Z380}
\item{Sharp LR35902 (,,Gameboy-Z80'')}
\item{Zilog Z8, Super8, Z8 Encore}
\item{Xilinx KCPSM/KCPSM3 ('PicoBlaze')}
\item{Toshiba TLCS-900(L)}
\item{Toshiba TLCS-870(/C)}
\item{Microchip PIC16C54..16C57}
\item{Microchip PIC16C84/PIC16C64}
\item{Microchip PIC17C42}
\item{Parallax SX20/SX28}
\item{SGS M380/GI LP8000}
\item{SGS-Thomson ST7/STM8}
\item{Texas Instruments TMS32010/32015}
\item{Texas Instruments TMS3202x}
\item{Texas Instruments TMS320C3x/TMS320C4x}
\item{Texas Instruments TMS320C20x/TMS320C5x}
\item{Texas Instruments TMS320C54x}
\item{Texas Instruments TMS320C6x}
\item{Texas Instruments TMS99xx/TMS99xxx}
\item{Texas Instruments TMS7000}
\item{Texas Instruments TMS1000}
\item{Texas Instruments TMS370xxx}
\item{Texas Instruments MSP430(X)}
\item{National Semiconductor IMP-16}
\item{National Semiconductor IPC-16 ('PACE'), INS8900}
\item{National Semiconductor SC/MP}
\item{National Semiconductor INS807x}
\item{National Semiconductor COP4}
\item{National Semiconductor COP8}
\item{National Semiconductor SC144xx}
\item{National Semiconductor NS32xxx}
\item{Olympia CP-3F (bzw. SGS M380, GI LP8000)}
\item{NEC $\mu$PD78(C)0x/$\mu$PD78(C)1x}
\item{NEC $\mu$PD75xxx (alias 75K0)}
\item{NEC $\mu$PD7720/7725}
\item{Fujitsu F$^2$MC16L}
\item{Panafacom MN1610/MN1613}
\item{Padauk PMS/PMC/PFSxxx}
\item{Symbios Logic SYM53C8xx (ja, die kann man programmieren!)}
\item{Intersil CDP1802/1804/1805(A)}
\item{Intersil IM6100/6120}
\end{itemize}
in Arbeit / Planung / "Uberlegung :
\begin{itemize}
\item{Analog Devices ADSP21xx}
\item{Texas Instruments TMS320C8x}
\end{itemize}
ungeliebt, aber {\it doch} vorhanden :
\begin{itemize}
\item{Intel 8086, 80186, NEC V30..V55 inkl. Koprozessor 8087}
\end{itemize}
Die Umschaltung des Codegenerators darf dabei auch mitten in der Datei
erfolgen, und das beliebig oft!
Der Grund f"ur diese Flexibilit"at ist, da"s \asname{} eine Vorgeschichte hat,
die auch in der Versionsnummer deutlich wird: \asname{} ist als Erweiterung eines
Makroassemblers f"ur die 68000er-Familie entstanden. Auf besonderen
Wunsch habe ich den urspr"unglichen Assembler um die F"ahigkeit zur
"Ubersetzung von 8051-Mnemonics erweitert, und auf dem Weg (Abstieg?!) vom
68000 zum 8051 sind eine Reihe anderer fast nebenbei abgefallen...die
restlichen Prozessoren wurden allesamt auf Benutzeranfrage hin integriert.
Zumindest beim prozessorunabh"angigen Kern kann man also getrost davon
ausgehen, da"s er gut ausgetestet und von offensichtlichen Bugs frei ist.
Leider habe ich aber h"aufig mangels passender Hardware nicht die
M"oglichkeit, einen neuen Codegenerator praktisch zu testen, so da"s bei
Neuerungen "Uberraschungen nie ganz auszuschlie"sen sind. Das in
Abschnitt \ref{SectLicense} gesagte hat also schon seinen Grund...
Diese Flexibilit"at bedingt ein etwas exotisches Code-Format, f"ur dessen
Bearbeitung ich einige Tools beigelegt habe. Deren Beschreibung findet
sich in Abschnitt \ref{ChapTools}.
\asname{} ist ein Makroassembler, d.h. dem Programmierer ist die M"oglichkeit
gegeben, sich mittels Makros neue ,,Befehle'' zu definieren. Zus"atzlich
beherrscht er die bedingte Assemblierung. Labels in Makror"umpfen werden
automatisch als lokal betrachtet.
Symbole k"onnen f"ur den Assembler sowohl Integer-, String- als auch
Gleitkommawerte haben. Diese werden --- wie Zwischenergebnisse bei Formeln
--- mit einer Breite von 32 Bit f"ur Integerwerte, 80/64 Bit f"ur
Gleitkommawerte und 255 Zeichen f"ur Strings gespeichert. F"ur eine Reihe
von Mikrokontrollern besteht die M"oglichkeit, durch Segmentbildung die
Symbole bestimmten Klassen zuzuordnen. Dem Assembler kann man auf diese
Weise die --- begrenzte --- M"oglichkeit geben, Zugriffe in falsche
Adre"sr"aume zu erkennen.
Der Assembler kennt keine expliziten Beschr"ankungen bzgl.
Verschachtelungstiefe von Include-Dateien oder Makros, eine Grenze bildet
lediglich die durch den Hauptspeicher beschr"ankte Rekursionstiefe.
Ebenso gibt es keine Grenze f"ur die Symboll"ange, diese wird nur durch
die maximale Zeilenl"ange begrenzt.
Ab Version 1.38 ist \asname{} ein Mehrpass-Assembler. Dieser hochtrabende Begriff
bedeutet nicht mehr, als das die Anzahl der Durchg"ange durch die Quelltexte
nicht mehr zwei sein mu"s. Sind keine Vorw"artsreferenzen im Quellcode
enthalten, so kommt \asname{} mit einem Durchgang aus. Stellt sich dagegen im zweiten
Durchgang heraus, da"s ein Befehl mit einer k"urzeren oder l"angeren Kodierung
benutzt werden mu"s, so wird ein dritter (vierter, f"unfter...) Durchgang
eingelegt, um alle Symbolreferenzen richtig zu stellen. Mehr steckt hinter dem
Begriff ,,Multipass'' nicht...er wird im weiteren Verlauf dieser Anleitung
deswegen auch nicht mehr auftauchen.
Nach soviel Lobhudelei ein dicker Wermutstropfen: \asname{} erzeugt keinen
linkf"ahigen Code. Eine Erweiterung um einen Linker w"are mit erheblichem
Aufwand verbunden und ist momentan nicht in Planung.
Wer einen Blick in die Quellen von \asname{} werfen will, besorge sich einfach
die Unix-Version von \asname{}, die als Quelltext zum Selber "ubersetzen kommt.
Die Quellen sind mit Sicherheit nicht in einem Format, da"s das
Verst"andnis m"oglichst leicht macht - an vielen Stellen schaut noch
der originale Pascal-Quellcode heraus, und ich teile einige h"aufig
vertretene Ansichten "uber 'guten' C-Stil nicht...
%%----------------------------------------------------------------------
\section{Unterst"utzte Plattformen}
Obwohl \asname{} als ein reines DOS-Programm \marginpar{{\em DOS}} angefangen
hat, stehen auch eine Reihe von Versionen zur Verf"ugung, die etwas mehr
als den Real-Mode eines Intel-Prozessors ausnutzen k"onnen. Diese sind in
ihrer Benutzung soweit als m"oglich kompatibel gehalten zur DOS-Version,
es ergeben sich nat"urlich bisweilen Unterschiede in der Installation und
der Einbindung in die jeweilige Betriebssystemumgebung. Abschnitte in
dieser Anleitung, die nur f"ur eine bestimmte Version von \asname{} gelten, sind
mit einer entsprechenden Randbemerkung (an diesem Absatz f"ur die
DOS-Version) gekennzeichnet. Im einzelnen existieren die folgenden,
weiteren Versionen (die als getrennte Pakete distributiert werden):
F"ur den Fall, da"s \marginpar{{\em DPMI}} man bei der "Ubersetzung
gro"ser, komplexer Programme unter DOS Speicherplatzprobleme bekommt,
existiert eine DOS-Version, die mittels eines DOS-Extenders im Protected
Mode abl"auft und so das komplette Extended Memory eines ATs nutzen kann.
Die "Ubersetzung wird durch den Extender merklich langsamer, aber immerhin
l"auft es dann noch...
F"ur Freunde von IBM's Betriebssystem OS/2 \marginpar{{\em OS/2}} gibt es
eine native OS/2-Version von \asname{}. Seit 1.41r8 ist diese nur eine volle
32-bittige OS/2-Anwendung, was nat"urlich zur Folge hat, da"s OS/2 2.x
und ein 80386-Prozessor jetzt zwingend erforderlich sind.
Den reinen PC-Bereich verl"a"st man mit der \marginpar{{\em UNIX}}
C-Version von \asname{}, die so gehalten wurde, da"s sie auf einer m"oglichst
gro"sen Zahl von UNIX-artigen Systemen (dazu z"ahlt aber auch OS/2 mit dem
emx-Compiler) ohne gro"sartige Verrenkungen "ubersetzbar ist. Im
Gegensatz zu den vorherigen Versionen (die auf den auf Anfrage
erh"altlichen Pascal-Sourcen basieren) wird die C-Version im Quellcode
ausgeliefert, d.h. man mu"s sich mittels eines Compilers selbst die
Binaries erzeugen. Dies ist aber (f"ur mich) der eindeutig einfachere
Weg, als ein Dutzend Binaries f"ur Maschinen vorzukompilieren, auf die ich
auch nicht immer Zugriff habe...
%%===========================================================================
\cleardoublepage
\begin{quote}\begin{raggedright}{\it
Scotty: Captain, we din\verb!'! can reference it! \\
Kirk: Analysis, Mr. Spock? \\
Spock: Captain, it doesn\verb!'!t appear in the symbol table. \\
Kirk: Then it\verb!'!s of external origin? \\
Spock: Affirmative. \\
Kirk: Mr. Sulu, go to pass two. \\
Sulu: Aye aye, sir, going to pass two. \\
}\end{raggedright}\end{quote}
%%---------------------------------------------------------------------------
Je nach Version von \asname{} variieren die Hardware-Anforderungen deutlich:
Die DOS-Version \marginpar{{\em DOS}} l"auft prinzipiell auf allen
IBM-kompatiblen PCs, angefangen vom PC/XT mit vierkommawenig Megaherz bis
hin zum Pentium. Wie bei vielen anderen Programmen aber auch, steigt der
Lustgewinn mit der Hardware-Ausstattung. So d"urfte ein XT-Benutzer ohne
Festplatte erhebliche Probleme haben, die "uber 500 Kbyte gro"se
Overlay-Datei von \asname{} auf einer Diskette unterzubringen...eine Festplatte
sollte der PC also schon haben, allein um vern"unftige Ladezeiten zu
erreichen. Im Hauptspeicherbedarf ist \asname{} recht gen"ugsam: Das Programm
selber belegt knapp 300 Kbyte Hauptspeicher, \asname{} sollte also ab einer
Hauptspeichergr"o"se von 512 Kbyte ausf"uhrbar sein.
Die Version von \asname{} f"ur das \marginpar{{\em DPMI}}
DOS-Protected-Mode-Interface (DPMI) ben"otigt zum Ablaufen mindestens
einen 80286-Prozessor und 1 Mbyte freies Extended Memory. Daher stellen 2
Mbyte Hauptspeicher das absolute Minimum dar, wenn man im XMS sonst keine
anderen Spielereien (Platten-Cache, RAM-Disk, hochgeladenes DOS)
installiert hat, sonst entsprechend mehr. Falls man die DPMI-Version in
einer DOS-Box von OS/2 laufen l"a"st, so sollte DPMI auch in den
DOS-Einstellungen der Box erlaubt sein (Einstellung \tty{An} oder
\tty{Auto}) und der Box eine entsprechende Menge von XMS-Speicher
zugeordnet sein. Die virtuelle Speicherverwaltung von OS/2 sorgt hier
"ubrigens daf"ur, da"s man sich keine Gedanken machen mu"s, ob der
eingestellte Speicher auch real verf"ugbar ist.
Die C-Version \marginpar{{\em UNIX}} von \asname{} wird im Quellcode ausgeliefert
und erfordert damit ein Unix- oder OS/2-System mit einem C-Compiler.
Der Compiler mu"s dem ANSI-Standard gen"ugen (GNU-C erf"ullt diese
Bedingung zum Beispiel). Ob Ihr UNIX-System bereits getestet und die
n"otigen Definitionen vorgenommen wurden, k"onnen Sie der \tty{README}-Datei
entnehmen. Als zur Kompilation ben"otigten Plattenplatz sollten Sie
ca. 15 Mbyte veranschlagen; dieser Wert (und der nach der "Ubersetzung
noch ben"otigte Platz f"ur die "ubersetzten Programme) variiert
allerdings stark von System zu System, so da"s man diesen Wert nur als
Richtschnur betrachten sollte.
%%---------------------------------------------------------------------------
Prinzipiell erh"alt man \asname{} in einer von zwei Formen: Als {\em
Bin"ardistribution} oder {\em Quellcodedistribution}. Im Falle einer
Bin"ardistribution bekommt man \asname{} mit den zugeh"origen Dienstprogrammen
und Hilfsdateien fertig "ubersetzt, so da"s man nach dem Auspacken des
Archivs an die gew"unschte Stelle direkt loslegen kann.
Bin"ardistributionen werden f"ur verbreitete Plattformen gemacht, bei
denen die Mehrzahl der Benutzer keinen Compiler hat oder die "Ubersetzung
trickreich ist (im Moment sind dies DOS und OS/2). Eine
Quellcodedistribution enth"alt im Gegensatz den kompletten Satz an
C-Quellen, um \asname{} zu generieren; es ist letzten Endes ein Schnappschu"s
des Quellenbaumes, an dem ich \asname{} weiterentwickele. Die Generierung von \asname{}
aus dem Quellcode und dessen Struktur ist n"aher in Anhang
\ref{ChapSource} beschrieben, weshalb an dieser Stelle nur auf den
Umfang und die Installation einer Bin"ardistribution beschrieben wird:
Das Archiv des Lieferumfangs gliedert sich in einige Unterverzeichnisse,
so da"s man nach dem Auspacken sofort einen Verzeichnisbaum erh"alt. Die
Verzeichnisse enthalten im einzelnen:
\begin{itemize}
\item{{\tt BIN}: ausf"uhrbare Programme, Text-Resourcen;}
\item{{\tt INCLUDE}: Include-Dateien f"ur Assemblerprogramme, z.B.
Registerdefinitionen oder Standardmakros;}
\item{{\tt MAN}: Kurzreferenzen f"ur die Programme im Unix-Man-Format;}
\item{{\tt DOC}: diese Dokumentation in verschiedenen Formaten;}
\item{{\tt LIB}: vorgesehen f"ur Initialisierungsdateien.}
\end{itemize}
Eine Auflistung der Dateien, die in jeder Bin"ardistribution enthalten
sind, findet sich in Tabelle \ref{TabCommonPackageList}. Falls eine der
in diesen (oder den folgenden) Tabellen aufgef"uhrten Dateien fehlt, hat
jemand (im Zweifelsfalle ich) beim Kopieren geschlafen...
\begin{center}\begin{longtable}{|l|l|}
Datei & Funktion \\
\endhead
{\bf Verzeichnis BIN} & \\
AS.EXE & Programmdatei Assembler \\
PLIST.EXE & listet Inhalt von Codedateien auf \\
PBIND.EXE & kopiert Codedateien zusammen \\
P2HEX.EXE & wandelt Code- in Hexdateien um \\
P2BIN.EXE & wandelt Code- in Bin"ardateien um \\
AS.MSG & Textresourcen zu \asname{} *) \\
PLIST.MSG & Textresourcen zu PLIST *) \\
PBIND.MSG & Textresourcen zu PBIND *) \\
P2HEX.MSG & Textresourcen zu P2HEX *) \\
P2BIN.MSG & Textresourcen zu P2BIN *) \\
TOOLS.MSG & gemeinsame Textresourcen zu den Tools *) \\
CMDARG.MSG & gemeinsame Textresourcen zu allen Programmen *) \\
IOERRS.MSG & \\
\multicolumn{2}{|l|}{*) nur DOS} \\
{\bf Verzeichnis DOC} & \\
AS\_DE.DOC & deutsche Dokumentation, ASCII-Format \\
AS\_DE.HTML & deutsche Dokumentation, HTML-Format \\
AS\_DE.TEX & deutsche Dokumentation, LaTeX-Format \\
AS\_EN.DOC & englische Dokumentation, ASCII-Format \\
AS\_EN.HTML & englische Dokumentation, HTML-Format \\
AS\_EN.TEX & englische Dokumentation, LaTeX-Format \\
{\bf Verzeichnis INCLUDE} & \\
BCDIC.INC & Definition BCDIC/Codepage 359 \\
BITFUNCS.INC & Funktionen zur Bitmanipulation \\
CTYPE.INC & Funktionen zur Klassifizierung von \\
& Zeichen \\
EBCDIC.INC & Inkludiert alle EBCDIC-Varianten \\
CP037.INC & Definition EBCDIC (Codepage 037) \\
CP5100.INC & Definition Zeichensatz IBM 5100 \\
CP5110.INC & Definition EBCDIC (IBM 5110) \\
80C50X.INC & Registeradressen SAB C50x \\
80C552.INC & Registeradressen 80C552 \\
H8\_3048.INC & Registeradressen H8/3048 \\
KENBAK.INC & Registeradressen Kenbak-1 \\
RADIX50.INC & Definition RADIX 50 Zeichensatz \\
REG166.INC & Adressen \& Befehlsmakros 80C166/167 \\
REG251.INC & Adressen \& Bits 80C251 \\
REG29K.INC & Peripherieadressen AMD 2924x \\
REG53X.INC & Registeradressen H8/53x \\
REG6303.INC & Registeradressen 6303 \\
REG683XX.INC & Registeradressen 68332/68340/68360 \\
REG7000.INC & Registeradressen TMS70Cxx \\
REG78310.INC & Registeradressen \& Vektoren 78K3 \\
REG78K0.INC & Registeradressen 78K0 \\
REG96.INC & Registeradressen MCS-96 \\
REGACE.INC & Registeradressen ACE \\
REGAVROLD.INC & Register- \& Bitadressen AVR-Familie (veraltet)\\
REGAVR.INC & Register- \& Bitadressen AVR-Familie (aktuell)\\
REGCOLD.INC & Registeradressen ColdFire \\
REGCOP8.INC & Registeradressen COP8 \\
REGF8.INC & Register- \& Speicheradressen F8 \\
REGGP32.INC & Registeradressen 68HC908GP32 \\
REGH16.INC & Registeradressen H16 \\
REGHC12.INC & Registeradressen 68HC12 \\
REGM16C.INC & Registeradressen Mitsubishi M16C \\
REGMSP.INC & Registeradressen TI MSP430 \\
REGPDK.INC & Register- \& Bitadressen PMC/PMS/PFSxxx \\
REGS12Z.INC & Register- \& Bitadressen S12Z-Familie \\
REGST6.INC & Register- \& Makrodefinitionen ST6 (aktuell)\\
REGST7.INC & Register- \& Makrodefinitionen ST7 \\
REGSTM8.INC & Register- \& Makrodefinitionen STM8 \\
REGST9.INC & Register- \& Makrodefinitionen ST9 \\
REGZ380.INC & Registeradressen Z380 \\
STDDEF04.INC & Registeradressen 6804 \\
STDDEF16.INC & Befehlsmakros und Registeradressen \\
& PIC16C5x \\
STDDEF17.INC & Registeradressen PIC17C4x \\
STDDEF18.INC & Registeradressen PIC16C8x \\
STDDEF2X.INC & Registeradressen TMS3202x \\
STDDEF37.INC & Register- \& Bitadressen TMS370xxx \\
STDDEF3X.INC & Peripherieadressen TMS320C3x \\
STDDEF4X.INC & Peripherieadressen TMS320C4x \\
STDDEF47.INC & Befehlsmakros TLCS-47 \\
STDDEF51.INC & Definition von SFRs und Bits f"ur \\
& 8051/8052/80515 \\
STDDEF56K.INC & Registeradressen DSP56000 \\
STDDEF5X.INC & Peripherieadressen TMS320C5x \\
STDDEF60.INC & Befehlsmakros \& Registeradressen \\
& PowerPC \\
STDDEF62.INC & Registeradressen \& Makros ST6 (veraltet)\\
STDDEF75.INC & Registeradressen 75K0 \\
STDDEF87.INC & Register- \& Speicheradressen TLCS-870 \\
STDDEF90.INC & Register- \& Speicheradressen TLCS-90 \\
STDDEF96.INC & Register- \& Speicheradressen TLCS-900 \\
STDDEFXA.INC & SFR-\& Bitadressen Philips XA \\
STDDEFZ8.INC & Registeradressen Z8-Familie (alt)\\
REGV60.INC & Registeradressen NEC V60 \\
REGZ8.INC & Registeradressen Z8-Familie (neu)\\
REGSX20.INC & Register- \& Bitadressen Parallax SX20/28 \\
AVR/\*.INC & Register- \& Bitadressen AVR-Familie \\
& (nicht direkt benutzen, REGAVR.INC \\
& inkludieren) \\
COLDFIRE\/*.INC & Register- \& Bitadressen ColdFire-Familie \\
& (nicht direkt benutzen, REGCOLD.INC \\
& inkludieren) \\
PDK\/*.INC & Register- \& Bitadressen PMC/PMS/PFSxxx \\
& (nicht direkt benutzen, REGPDK.INC \\
& inkludieren) \\
S12Z\/*.INC & Register- \& Bitadressen S12Z-Familie \\
& (nicht direkt benutzen, REGS12Z.INC \\
& inkludieren) \\
ST6\/*.INC & Register- \& Bitadressen ST6-Familie \\
& (nicht direkt benutzen, REGST6.INC \\
& inkludieren) \\
ST7\/*.INC & Register- \& Bitadressen ST7-Familie \\
& (nicht direkt benutzen, REGST7.INC \\
& inkludieren) \\
STM8\/*.INC & Register- \& Bitadressen STM8-Familie \\
& (nicht direkt benutzen, REGSTM8.INC \\
& inkludieren) \\
Z8\/*.INC & Register- \& Bitadressen Z8-Familie \\
& (nicht direkt benutzen, REGZ8.INC \\
& inkludieren) \\
{\bf Verzeichnis LIB} & \\
{\bf Verzeichnis MAN} & \\
ASL.1 & Kurzanleitung zu AS \\
PLIST.1 & Kurzanleitung zu PLIST \\
PBIND.1 & Kurzanleitung zu PBIND \\
P2HEX.1 & Kurzanleitung zu P2HEX \\
P2BIN.1 & Kurzanleitung zu P2BIN \\
\caption{Standardumfang einer Bin"ardistribution
\label{TabCommonPackageList}}
\end{longtable}\end{center}
Je nach Plattform kann eine Bin"ardistribution aber noch weitere Dateien
enthalten, um einen Betrieb zu erm"oglichen, wie es z.B. bei DOS-Extendern
der Fall ist. F"ur die DOS-DPMI-Version \marginpar{{\em DPMI}} ergeben
sich die in Tabelle \ref{TabDPMIPackageList} gelisteten Erg"anzungen. Es
spricht "ubrigens nichts dagegen, als Hilfsprogramme die Versionen aus
einer DOS-Distribution zu verwenden, da diese einerseits ohne den
Extender-Overhead deutlich schneller ablaufen und andererseits den
vom Extender bereitgestellten erweiterten Speicher nicht ben"otigen.
\begin{table*}[htp]
\begin{center}\begin{tabular}{|l|l|}
Datei & Funktion \\
{\bf Verzeichnis BIN} & \\
DPMI16BI.OVL & DPMI-Server f"ur den Assembler \\
RTM.EXE & Laufzeit-Modul des Extenders \\
\end{tabular}\end{center}
\caption{Zus"atzliche Dateien in einer DPMI-Bin"ardistribution
\label{TabDPMIPackageList}}
\end{table*}
Eine OS/2-Bin"ardistribution \marginpar{{\em OS/2}} enth"alt neben den
Basisdateien eine Reihe von DLLs, die zur Laufzeitumgebung des verwendeten
emx-Compilers geh"oren (Tabelle \ref{TabOS2PackageList}). Falls man diese
DLLs (oder neuere Versionen davon) bereits besitzt, kann man diese auch
wieder l"oschen und seine eigenen benutzen.
\begin{table*}[htp]
\begin{center}\begin{tabular}{|l|l|}
Datei & Funktion \\
{\bf Verzeichnis BIN} & \\
EMX.DLL & Laufzeitbibliotheken f"ur \asname{} und \\
EMXIO.DLL & die Dienstprogramme \\
EMXLIBC.DLL & \\
EMXWRAP.DLL & \\
\end{tabular}\end{center}
\caption{Zus"atzliche Dateien in einer OS/2-Bin"ardistribution
\label{TabOS2PackageList}}
\end{table*}
%%---------------------------------------------------------------------------
Eine besondere \marginpar{{\em DOS}} Installation ist f"ur die Nutzung
einer Bin"ardistribution nicht notwendig, es gen"ugt, das Archiv an
passender Stelle auszupacken und dann noch einige Kleinigkeiten zu
erg"anzen. Als Beispiel hier eine Installation, wie sie vielleicht
ein UNIX-Anh"anger vornehmen w"urde:
Legen Sie ein Verzeichnis \verb!c:\as! an (im folgenden nehme ich an,
da"s Sie \asname{} auf Laufwerk C installieren wollen), wechseln Sie in dieses
und entpacken Sie das Archiv unter Erhalt der Verzeichnisnamen (bei
Verwendung von PKUNZIP ist dazu die Kommandozeilenoption \verb!-d!
erforderlich). Sie sollten jetzt folgenden Verzeichnisbaum haben:
\begin{verbatim}
c:\as
c:\as\bin
c:\as\lib
c:\as\man
c:\as\doc
\end{verbatim}
Erg"anzen Sie jetzt die \tty{PATH}-Anweisung in Ihrer \tty{AUTOEXEC.BAT}
um das Verzeichnis \verb!c:\as\bin!, so da"s \asname{} und seine Hilfsprogramme
vom System gefunden werden. In dem \tty{lib}-Verzeichnis erzeugen Sie
mit einem beliebigen Texteditor eine Datei \tty{AS.RC} mit folgendem
Inhalt:
\begin{verbatim}
\end{verbatim}
Diese sogenannte {\em Key-Datei} zeigt \asname{}, in welchem Verzeichnis er seine
Include-Dateien suchen soll. Damit \asname{} diese Key-Datei bei Start
auch beachtet, mu"s noch folgende Anweisung in die \tty{AUTOEXEC.BAT}:
\begin{verbatim}
set ASCMD=@c:\as\lib\as.rc
\end{verbatim}
Was Sie alles noch in der Key-Datei voreinstellen k"onnen, steht im
folgenden Abschnitt.
Die Installation der DPMI-Version \marginpar{{\em DPMI}} sollte im Prinzip
genauso verlaufen wie der reinen DOS-Version; wenn der Pfad das {\tt
bin}-Verzeichnis enth"alt, werden die Dateien des DOS-Extenders
automatisch gefunden und man sollte von dieser Mimik (mit Ausnahme der
l"angeren Anlaufzeit...) nichts mitbekommen. Theoretisch ist es m"oglich,
da"s Sie auf 80286-Rechnern beim ersten Start mit einer Meldung der
folgenden Form konfrontiert werden:
\begin{verbatim}
machine not in database (run DPMIINST)
\end{verbatim}
Da das Tool DPMIINST bei neueren Versionen des DOS-Extenders von Borland
aber nicht mehr dabei ist, nehme ich einmal an, da"s diese Sache sich
erledigt hat...falls doch nicht, bitte ich um R"uckmeldung!
Die Installation der OS/2-Version \marginpar{{\em OS/2}} kann in weiten
Z"ugen genauso ablaufen wie f"ur die DOS-Version, nur da"s dem System noch
die DLLs bekannt gemacht werden m"ussen. Wenn Sie den {\tt
LIBPATH}-Eintrag in Ihrer {\tt CONFIG.SYS} nicht erweitern wollen, ist es
nat"urlich auch m"oglich, die DLLs in ein Verzeichnis zu verschieben, das
bereits dort aufgef"uhrt ist.
Wie bereits erw"ahnt, beschr"ankt sich die Installationsbeschreibung hier
nur auf Bin"ardistributionen. Da eine Installation unter Unix
\marginpar{{\em UNIX}} im Augenblick immer eine Quellcodedistribution ist,
geht der Verweis hier unisono in Anhang \ref{ChapSource}.
%%---------------------------------------------------------------------------
\asname{} ist ein Kommandozeilen-gesteuertes Programm, d.h. alle Parameter
und Dateiangaben sind in der Kommandozeile anzugeben.
Zu \asname{} geh"ort eine Reihe Reihe von Nachrichtendateien (erkennbar an der
Endung {\tt MSG}, aus denen \asname{} zur Laufzeit die f"ur die jeweilige
Landessprache dynamisch nachl"adt. \asname{} sucht nach diesen Dateien in den
folgenden Verzeichnissen:
\begin{itemize}
\item{im aktuellen Verzeichnis;}
\item{im Verzeichnis der EXE-Datei;}
\item{in dem in der Environment-Variablen {\tt AS\_MSGPATH} angegebenen
Verzeichnis, oder alternativ in den in der {\tt PATH}-Variablen
gelisteten Verzeichnissen;}
\item{In dem Verzeichnis, das \asname{} zur Kompilationszeit durch das
Makro {\tt LIBDIR} mitgegeben wurde.}
\end{itemize}
Diese Dateien werden von \asname{} {\em zwingend} zum Betrieb ben"otigt, d.h.
findet \asname{} diese Dateien nicht, bricht er an dieser Stelle sofort ab.
Die Auswahl der Sprache (momentan Deutsch oder Englisch) orientiert sich
unter DOS und OS/2 an der {\tt COUNTRY}-Einstellung in der {\tt
CONFIG.SYS}, unter Unix an der {\tt LANG}-Environment-Variablen.
Um den \marginpar{{\em DOS}} Speicherbedarf von \asname{} unter DOS "uberhaupt
befriedigen zu k"onnen, wurden die verschiedenen Codegeneratormodule in
der DOS-Version in einen Overlay verlegt, der Teil des EXE-Files ist.
Eine getrennte OVR-Datei wie bei fr"uheren Versionen von \asname{} existiert also
nicht mehr, \asname{} versucht aber wie bisher auch weiterhin, die durch das
Overlaying entstehenden Verz"ogerungen durch Nutzung von eventuellem EMS-
oder XMS-Speicher zu reduzieren. Sollte diese Verwendung zu Problemen
f"uhren, so k"onnen Sie die Verwendung von EMS bzw. XMS unterbinden, indem
Sie einer Environment-Variablen \tty{USEXMS} bzw. \tty{USEEMS} den Wert
\tty{n} zuweisen. So kann man z.B. mit dem Befehl
\begin{verbatim}
SET USEXMS=n
\end{verbatim}
die Verwendung von Extended Memory verhindern.
Da \asname{} alle Ein-und Ausgaben "uber das Betriebssystem abwickelt (und daher
unter DOS auch auf nicht ganz so kompatiblen PCs laufen sollte) und eine
rudiment"are Bildschirmsteuerung ben"otigt, gibt er w"ahrend der
Assemblierung ANSI-Steuersequenzen aus.
Falls Sie in den Ausgaben von \asname{} \marginpar{{\em DOS/}} also seltsame
Zeichen sehen sollten, fehlt offensichtlich in Ihrer CONFIG.SYS die
Einbindung des ANSI-Trei\-bers (\tty{device=\-ansi.sys}), die weitere Funktion
von \asname{} \marginpar{{\em DPMI}} wird dadurch aber nicht beeinflu"st. Alternativ
k"onnen Sie aber auch die Ausgabe von ANSI-Sequenzen durch das Setzen der
Environment-Variablen \tty{USEANSI} auf \tty{n} ganz unterdr"ucken.
Der DOS-Extender der DPMI-Version \marginpar{{\em DPMI}} l"a"st sich in
seiner Speicherbelegung durch diverse Kommandozeilenoptionen beeinflussen.
Diese k"onnen Sie bei Bedarf der Datei DPMIUSER.DOC entnehmen.
Zus"atzlich ist sie in der Lage, bei Bedarf den vorhandenen Speicher
durch eine Swap-Datei zu ,,erweitern''. Dazu belegt man eine
Environment-Variable \tty{ASXSWAP} folgenderma"sen:
\begin{quote}{\tt
SET ASXSWAP=$<$Gr"o"se$>$[,Dateiname]
}\end{quote}
Die Gr"o"senangabe erfolgt in Megabytes und \bb{mu"s} gemacht werden. Der
Name der Datei ist dagegen optional; fehlt er, so wird die Swap-Datei im
aktuellen Verzeichnis unter dem Namen \tty{ASX.TMP} angelegt. In jedem
Falle wird die Swap-Datei nach Programmende wieder gel"oscht.
Die Kommandozeilenparameter k"onnen grob in drei Klassen eingeteilt
werden: Schalter, Key-File-Referenzen (s.u.) und Dateispezifikationen.
Parameter dieser beiden Klassen k"onnen beliebig gemischt in der
Kommandozeile auftreten, \asname{} wertet zuerst alle Parameter aus und
assembliert dann die angegebenen Dateien. Daraus folgen zwei Dinge:
\begin{itemize}
\item{Die angegebenen Schalter wirken auf alle angegebenen Quelldateien.
Sollen mehrere Quelldateien mit unterschiedlich gesetzten Schaltern
assembliert werden, so mu"s dies in getrennten L"aufen erfolgen.}
\item{Es k"onnen in einem Durchgang mehrere Dateien assembliert werden.
Um der Sache die Krone aufzusetzen, d"urfen die Dateiangaben
Jokerzeichen enthalten.}
\end{itemize}
Schalterparameter erkennt \asname{} daran, da"s sie durch einen
Schr"agstrich (/) oder Bindestrich (-) eingeleitet werden. Es gibt dabei
sowohl Schalter, die nur aus einem Buchstaben bestehen, als auch Schalter,
die aus einem ganzen Wort bestehen. Immer wenn \asname{} einen Schalter nicht
als ,,Wort-Schalter'' verstehen kann, so versucht er, die Buchstaben des
Wortes als einzelne Schalter zu interpretieren. Wenn man also z.B.
\begin{verbatim}
-queit
\end{verbatim}
anstelle von
\begin{verbatim}
-quiet
\end{verbatim}
geschrieben h"atte, w"urde \asname{} die Buchstaben \tty{q, u, e, i} und \tty{t}
als einzelne Schalter auffassen. Mehrbuchstabige Schalter unterscheiden
sich weiterhin von einbuchstabigen dadurch, da"s \asname{} bei ihnen beliebige
Gro"s-und Kleinschreibungen akzeptiert, w"ahrend einbuchstabige Schalter
je nach Gro"s- oder Kleinschreibung unterschiedliche Bedeutung haben.
Momentan sind folgende Schalter definiert:
\ttindex{SHARED}
\begin{itemize}
\item{\tty{l}: Assemblerlisting auf Konsole ausgeben. Falls mehrere
Passes ausgef"uhrt werden m"ussen, landen im Gegensatz zur
n"achsten Option die Listings aller Durchg"ange auf der Ausgabe!}
\item{\tty{L}: Assemblerlisting auf Datei schreiben. Die Listdatei erh"alt
dabei den gleichen Namen wie die Quelldatei, lediglich die Endung
wird durch \tty{LST} ersetzt, es sei denn...}
\item{\tty{OLIST}: mit einem zus"atzlichen Argument legt einen anderen
Pfad bzw. Namen f"ur die Listdatei fest. Falls mehrere Dateien
assembliert werden, kann diese Option auch mehrfach gegeben werden.}
\item{\label{listradix}\tty{LISTRADIX}: Defaultm"a"sig erfolgen alle Zahlenausgaben im Listing
(Adressen, erzeugter Code, Symboltabelle) im Hexadezimalsystem. Mit
diesem Schalter kann ein beliebiges anderes Zahlensystem im Bereich
2 bis 36 angegeben werden, z.B. '-listradix 8' f"ur oktale Ausgaben.
Wird der Zahlenwert mit f"uhrender Null geschrieben (also z.B. 08
anstelle 8), wird der Programmz"ahler im Listing mit f"uhrenden
Nullen geschrieben.}
\item{\tty{SPLITBYTE [Zeichen]}: Zahlen im Listing werden Byte-weise
dargestellt, mit dem angegebenen Zeichen als Trenner. Ein Punkt wird
als Trenner verwendet, wenn kein Zeichen angegeben wurde. Diese Option
wird "ublicherweise zusammen mit der \tty{LISTRADIX}-Option verwendet;
Listradix 8 zusammen mit einem Punkt als Trenner ergibt die sogenannte
''Split-Octal''-Darstellung.}
\item{\tty{o}:Bestimmt einen neuen Namen f"ur die von \asname{} zu erzeugende
Code-Datei. Wird diese Option mehrfach verwendet, so werden
die angegebenen Namen nacheinander den zu assemblierenden
Quelldateien zugeordnet; Negation (s.u.) dieser Option in
Verbindung mit einem Namen l"oscht den Namen aus der Liste;
Negation ohne Namensangabe l"oscht die komplette Liste.}
\item{\tty{SHAREOUT}:dito, nur f"ur eine eventuell zu erzeugende
SHARE-Datei}
\item{\tty{c}: SHARED-Variablen werden in einem Format abgelegt, das die
Einbindung in eine C-Quelldatei erlaubt. Die Endung der Datei
ist \tty{H}.}
\item{\tty{p}: SHARED-Variablen werden in einem Format abgelegt, das die
Einbindung in den \tty{CONST}-Block eines Pascal- oder Modula-Programms
erlaubt. Die Endung der Datei ist \tty{INC}.}
\item{\tty{a}: SHARED-Variablen werden in einem Format abgelegt, das die
Einbindung in eine Assembler-Quelldatei erlaubt. Die Endung
der Datei ist \tty{INC}.}
\end{itemize}
Zu Sinn und Funktion der SHARED-Symbole siehe Kapitel \ref{ChapShareMain}
bzw. \ref{ChapShareOrder}.
\begin{itemize}
\item{\tty{g [Format]}: Mit diesem Schalter erzeugt \asname{} zus"atzlich eine
Datei, die Debug-Informationen f"ur dieses Programm enth"alt.
Als Format ist dabei entweder ein \asname{}-eigenes Format ({\tt
Format=MAP}), eine NoICE-kompatible Kommandodatei ({\tt
Format=NOICE}) oder das Format der AVR-Tools ({\tt Format=ATMEL})
erlaubt. Zu den im MAP-Format gespeicherten
Informationen geh"ort zum einen die Symboltabelle, zum anderen eine
Zuordnung von Quellzeilen zu Maschinenadressen. Eine genauere
Beschreibung des benutzten MAP-Dateiformates findet sich in
Abschnitt \ref{SectDebugFormat}. Die Endung der Datei ist
\tty{MAP}, \tty{NOI} bzw. \tty{OBJ}, je nach gew"ahltem Format.
Wird keine explizite Formatangabe gemacht, wird das MAP-Format
gew"ahlt.}
\item{\tty{noicemask [Wert]}: Normalerweise listet \asname{} in NoICE-Debuginfos
nur Symbole aus dem CODE-Segment. Mit dieser Option und einem als
Bitmaske zu verstehenden Wert lassen sich andere Symbole aus
anderen Segmenten zuschalten. Die Zuordnung von Bits zu Segmenten
kann Tabelle \ref{TabSegmentNums} entnommen werden.}
\item{\tty{w}: Ausgabe von Warnungen unterdr"ucken;}
\item{\tty{E [Datei]}: Die von \asname{} erzeugten Fehlermeldungen und Warnungen
in eine Datei umleiten. Anstatt einer Datei k"onnen auch die 5
Standardhandles (STDIN..STDPRN) als !0 bis !4 angegeben werden.
Default ist !2, also STDERR. Wird die Dateiangabe weggelassen,
so ist der Name der Fehlerdatei gleich dem der Quelldatei, nur
mit der Endung \tty{LOG}.}
\item{\tty{q}: Dieser Schalter unterdr"uckt alle Meldungen von \asname{} mit
Ausnahme von Fehlermeldungen und vom Programm selber erzeugten
Ausgaben. Die Assemblierzeit kann dadurch geringf"ugig reduziert
werden, und beim Aufruf aus einer Shell heraus kann man sich eine
Umleitung ersparen. Der Nachteil ist, da"s man u.U. einige Minuten
,,im Dunklen'' steht... Anstelle von 'q' darf auch 'quiet' geschrieben
werden.}
\item{\tty{v}: Dies fordert auf"uhrliche Angaben an, also das Gegenteil
zum Quiet-Modus. Die einzige Angabe, die momentat zus"atzlich ausgegeben
wird, ist die Versionsinformation.}
\item{\tty{version}: Gibt Versionsinformationen aus und beendet sich.}
\item{\tty{h}: Hexadezimalzahlen mit Klein- anstelle von Gro"sbuchstaben ausgeben.
Diese Option ist in erster Linie eine Frage des pers"onlichen
Geschmacks.}
\item{\tty{i $<$Pfadliste$>$}: gibt eine Liste von Verzeichnissen an, in denen
der Assembler automatisch nach Include-Dateien suchen soll, falls
er diese nicht im aktuellen Verzeichnis findet. Die einzelnen
Verzeichnisse m"ussen durch Semikolons getrennt werden.}
\item{\tty{u}: eine Liste der in den Segmenten belegten Bereiche berechnen.
Sie ist nur sinnvoll, falls ein Listing erzeugt
wird. Diese Option ben"otigt erhebliche zus"atzliche Speicher-
und Rechenleistung, im Normalbetrieb sollte sie daher abgeschaltet
sein. Da \asname{} aber unabh"angig vom eingeschalteten Listing mit dieser
Option auf "uberlappende Speicherbelegung pr"uft, hat sie auch
unabh"angig vom Listing einen gewissen Sinn...}
\item{\tty{C}: erzeugt eine Liste mit Querverweisen. Aufgelistet wird,
welche (globalen) Symbole in welchen Dateien in welchen Zeilen
benutzt werden. Auch diese Liste wird nur generiert, falls
ein Listing erzeugt wird und belegt w"ahrend der
Assemblierung zus"atzlichen Speicherplatz.}
\item{\tty{s}: eine Liste aller Sektionen (s. Abschnitt \ref{ChapLocSyms})
ausgeben. Die Verschachtelung wird dabei durch Einr"uckungen
angedeutet.}
\item{\tty{I}: Analog zur Sektionsliste eine Liste aller bearbeiteten
Include-Dateien ausgeben.}
\item{\tty{t $<$Maske$>$}: Mit diesem Schalter lassen sich einzelne Komponenten
des standardm"a"sig ausgegebenen Assembler-Listings ein-und ausblenden.
Welcher Teil dabei welchem Bit zugeordnet ist, ist im "ubern"achsten
Abschnitt, der genauer auf das Format des Assembler Listings eingeht,
nachgelesen werden.}
\item{\tty{D $<$Symbolliste$>$}: Symbole definieren. Die hinter dieser Option
angegebenen, durch Kommas getrennten Symbole werden in der
globalen Symboltabelle vor Beginn der Assemblierung abgelegt.
Defaultm"a"sig werden diese Symbole als ganze Zahlen mit dem
Wert TRUE abgelegt, mit einem nachgestellten Gleichheitszeichen
kann aber auch eine andere Belegung gew"ahlt werden. Der dem
Gleichheitszeichen folgende Ausdruck darf dabei auch Operatoren
oder interne Funktionen beinhalten, jedoch \bb{KEINE} anderen
Symbole, selbst wenn diese schon davor in der Liste definiert
sein sollten! Zusammen mit den Befehlen zur bedingten
Assemblierung (siehe dort) k"onnen so per Kommandozeile aus einer
Quelldatei unterschiedliche Programmversionen erzeugt werden.
{\bf ACHTUNG!} Wenn case-sensitiv gearbeitet werden soll, mu"s dies
in der Kommandozeile {\em vor} Symboldefinitionen angegeben werden,
sonst werden Symbolnamen schon an dieser Stelle in Gro"sbuchstaben
umgewandelt!}
\item{\tty{A}: Die Liste globaler Symbole in einer anderen, kompakteren Form
ablegen. Verwenden Sie diese Option, wenn der Assembler bei
langen Symboltabellen mit einem Stapel"uberlauf abst"urzt.
Eventuell kann diese Option die Arbeitsgeschwindigkeit des
Assemblers erh"ohen, dies h"angt jedoch von den Quellen ab.}
\item{\tty{x}: Legt die Ausf"uhrlichkeitsstufe von Fehlermeldungen fest.
Jedes Mal, wenn diese Option angegeben wird, wird die Stufe
um eins erh"oht oder gesenkt. W"ahrend auf Stufe 0 (Vorgabe) nur
der Fehler selber ausgegeben wird, wird ab Stufe 1 noch eine
erweiterte Meldung ausgegeben, anhand der die Identifizierung des
Fehlers erleichtert werden soll. Welche Fehlermeldungen welche
Zusatzinformationen tragen k"onnen, steht in Anhang \ref{ChapErrMess}
mit der Liste aller Fehlermeldungen. Auf Stufe 2 (Maximum) wird
zus"atzlich noch die betroffene Quellzeile mit ausgegeben.}
\item{\tty{n}: Wird diese Option angegeben, so werden Fehlermeldungen nicht nur
mit ihrem Klartext, sondern auch mit ihren im Anhang
\ref{ChapErrMess} genannten internen Nummern ausgegeben. Diese
Option ist prim"ar f"ur Shells und Entwicklungsumgebungen gedacht,
denen mit diesen Nummern die Identifizierung von Fehlern erleichtert
werden soll.}
\item{\tty{U}: Mit dieser Option schaltet man \asname{} in den case-sensitiven
Modus um, d.h. in Namen von Symbolen, Sektionen, Makros,
Zeichentabellen und selbst definierte Funktionen werden Klein-
und Gro"sbuchstaben unterschieden, was normalerweise nicht der
Fall ist.}
\item{\tty{P}: weist \asname{} an, den von Makroprozessor und bedingter Assemblierung
bearbeiteten Quelltext in einer Datei abzulegen. Dieser Datei
fehlen zus"atzlich Leer- und reine Kommentarzeilen. Die Endung
der Datei ist \tty{I}.}
\item{\tty{M}: mit diesem Schalter erzeugt \asname{} eine Datei, in der die Definitionen
der Makros aus der Quelldatei abgespeichert werden, die die
\tty{EXPORT}-Option verwenden. Diese neue Datei hat den gleichen
Namen wie die Quelldatei, lediglich die Endung wird in \tty{MAC} ge"andert.}
\item{\tty{G}: Dieser Schalter bestimmt, ob \asname{} Code erzeugen soll oder nicht.
Ist er ausgeschaltet, wird die Datei zwar assembliert,
aber keine Code-Datei geschrieben. Dieser Schalter ist defaultm"a"sig aktiviert
(logisch, sonst bek"ame man ja auch gar kein Code-File).}
\item{\tty{r [n]}: Warnungen ausgeben, falls Situationen eintreten, die
einen weiteren Pass erfordern. Diese Information kann genutzt
werden, um die Anzahl der Durchl"aufe zu verringern. Optional kann
man die Nummer des Passes angeben, ab dem diese Warnungen erzeugt
werden; ohne Angabe kommen die Warnungen ab dem ersten Pass. Machen
Sie sich aber so oder so auf einen ziemlichen Haufen an Meldungen
gefa"st!!}
\item{\tty{bigendian}: Mit diesem Schalter schaltet man vom Beginn des
Programms die Ablage von Werten im Speicher im Big Endian Modus ein,
sofern die Zielarchitektur den gleichnamigen Pseudobefehl unterst"utzt
(siehe Abschnitt \ref{SectBIGENDIAN}).}
\item{\tty{plainbase}: Mit diesem Schalter erlaubt man vom Beginn des
Programms an das Fortlassen eines leeren Indexarguments (siehe Abschnitt
\item{\tty{underscore-macroargs}: Erlaubt die Verwendung von Unterstrichen in
Namen von Makro-Argumenten (siehe \ref{SectMacros}).}
\item{\tty{relaxed}: Mit diesem Schalter aktiviert man den RELAXED-Modus
vom Beginn des Programms an, der ansonsten erst durch die gleichnamige
Pseudoanweisung (siehe Abschnitt \ref{SectRELAXED}) eingeschaltet
werden mu"s.}
\item{\tty{supmode}: Mit diesem Schalter erlaubt man vom Beginn des Programms
an die Verwendung von Maschinenbefehlen, die nur im Supervisor-Modus
des Prozessors verwendet werden d"urfen (siehe Abschnitt \ref{SectSUPMODE}).}
\item{\tty{Y}: Mit diesem Schalter weist man \asname{} an, alle Fehlermeldungen
wegen zu langer Sprungdistanzen zu verwerfen, sobald die Notwendigkeit
eines neuen Durchlaufs feststeht. In welchen (seltenen) Situationen
dieser Schalter notwendig ist, kann man in Abschnitt \ref{ForwRefs}
nachlesen.}
\item{\tty{cpu $<$Name$>$}: Hiermit kann man man den Zielprozessor
vorgeben, f"ur den \asname{} Code erzeugen soll, wenn die Quelldatei keinen
{\tt CPU}-Befehl enth"alt.
Falls das gew"ahlte Ziel CPU-Argumente unterst"utzt (siehe Abschnitt
\ref{SectCPU}), k"onnen diese auch hier angegeben werden. Ein Aufruf
mit \verb!?! oder {\tt list} als Argument listet alle implementierten
Zielprozessoren auf.}
\item{\tty{alias $<$neu$>$=$<$alt$>$}:\\
definiert den Prozessortyp \tty{$<$neu$>$} als einen Alias f"ur den
Typen \tty{$<$alt$>$}. Zu den Sinn und Zweck von Aliasen siehe
Abschnitt \ref{SectAlias}}
\item{{\tt gnuerrors}: Meldungen "uber Fehler bzw. Warnungen und deren
Position nicht im Standardformat von \asname{}, sondern in einem dem GNU
C-Compiler entlehnten Format anzeigen. Dies erleichtert die
Integration von \asname{} in f"ur dieses Format ausgelegte Umgebungen,
unterdr"uckt aber gleichzeitig die Anzeige der pr"azisen
Fehlerposition innerhalb Makror"umpfen!}
\item{{\tt maxerrors [n]}: Weist den Assembler an, nach der gegebenen
Anzahl von Fehlern die Assemblierung abzubrechen.}
\item{{\tt maxinclevel [n]}: Weist den Assembler an, nach der gegebenen
Include-Verschachtelungstiefe abzubrechen (Default ist 200).}
\item{{\tt Werror}: Weist den Assembler an, Warnungen als Fehler zu
behandeln.}
\item{\tty{compmode}: Dieser Schalter weist den Assembler an, im Default
im Kompatibilit"atsmodus zu arbeiten. Genauere Informationen zu
diesem Modus finden sich im Abschnitt \ref{SectCompMode}.}
\item{\tty{packing}: Dieser Schalter "ubersteuert den Architektur-
abh"angigen Default f"ur die {\tt PACKING}-Option (siehe
Abschnitt \ref{SectPACKING}).}
\end{itemize}
Sofern Schalter keine Argumente ben"otigen und ihre Zusammenziehung
keinen mehrbuchstabigen Schalter ergibt, k"onnen mehrere Schalter
auch auf einen Rutsch angegeben werden, wie z.B im folgenden Beispiel:
\begin{verbatim}
as test*.asm firstprog -cl /i c:\as\8051\include
\end{verbatim}
Es werden alle Dateien TEST*.ASM sowie die Datei FIRSTPROG.ASM
assembliert, wobei f"ur alle Dateien Listings auf der Konsole
ausgegeben und Sharefiles im C-Format erzeugt werden. Nach Includes
soll der Assembler zus"atzlich im Verzeichnis \verb! C:\AS\8051\INCLUDE !
suchen.
Dieses Beispiel zeigt nebenbei, da"s \asname{} als Defaultendung f"ur Quelldateien
\tty{ASM} annimmt.
Etwas Vorsicht ist bei Schaltern angebracht, die ein optionales Argument
haben: Folgt auf einen solchen Schalter ohne Argument ein Dateiname, so
versucht \asname{}, diesen als Argument zu verwerten, was naturgem"a"s schief
geht:
\begin{verbatim}
as -g test.asm
\end{verbatim}
Die L"osung w"are in diesem Fall, die \tty{-g}-Option ans Ende der
Kommandozeile zu setzen oder ein explizites \tty{MAP}-Argument zu
spezifizieren.
Neben der Angabe in der Kommandozeile k"onnen dauernd ben"otigte
Optionen in der Environment-Variablen ASCMD abgelegt werden. Wer z.B.
immer Listdateien haben m"ochte und ein festes Include-Verzeichnis hat,
kann sich mit dem Befehl
\begin{verbatim}
\end{verbatim}
eine Menge Tipparbeit ersparen. Da die Environment-Optionen vor der
Kommandozeile abgearbeitet werden, k"onnen Optionen in der
Kommandozeile widersprechende im Environment "ubersteuern.
Bei sehr langen Pfaden kann es jedoch auch in der ASCMD-Variablen eng
werden. F"ur solche F"alle kann auf eine sogenannte \ii{Key}-Datei
ausgewichen werden, in der die Optionen genauso wie in der Kommandozeile
oder ASCMD-Variablen abgelegt werden k"onnen, nur da"s diese Datei
mehrere Zeilen mit jeweils maximal 255 Zeichen enthalten darf. Wichtig
ist dabei, da"s bei Optionen, die ein Argument ben"otigen, sowohl Schalter
als auch Argument in \bb{einer} Zeile stehen m"ussen. Der Name der
Datei wird \asname{} dadurch mitgeteilt, da"s er mit einem vorangestellten
Klammeraffen in der ASCMD-Variablen abgelegt wird, z.B.
\begin{verbatim}
set ASCMD=@c:\as\as.key
\end{verbatim}
Um Optionen in der ASCMD-Variablen (oder der Key-Datei) wieder aufzuheben,
kann die Option mit einem vorangestellten Pluszeichen wieder aufgehoben
werden. Soll in einem Einzelfall z.B. doch kein Listing erzeugt werden,
so kann es mit
\begin{verbatim}
as +L <Datei>
\end{verbatim}
wieder aufgehoben werden. Nat"urlich ist es nicht ganz logisch, eine
Option mit einem Pluszeichen zu negieren...UNIX soit qui mal y pense.
Referenzen auf eine Key-Datei k"onnen nicht nur von der {\tt
ASCMD}-Variablen aus erfolgen, sondern auch direkt von der Kommandozeile
aus, indem man analog zur {\tt ASCMD}-Variablen dem Dateinamen einen
Klammeraffen voranstellt:
\begin{verbatim}
as @<Datei> ....
\end{verbatim}
Die in einem solchen Fall aus dem Key-File gelesenen Optionen werden so
eingearbeitet, als h"atten sie anstelle dieser Referenz in der
Kommandozeile gestanden - es ist also {\em nicht} wie bei der {\tt
ASCMD}-Variablen so, da"s sie vor allen anderen Kommandozeilenoptionen
abgearbeitet werden w"urden.
Das Referenzieren eines Key-Files von einem Key-File selber ist nicht
erlaubt und wird von \asname{} mit einer Fehlermeldung quittiert.
F"ur den Fall, da"s Sie \asname{} von einem anderen Programm oder einer Shell
aufrufen wollen und diese Shell nur Klein- oder Gro"sbuchstaben in der
Kommandozeile "ubergeben will, existiert folgendes Workaround: Wird vor
den Buchstaben der Option eine Tilde gesetzt, so werden die folgenden
Buchstaben immer als Kleinbuchstaben interpretiert. Analog erzwingt
ein Lattenzaun die Interpretation als Gro"sbuchstaben. Es ergeben
sich z.B. folgende Transformationen:
\begin{quote}{\tt
/\verb!~!I $\longrightarrow$ /i \\
-\verb!#!u $\longrightarrow$ -U}
\end{quote}
Abh"angig vom Ablauf der Assemblierung endet der Assembler mit
folgenden Returncodes:
\begin{description}
\item[0]{fehlerfreier Ablauf, h"ochstens Warnungen aufgetreten}
\item[1]{Der Assembler hat nur die Aufrufparameter ausgegeben und
endete danach sofort.}
\item[2]{Es sind Fehler bei der Assemblierung aufgetreten, es wurde
keine Code-Datei erzeugt.}
\item[3]{Es trat ein fataler Fehler w"ahrend des Ablaufes auf, der
zum sofortigen Abbruch gef"uhrt hat.}
\item[4]{Bereits w"ahrend des Starts des Assemblers ist ein Fehler
aufgetreten. Dies kann ein Parameterfehler oder eine fehlerhafte
Overlay-Datei sein.}
\item[255]{Bei der Initialisierung ist irgendein interner Fehler
aufgetreten, der auf keinen Fall auftreten sollte...neu booten,
noch einmal probieren, und bei Reproduzierbarkeit mit mir
Verbindung aufnehmen!}
\end{description}
Zus"atzlich endet jede Assemblierung einer Datei mit einer kleinen
Statistik, die Fehlerzahlen, Laufzeit, Anzahl der Durchl"aufe und freien
Speicher ausgibt. Bei eingeschaltetem Assembler-Listing wird diese
Statistik zus"atzlich auch in das Listing geschrieben.
OS/2 \marginpar{{\em OS/2}} erweitert wie Unix das Datensegment einer
Anwendung erst dann, wenn sie wirklich mehr Speicher anfordert. Eine
Angabe wie
\begin{quote}{\tt
511 KByte verf"ugbarer Restspeicher
}\end{quote}
bedeutet also nicht einen nahenden Systemabsturz wegen Speichermangel,
sondern stellt nur den Abstand zu der Grenze dar, bei der OS/2 einfach
ein paar mehr Kohlen in den Ofen schaufelt...
Da es unter C \marginpar{{\em UNIX}} auf verschiedenen Betriebssystemen
keine kompatible M"oglichkeit gibt, den noch verf"ugbaren Speicher bzw.
Stack zu ermitteln, fehlen bei der C-Version diese beiden Angaben ganz.
%%---------------------------------------------------------------------------
\section{Format der Eingabedateien}
Wie die meisten Assembler auch erwartet \asname{} genau einen Befehl pro Zeile
(Leerzeilen sind nat"urlich auch zugelassen). Die Zeilen d"urfen nicht
l"anger als 255 Zeichen werden, dar"uber hinaus gehende Zeichen werden
abgeschnitten.
Eine einzelne Zeile hat folgendes Format:
\begin{verbatim}
[Label[:]]<Befehl>[.Attribut] [Parameter[,Parameter..]] [;Kommentar]
\end{verbatim}
Eine Zeile darf dabei auch "uber mehrere Zeilen in der Quelldatei
verteilt sein, Folgezeichen (\verb!\!) verketten diese Teile dann zu
einer einzigen Zeile. Zu beachten ist allerdings, da"s aufgrund der
internen Pufferstruktur die Gesamtzeile nicht 256 Zeichen "uberschreiten
darf. Zeilenangaben in Fehlermeldungen beziehen sich immer auf die
letzte Zeile einer solchen zusammengesetzten Zeile.
Der Doppelpunkt nach dem Label ist optional, falls das Label in der
ersten Spalte beginnt (woraus folgt, da"s ein Befehl, sei es ein
Maschinen- oder Pseudobefehl niemals in Spalte 1 beginnen darf).
Man mu"s ihn aber setzen, falls das Label nicht in der ersten Spalte
beginnt, damit \asname{} es von einem Befehl unterscheiden kann. In letzterem
Fall mu"s "ubrigens zwischen Doppelpunkt und dem Befehl mindestens ein
Leerzeichen stehen, falls der eingestellte Zielprozessor zu denjenigen
geh"ort, bei denen das Attribut auch eine mit einem Doppelpunkt
abgetrennte Formatangabe sein darf. Diese Einschr"ankung ist aus
Eindeutigkeits-Gr"unden n"otig, da sonst keine Unterscheidung zwischen
Befehl mit Format und Label mit Befehl m"oglich w"are.
Einige Signalprozessorreihen von Texas Instruments verwenden den f"ur das
Label vorgesehenen Platz wahlweise auch f"ur einen Doppelstrich
(\verb!||!), der die parallele Ausf"uhrung mit der vorangehenden
Instruktion anzeigt. Wenn diese beiden Instruktionen auf Maschinenebene
in einem einzigen Wort vereinigt werden (C3x/C4x), macht ein zus"atzliches
Label vor der zweiten Anweisung nat"urlich keinen Sinn und ist auch nicht
vorgesehen. Anders sieht es beim C6x mit seinen Instruktionspaketen
variabler L"ange aus: Wer dort (unsch"onerweise...) mitten in ein Paket
hinein springen will, mu"s das Label daf"ur in eine Extrazeile davor setzen
(das gleiche gilt "ubrigens auch f"ur Bedingungen, die aber zusammen mit
dem Doppelstrich in einer Zeile stehen d"urfen).
Das Attribut wird von einer Reihe von Prozessoren benutzt, um
Spezialisierungen oder Kodierungsvarianten eines bestimmten Befehls zu
spezifizieren. Die bekannteste Nutzung des Attributs ist die Angabe der
Operandengr"o"se, wie z. B. bei der 680x0-Familie (Tabelle
\begin{table*}[htb]
\begin{center}\begin{tabular}{|l|l|l|}
Attribut & arithmetisch-logischer Befehl & Sprungbefehl \\
B & Byte (8 Bit) & 8-bit-displacement \\
W & Wort (16 Bit) & 16-Bit-Displacement \\
L & Langwort (32 Bit) & 16-Bit-Displacement \\
Q & Vierfachwort (64 Bit) & --------- \\
C & Half Precision (16 Bit) & --------- \\
S & Single Precision (32 Bit) & 8-Bit-Displacement \\
D & Double Precision (64 Bit) & --------- \\
X & Extended Precision (80/96 Bit) & 32-Bit-Displacement \\
P & Dezimalgleitkomma (80/96 Bit) & --------- \\
\end{tabular}\end{center}
\caption{Erlaubte Attribute (Beispiel 680x0) \label{TabAttrs}}
\end{table*}
Da sich diese Anleitung nicht gleichzeitig als Handbuch f"ur die von \asname{}
unterst"utzten Prozessorfamilien versteht, ist dies leider auch nicht der
richtige Platz, um hier alle m"oglichen Attribute f"ur alle unterst"utzten
Familien aufzuz"ahlen. Es sei aber angemerkt, da"s i.a. nicht alle Befehle
alle Attribute zulassen, andererseits das Fortlassen eines Attributs meist
zur Verwendung der f"ur diese Familie ,,nat"urlichen'' Operandengr"o"se
f"uhrt. Zum genaueren Studium greife man auf ein Programmierhandbuch f"ur
die jeweilige Familie zur"uck, z.B. in \cite{Williams} f"ur die 68000er.
Bei TLCS-9000, H8/500 und M16(C) dient das Attribut sowohl der Angabe der
Operandengr"o"se, falls diese nicht durch die Operanden klar sein sollte,
als auch der des zu verwendenden Befehlsformates.
Dieses mu"s durch einen Doppelpunkt von der Operandengr"o"se getrennt werden,
z.B. so:
\begin{verbatim}
add.w:g rw10,rw8
\end{verbatim}
Was dieses Beispiel nicht zeigt, ist, da"s die Formatangabe auch ohne
Operandengr"o"se geschrieben werden darf. Steht demgegen"uber eine
Operandengr"o"se ohne Formatangabe, verwendet \asname{} automatisch das
k"urzeste Format. Die erlaubten Befehlsformate und Operandengr"o"sen
sind vom Maschinenbefehl abh"angig und k"onnen z.B. \cite{Tosh9000},
\cite{HitH8_5}, \cite{MitM16} bzw. \cite{MitM16C} entnommen werden.
Die Zahl der Befehlsparameter ist abh"angig vom Befehl und kann
prinzipiell zwischen 0 und 20 liegen. Die Trennung der Parameter
voneinander erfolgt ausschlie"slich durch Kommas (Ausnahme: DSP56xxx,
dessen parallele Datentransfers durch Leerzeichen getrennt werden),
wobei in Klammern oder Hochkommas eingeschlossene Kommas nat"urlich
nicht beachtet werden.
Anstelle eines Kommentars am Ende kann die Zeile auch nur aus einem
Kommentar bestehen, wenn er in der ersten Spalte beginnt.
Bei den Leerzeichen zur Trennung einzelnen Komponenten darf es sich
genauso gut um Tabulatoren handeln.
%%---------------------------------------------------------------------------
Das von \asname{} bei Angabe der Kommandozeilenoptionen \tty{l} oder \tty{L}
erzeugte Listing l"a"st sich grob in folgende Teile gliedern:
\begin{enumerate}
\item{Wiedergabe des assemblierten Quellcodes;}
\end{enumerate}
Letztere beide werden nur erzeugt, wenn sie durch zus"atzliche
Kommandozeilenoptionen angefordert wurden.
Im ersten Teil listet \asname{} den kompletten Inhalt aller Quelldateien inklusive
des erzeugten Codes auf. Eine Zeile in diesem Listing hat dabei folgende Form:
\begin{verbatim}
[<n>] <Zeile>/<Adresse> <Code> <Quelle>
\end{verbatim}
Im Feld $n$ zeigt \asname{} die Include-Verschachtelungstiefe an. Die
Hauptdatei (die Datei, mit der die Assemblierung begann), hat dabei die
Tiefe 0, von dort aus eingebundene Dateien haben Tiefe 1 usw. Die Tiefe
0 wird dabei nicht angezeigt: F"ur Zeilen der Hauptdatei wird dieses Feld
durch eine passende Zahl von Leerzeichen ersetzt, oder g"anzlich fortgelassen,
falls es bisher gar keine Include-Anweisungen gegeben hat. Das 'Ged"achtnis',
ob es Include-Anweisungen gegeben hat, und bis zu welcher Tiefe, reicht
"uber den einzelnen Pass hinaus. Auf diese Weise 'lernt' der Assembler im
ersten Pass die maximale Tiefe und kann in folgenden Durchl"aufen dieses
Feld mit durchgehend gleicher Breite ausgeben.
Im Feld \tty{Zeile} wird die Zeilennummer bezogen auf die jeweilige Datei
ausgegeben. Die erste Zeile einer Datei hat dabei Nummer 1. Die Adresse,
an der der f"ur diese Zeile erzeugte Code abgelegt wurde, folgt hinter dem
Schr"agstrich im Feld \tty{Adresse}. Das daf"ur verwendete Zahlensystem
wird durch den {\tt listradix}-Schalter festgelegt (\ref{listradix}), ebenso
ob der Wert mit f"uhrenden Nullen angezeigt werden soll oder nicht. Das
gerade aktuell verwendete Target mit der Gr"o"se seines Adre"sraumes bestimmt
die Breite des Feldes: F"ur einen Prozessor mit 64 KByte Adre"sraum sind
nur 4 Hex-Stellen erforderlich, bei 4 GByte dagegen acht.
Der erzeugte Code selber steht dahinter im Feld \tty{Code} in
hexadezimaler Schreibweise. Je nach Prozessortyp und aktuellem Segment
k"onnen die Werte entweder als Bytes oder 16/32-Bit-Worte formatiert sein.
Sollte mehr Code erzeugt worden sein, als in das Feld hineinpa"st, so
werden im Anschlu"s an die Zeile weitere Zeilen erzeugt, in denen nur
dieses Feld belegt ist.
Im Feld \tty{Quelle} schlu"sendlich wird die Zeile aus der Quelldatei in
ihrer Originalform ausgegeben.
Die Symboltabelle ist so ausgelegt, da"s sie nach M"oglichkeit immer in 80
Spalten dargestellt werden kann. F"ur Symbole ,,normaler L"ange'' wird
eine zweispaltige Ausgabe gew"ahlt. Sollten einzelne Symbole mit ihrem
Wert die Grenze von 40 Spalten "uberschreiten, werden sie in einer
einzelnen Zeile ausgegeben. Die Ausgabe erfolgt in alphabetischer
Reihenfolge. Symbole, die zwar definiert, aber nie benutzt wurden,
werden mit einem vorangestellten Stern (\verb!*!) gekennzeichnet.
Die bisher genannten Teile sowie die Auflistung aller definierten
Makros / Funktionen lassen sich selektiv aus dem Gesamtlisting ein-und
ausblenden, und zwar mit dem bereits erw"ahnten \tty{t}-Kommandozeilenschalter.
Intern existiert in \asname{} ein Byte, dessen Bits repr"asentieren, welche Teile
ausgegeben werden sollen. Die Zuordnung von Bits zu den Teilen ist in
Tabelle \ref{TabTBits} aufgelistet.
\begin{table*}[p]
\begin{center}\begin{tabular}{|l|l|}
Bit & Teil \\
0 & Quelldatei(en)+erzeugter Code \\
1 & Symboltabelle \\
2 & Makroliste \\
3 & Funktionsliste \\
4 & Zeilennumerierung \\
5 & Registersymboltabelle \\
7 & Zeichentabellenliste \\
\end{tabular}\end{center}
\caption{Zuordnung der Bits zu den Listingkomponenten\label{TabTBits}}
\end{table*}
Defaultm"a"sig sind alle Bits auf 1 gesetzt, bei Verwendung des Schalters
\begin{verbatim}
-t <Maske>
\end{verbatim}
werden die in \verb!<Maske>! gesetzten Bits gel"oscht, so da"s die entsprechenden
Listing-Teile unterdr"uckt werden. Analog lassen sich mit einem Pluszeichen
einzelne Teile wieder einschalten, falls man es in der \tty{ASCMD}-Variablen
"ubertrieben hat...will man z.B. nur die Symboltabelle haben, so reicht
\begin{verbatim}
-t 2 .
\end{verbatim}
In der Belegungsliste werden f"ur jedes Segment einzeln die belegten Bereiche
hexadezimal ausgegeben. Handelt es sich bei einem Bereich um eine einzige
Adresse, wird nur diese ausgegeben, ansonsten erste und letzte Adresse.
In der Querverweisliste wird f"ur jedes definierte Symbol in alphabetischer
Reihenfolge eine Ausgabe folgender Form erzeugt:
\begin{verbatim}
Symbol <Symbolname> (=<Wert>,<Datei>/<Zeile>):
Datei <Datei 1>:
<n1>[(m1)] ..... <nk>[(mk)]
.
.
Datei <Datei l>:
<n1>[(m1)] ..... <nk>[(mk)]
\end{verbatim}
F"ur jedes Symbol wird aufgelistet, in welchen Dateien es in welchen Zeilen
angesprochen wurde. Sollte ein Symbol mehrmals in der gleichen Zeile
benutzt worden sein, so wird dies durch eine in Klammern gesetzte Anzahl
hinter der Zeilennummer angedeutet. Sollte ein Symbol niemals benutzt
worden sein, erscheint es auch nicht in der Liste; entsprechend erscheint
eine Datei auch "uberhaupt nicht in der Liste eines Symbols, falls es in
der entsprechenden Datei nicht referenziert wurde.
\bb{ACHTUNG!} \asname{} kann dieses Listing nur dann korrekt aufs Papier bringen,
wenn man ihm vorher die L"ange und Breite des Ausgabemediums mit Hilfe des
\tty{PAGE}-Befehls (siehe \ref{SectPAGE}) mitgeteilt hat! Der voreingestellte
Default sind 60 Zeilen und eine unbegrenzte Zeilenbreite.
%%---------------------------------------------------------------------------
Symbole d"urfen zwar (wie in der Einleitung bereits angedeutet) bis zu
255 Zeichen lang werden und werden auch auf der ganzen L"ange
unterschieden, die Symbolnamen m"ussen aber einigen Konventionen
gen"ugen:
Symbolnamen d"urfen aus einer beliebigen Kombination von Buchstaben,
Ziffern, Unterstrichen und Punkten bestehen, wobei das erste Zeichen
keine Ziffer sein darf. Der Punkt wurde nur zugelassen, um der
MCS-51-Notation von Registerbits zu gen"ugen, und sollte m"oglichst nicht in
eigenen Symbolnamen verwendet werden. Zur Segmentierung von Symbolnamen
sollte auf jeden Fall der Unterstrich und nicht der Punkt verwendet werden.
Defaultm"a"sig ist \asname{} nicht case-sensitiv, es ist also egal, ob man
Gro"s-oder Kleinbuchstaben verwendet. Mittels des Kommandozeilenschalters
\tty{U} l"a"st sich \asname{} jedoch in einen Modus umschalten, in dem Gro"s- und
Kleinschreibung unterschieden wird. Ob \asname{} umgeschaltet wurde, kann mit dem
vordefinierten Symbol \tty{CASESENSITIVE} ermittelt werden: TRUE bedeutet
Unterscheidung, FALSE keine.
Tabelle \ref{TabPredefined} zeigt die wichtigsten, von \asname{} vordefinierten
Symbole.
\begin{table*}[p]
\begin{center}\begin{tabular}{|l|l|}
Name & Bedeutung \\
\tty{TRUE} & logisch ,,wahr'' \\
\tty{FALSE} & logisch ,,falsch'' \\
\tty{CONSTPI} & Kreiszahl Pi (3.1415.....) \\
\tty{VERSION} & Version von \asname{} in BCD-Kodierung, \\
& z.B. 1331 hex f"ur Version 1.33p1 \\
\tty{ARCHITECTURE} & Zielplattform, f"ur die \asname{} "ubersetzt wurde, \\
& in der Form Prozesor-Hersteller-Betriebssystem \\
\tty{DATE} & Datum und \\
\tty{TIME} & Zeitpunkt der Assemblierung (Beginn) \\
\tty{MOMCPU} & momentan gesetzte Ziel-CPU \\
\tty{MOMCPUNAME} & dito, nur als voll ausgeschriebener String \\
\tty{MOMFILE} & augenblickliche Quelldatei \\
\tty{MOMLINE} & Zeilennummer in Quelldatei \\
\tty{MOMPASS} & Nummer das laufenden Durchgangs \\
\tty{MOMSECTION} & Name der aktuellen Sektion oder \\
& Leerstring \\
\tty{MOMSEGMENT} & Name des mit \tty{SEGMENT} gew"ahlten \\
& Adre"sraumes \\
\verb!*!, \$, . bzw. \tty{PC} & mom. Programmz"ahler \\
\end{tabular}\end{center}
\end{table*}
\bb{VORSICHT!} W"ahrend es im case-insensitiven Modus egal ist,
mit welcher Kombination von Gro"s- und Kleinbuchstaben man
vordefinierte Symbole anspricht, mu"s man sich im case-sensitiven
Modus exakt an die oben angegebene Schreibweise (nur Gro"sbuchstaben)
halten!
Zus"atzlich definieren einige Pseudobefehle noch Symbole, die eine
Abfrage des damit momentan eingestellten Wertes erm"oglichen. Deren
Beschreibung findet sich bei den zugeh"origen Befehlen.
Ein etwas verstecktes (und mit Vorsicht zu nutzendes) Feature ist,
Symbolnamen aus String-Variablen zusammenzubauen, indem man den
Namen des Strings mit geschweiften Klammern in den Symbolnamen
einbaut. So kann man z.B. den Namen eines Symbols anhand des
Wertes eines anderen Symbols festlegen:
\begin{verbatim}
cnt set cnt+1
temp equ "\{CNT}"
jnz skip{temp}
.
.
skip{temp}: nop
\end{verbatim}
\bb{ACHTUNG!} Der Programmierer ist selber daf"ur verantwortlich,
da"s sich dabei g"ultige Symbolnamen ergeben!
Eine vollst"andige Auflistung aller von \asname{} verwendeten Symbolnamen
findet sich in Anhang \ref{AppInternSyms}.
Neben seinem Wert besitzt auch jedes Symbol eine Markierung, zu welchen
{\em Segment} es geh"ort. In erster Linie wird eine solche Unterscheidung
bei Prozessoren ben"otigt, die mehrere Adre"sr"aume besitzen. \asname{} kann mit
dieser Zusatzinformation bei Zugriffen "uber ein Symbol warnen, wenn ein
f"ur diesen Adre"sraum ungeeigneter Befehl verwendet wird. Ein
Segmentattribut wird einem Symbol automatisch angeh"angt, wenn es als Label
oder mit einem Spezialbefehl (z.B. \tty{BIT}) definiert wird; ein mit
dem ,,Universalbefehl'' \tty{SET} oder \tty{EQU} definiertes Symbol ist
jedoch ,,typenlos'', d.h. seine Verwendung wird niemals Warnungen
ausl"osen. Das Segmentattribut eines Symbols kann mit der eingebauten
Funktion \tty{SYMTYPE} abgefragt werden, etwa so:
\begin{verbatim}
Label:
.
.
Attr equ symtype(Label) ; ergibt 1
\end{verbatim}
Den einzelnen Segmenttypen sind die in Tabelle \ref{TabSegNums}
aufgelisteten Nummern zugeordnet. Die aus der Ordnung normaler Symbole
etwas herausfallenden Registersymbole sind n"aher in Abschnitt
\ref{SectRegSyms} erl"autert. Mit einem undefinierten Symbol als Argument
liefert die \tty{SYMTYPE}-Funktion -1 als Ergebnis. Ob ein Symbol "uberhaupt
definiert ist, l"a"st sich auch einfach mit der \tty{DEFINED}-Funktion abfragen.
\begin{table}[htb]
\begin{center}
\begin{tabular}{|l|c|}
Segment & R"uckgabewert \\
$<$keines$>$ & 0 \\
CODE & 1 \\
DATA & 2 \\
IDATA & 3 \\
XDATA & 4 \\
YDATA & 5 \\
BITDATA & 6 \\
IO & 7 \\
REG & 8 \\
ROMDATA & 9 \\
EEDATA & 10 \\
$<$Registersymbol$>$ & 128 \\
\end{tabular}
\end{center}
\caption{R"uckgabewerte der \tty{SYMTYPE}-Funktion\label{TabSegNums}}
\end{table}
%%---------------------------------------------------------------------------
Besonders bei Programmen mit vielen aufeinanderfolgenden Schleifen oder
IF-artigen Strukturen steht man immer wieder vor dem Problem, sich
st"andig neue Namen f"ur Labels ausdenken zu m"ussen. Dabei wei"s man an
sich genau, da"s man dieses Label nie wieder brauchen wird und am liebsten
in irgendeiner Weise 'verwerfen' m"ochte. Eine einfache L"osung, wenn man
nicht gleich den gro"sen Hammer des Sektionskonzeptes (siehe Kapitel
\ref{ChapLocSyms}) schwingen m"ochte, sind {\em tempor"are} Symbole, die
solange ihre G"ultigkeit behalten, bis ein neues, nicht-tempor"ares Symbol
definiert wird. Andere Assembler bieten einen "ahnlichen Mechanismus an,
der dort unter dem Stichwort 'lokale Symbole' l"auft, zur besseren
Abgrenzung gegen das Sektionskonzept m"ochte ich aber beim Begriff
'tempor"are Symbole' bleiben. \asname{} kennt drei unterschiedliche Typen von
tempor"aren Symbolen, um jedem 'Umsteiger' ein Konzept anzubieten, das den
Umstieg so einfach wie m"oglich macht. Leider kocht quasi jeder Assembler
bei diesem Thema sein eigenes S"uppchen, so da"s es nur in Ausnahmef"allen
eine 1:1-L"osung f"ur existierenden Code geben wird:
Ein Symbol, dessen Name mit zwei Dollarzeichen beginnt (dies ist weder
f"ur normale Symbole noch Konstanten zul"assig), ist ein tempor"ares
Symbol mit Namen. \asname{} f"uhrt intern einen Z"ahler mit, der zu Beginn der
Assemblierung auf Null gesetzt wird und bei jeder Definition eines
nicht-tempor"aren Symbols inkrementiert wird. Wird ein tempor"ares Symbol
definiert oder referenziert, so werden die beiden f"uhrenden Dollarzeichen
gestrichen und der momentane Stand des Z"ahlers wird angeh"angt. Auf
diese Weise erh"alt man mit jedem nicht-tempor"aren Symbol sozusagen die
Symbolnamen zur"uck - man kommt an die Symbole vor dieser Definition aber
auch nicht mehr heran! Tempor"are Symbole bieten sich daher besonders
f"ur den Einsatz in kleinen Anweisungsbl"ocken an, typischerweise etwa ein
Dutzend Befehle, auf keinen Fall mehr als eine Bildschirmseite, sonst
kommt man leicht durcheinander...
Hier ein kleines Beispiel:
\begin{verbatim}
$$loop: nop
dbra d0,$$loop
split:
$$loop: nop
dbra d0,$$loop
\end{verbatim}
W"are das zwischen den Schleifen liegende nicht-tempor"are Label nicht
vorhanden, g"abe es nat"urlich eine Fehlermeldung wegen eines doppelt
definierten Symbols.
{\em Namenlose Tempor"are Symbole}
F"ur all jene, denen tempor"are Symbole mit Namen noch immer zu
kompliziert sind, gibt es eine noch einfachere Variante: Setzt man als
Label ein einfaches Plus- oder Minuszeichen, so werden diese in die Namen
{\tt \_\_forwnn} bzw. {\tt \_\_backmm} umgesetzt, wobei {\tt nn} bzw. {\tt mm}
von Null an laufende Z"ahler sind. Referenziert werden diese Symbole
"uber die Sonderwerte {\tt - -- ---} bzw. {\tt + ++ +++}, womit sich die
drei letzten 'Minussymbole' bzw die drei n"achsten 'Plussymbole'
referenzieren lassen. Welche Variante man benutzt, h"angt also davon ab,
ob man ein Symbol vorw"arts oder r"uckw"arts referenzieren will.
Bei der {\em Definition} namenloser tempor"arer Symbole gibt es neben dem
Plus- und Minuszeichen noch eine dritte Variante, n"amlich einen
Schr"agstrich (/). Ein so definiertes tempor"ares Symbol kann
gleicherma"sen vorw"arts wie r"uckw"arts referenziert werden; d. h. je
nach Referenzierung wird es wie ein Minus oder Plus behandelt.
Namenlose tempor"are Symbole finden ihre Anwendung "ublicherweise in
Konstruktionen, die auf eine Bildschirmseite passen, wie das bedingte
"Uberspringen von ein paar Maschinenbefehlen oder kleinen Schleifen -
ansonsten w"urde die Sache zu un"ubersichtlich werden (das ist aber nur
ein gut gemeinter Rat...). Ein Beispiel daf"ur ist das folgende St"uck
Code, zur Abwechslung mal als 65xx-Code:
\begin{verbatim}
cpu 6502
- ldx #00
- dex
bne - ; springe zu 'dex'
lda RealSymbol
beq + ; springe zu 'bne --'
jsr SomeRtn
iny
+ bne -- ; springe zu 'ldx #00'
SomeRtn:
rts
RealSymbol:
dfs 1
inc ptr
bne + ; springe zu 'tax'
inc ptr+1
+ tax
bpl ++ ; springe zu 'dex'
beq + ; springe vorwaerts zu 'rts'
lda #0
/ rts ; Schraegstrich = Wildcard
+ dex
beq - ; springe rueckwaerts zu 'rts'
ptr: dfs 2
\end{verbatim}
Dies ist vielleicht der Typ von tempor"aren Symbolen, der dem Konzept von
lokalen Symbolen und Sektionen am n"achsten kommt. Wann immer der Name
eines Symboles mit einem Punkt (.) anf"angt, wird das Symbol nicht mit
diesem Namen in der Symboltabelle abgelegt. Stattdessen wird der Name des
zuletzt definierten Symbols ohne vorangestellten Punkt davor geh"angt. Auf
diese Weise nehmen Symbole, deren Name nicht mit einem Punkt anf"angt, quasi
die Rolle von 'Bereichsgrenzen' ein und Symbole, deren Name mit einem
Punkt anf"angt, k"onnen in jedem Bereich neu verwendet werden. Sehen wir
uns das folgende kurze Beispiel an:
\begin{verbatim}
proc1: ; nicht-temporaeres Symbol 'proc1'
.loop moveq #20,d0 ; definiert in Wirklichkeit 'proc1.loop'
dbra d0,.loop
rts
proc2: ; nicht-temporaeres Symbol 'proc2'
.loop moveq #10,d1 ; definiert in Wirklichkeit 'proc2.loop'
jsr proc1
dbra d1,.loop
rts
\end{verbatim}
Man beachte, da"s es weiterhin m"oglich ist, auf alle tempor"aren Symbole
zuzugreifen, auch wenn man sich nicht im gleichen 'Bereich' befindet,
indem man einfach den zusammengesetzten Namen benutzt (wie z.B.
'proc2.loop' im voranstehenden Beispiel).
Zusammengesetzte Symbole lassen sich prinzipiell mit Sektionen kombinieren
und k"onnen so auch zu lokalen Symbolen werden. Man beachte allerdings,
da"s das zuletzt definierte, nicht tempor"are Symbol nicht pro Sektion
gespeichert wird, sondern lediglich global. Das kann sich
aber auch irgendwann einmal "andern, man sollte sich also nicht auf das
augenblickliche Verhalten verlassen.
%%---------------------------------------------------------------------------
An den meisten Stellen, an denen der Assembler Zahlenangaben erwartet,
k"onnen nicht nur einfache Symbole oder Konstanten angegeben werden,
sondern ganze Formelausdr"ucke. Bei den Komponenten der Formelausdr"ucke
kann es sich sowohl um ein einzelnes Symbol als auch um eine Konstante
handeln. Konstanten d"urfen entweder Integer-, Gleitkomma-, oder
Stringkonstanten sein.
Integerkonstanten bezeichnen ganze Zahlen. Sie werden als eine
Folge von Ziffern geschrieben. Dies kann in verschiedenen
Zahlensystemen erfolgen, deren Notation von verwendeten
Zielprozessor abh"angt (Tabelle
\begin{table*}[htbp]
\begin{center}\begin{tabular}{|l|c|c|c|c|}
& Intel-Modus & Motorola-Modus & C-Modus & IBM-Modus \\
dezimal & direkt & direkt & direkt & direkt \\
hexadezimal & Suffix H & Pr"afix \$ & Pr"afix 0x & X'..' oder H'..' \\
\ii{Kennung}& \tty{hexh} & \tty{\$hex} & \tty{0xhex} & \tty{x'hex'} \\
& & & & \tty{h'hex'} \\
bin"ar & Suffix B & Pr"afix \% & Pr"afix 0b & B'..' \\
\ii{Kennung}& \tty{binb} & \tty{\%bin} & \tty{0bbin} & \tty{b'bin'} \\
oktal & Suffix O oder Q & Pr"afix @ & Pr"afix 0 & O'..' \\
\ii{Kennung}& \tty{octo} & \tty{@oct} & \tty{0oct} & \tty{o'oct'} \\
& \tty{octq} & & & \\
ASCII & & & & A'..' \\
\ii{Kennung}& & & & \tty{a'asc'} \\
\end{tabular}\end{center}
\caption{definierte Zahlensysteme und Schreibweisen\label{TabSystems}}
\end{table*}
Falls das Zahlensystem nicht explizit durch vor-oder nachgestellte Zeichen
vorgegeben wird, nimmt \asname{} die Basis an, die mit dem {\tt RADIX}-Befehl
vorgegeben wurde (deren Default ist wiederum 10). Mit diesem Befehl lassen
sich auch ,,ungew"ohnliche'' Zahlensysteme, d.h. andere als 2, 8, 10 oder 16
einstellen.
G"ultige Ziffern sind die Zahlen 0 bis 9 sowie die Buchstaben A bis Z
(Wert 10 bis 35) bis zur Basis des Zahlensystems minus eins. Die ASCII-
Darstellung f"allt etwas aus diesem System heraus: hier beschreibt der
ASCII-Wert (bzw. der Code im aktuell eingestellten Zeichensatz, siehe
Abschnitt \ref{SectCHARSET}) ein ganzes Byte. Solcherart geschriebene
Integer-Konstanten sind also letzten Endes identisch zu Multi-Character-Konstanten.
Die beiden Schreibweisen:
\begin{verbatim}
'ABCD'
A'ABCD'
\end{verbatim}
sind also identisch, das vorangestellte 'A' ist eigentlich redundant. Man
kann diese Schreibweise aber f"ur existierenden Code erlauben, weil einige "altere
Original-Assembler (z.B. Signetics 2650) diese Schreibweise unterst"utzen.
Multi-Character-Konstanten sind bei \asname{} grunds"atzlich immer Big-Endian,
d.h. 'ABCD' ergibt den Zahlenwert 0x41424344. Warum das so ist? Naja,
das erste \asname{}-Target war der Motorola 68000, und es hat sich nie jemand
dar"uber beklagt...die einzige Ausnahme von
dieser Regel ist die PDP-11 (und der einen LSI-11 nutzende WD16): zwecks
besserer Kompatibilit"at zum MACRO-11 von DEC sind solche Konstanten
ausnahmsweise Little-Endian, 'AB' ergibt also den Zahlenwert 0x4241.
Die Verwendung von Buchstaben in Integerkonstanten bringt allerdings auch
einige Mehrdeutigkeiten mit sich, da Symbolnamen ja auch Ketten aus Zahlen
und Buchstaben sind: Ein Symbolname darf nicht mit einem Zeichen von 0 bis
9 beginnen, was bedeutet, da"s eine Integerkonstante, die nicht durch ein
anderes Sonderzeichen eindeutig als solche erkennbar ist, niemals mit
einem Buchstaben beginnen darf; notfalls mu"s man eine eigentlich
"uberfl"ussige Null voranstellen. Der bekannteste Fall ist das Schreiben
von Hexadezimalkonstanten im Intel-Modus: Ist die vorderste Stelle
zwischen A und F, so hilft das hintangestellte H "uberhaupt nichts, es
mu"s noch eine Null davor (statt F0H also 0F0H). Die Motorola-oder
C-Syntax, die beide das Zahlensystem am Anfang einer Integerkonstante
kennzeichnen, kennen dieses Problem nicht.
Reichlich heimt"uckisch ist auch, da"s bei immer h"oheren, mit {\tt RADIX}
eingestellten Zahlensystemen, die bei Intel- und C-Syntax benutzten
Buchstaben zur Zahlensystemkennung immer weiter ,,aufgefressen'' werden; so
kann man z.B. nach {\tt RADIX 16} keine bin"aren Konstanten mehr
schreiben, und ab {\tt RADIX 18} in Intel-Syntax auch keine hexadezimalen
Konstanten mehr. Also {\bf VORSICHT!}
Welche Syntax f"ur welchen Zielprozessor im Default verwendet wird, ist
im Anhang \ref{SectPseudoInst} gesammelt. Unabh"angig von diesem Default
ist es m"oglich, einzelne Schreibweisen mit dem \tty{INTSYNTAX}-Befehl
(siehe Abschnitt \ref{SectINTSYNTAX}) weg- oder dazuzuschalten. Die unter
\ii{Ident} aufgef"uhrten Namen, mit einem vorangestellten Plus- oder
Minuszeichen, dienen bei diesem Befehl als Argumente.
Eine Art ''Generalschalter' f"ur Integer-Schreibweisen ist der
\tty{RELAXED}-Befehl (siehe Abschnitt \ref{SectRELAXED}): Unabh"angig
vom Zielprozessor k"onnen beliebige Schreibweisen verwendet werden
kann (auf Kosten der Kompatibilit"at zu Standard-Assemblern).
Mit \tty{INTSYNTAX} bzw. \tty{RELAXED} er"offnet sich insbesondere die
'IBM-Schreibweise', wie man sie bei manchen Fremdassemblern antrifft,
f"ur alle Ziele:
Bei dieser Schreibweise wird der eigentliche Wert in Hochkommas geschrieben
und das Zahlensystem ('x' oder 'h' f"ur hexadezimal, 'o' f"ur oktal und 'b'
f"ur bin"ar) direkt davor. Die Integer-Konstante 305419896 kann damit
also folgenderma"sen geschrieben werden:
\begin{verbatim}
x'12345678'
h'12345678'
o'2215053170'
b'00010010001101000101011001111000'
\end{verbatim}
Als weitere Variante dieser Schreibweise erlauben einige wenige Targets
das Fortlassen des schlie"senden Hochkommas, zwecks Kompatibilt"at zu
Code, der f"ur andere Assembler geschrieben wurde. F"ur eigenen, neu
erstellten Code wird von der Verwendung abgeraten.
Gleitkommazahlen werden in der "ublichen halblogarithmischen
Schreibweise geschrieben, die in der allgemeinsten Form
\begin{verbatim}
[-]<Vorkommastellen>[.Nachkommastellen][E[-]Exponent]
\end{verbatim}
lautet. \bb{ACHTUNG!} Der Assembler versucht eine Konstante zuerst als
Integerkonstante zu verstehen und macht erst dann einen Versuch mit
Gleitkomma, falls dies gescheitert ist. Will man aus irgendwelchen
Gr"unden die Auswertung als Gleitkommazahl erzwingen, so kann man
dies durch Dummy-Nachkommastellen erreichen, z.B. \tty{2.0} anstelle
\tty{2}.
Stringkonstanten m"ussen in einfache oder doppelte Hochkommas
eingeschlossen werden. Um diese selber und andere Sonderzeichen ohne
Verrenkungen in String-Konstanten einbauen zu k"onnen, wurde ein
,,Escape-Mechanismus'' eingebaut, der C-Programmierer*innen bekannt
vorkommen d"urfte:
Schreibt man einen Backslash mit einer maximal dreiziffrigen Zahl im
String, so versteht der Assembler dies als Zeichen mit dem entsprechenden
dezimalen ASCII-Wert. Alternativ kann der Zahlenwert auch hexadezimal
oder oktal mit einem vorangestellten x oder einer vorangestellten 0
geschrieben werden. F"ur die hexadezimale Schreibweise reduziert sich die
Maximalanzahl von Stellen auf 2. So kann man z.B. mit {\tt\verb!\3!} ein
ETX-Zeichen definieren. Vorsicht allerdings mit der Definition von
NUL-Zeichen! Da die C-Version \marginpar{{\em UNIX}} von \asname{} momentan
intern zur Speicherung von String-Symbolen C-Strings benutzt (die durch
NUL-Zeichen terminiert werden), sind NUL-Zeichen in Strings momentan nicht
portabel!
Einige besonders h"aufig gebrauchte Steuerzeichen kann man auch mit
folgenden Abk"urzungen erreichen:
\begin{quote}\begin{tabbing}
\verb!\b! : Backspace \> \verb!\a! : Klingel \> \verb!\e! : Escape \\
\verb!\t! : Tabulator \> \verb!\n! : Zeilenvorschub \> \verb!\r! : Wagenr"ucklauf \\
\verb!\\! : Backslash \> \verb!\'! oder \verb!\h! : Hochkomma \\
\verb!\"! oder \verb!\i! : G"ansef"u"schen \\
\end{tabbing}\end{quote}
Die Kennbuchstaben d"urfen sowohl gro"s als auch klein geschrieben
werden.
"Uber dieses Escape-Zeichen k"onnen sogar Formelausdr"ucke in den
String eingebaut werden, wenn sie in geschweifte Klammern eingefa"st
werden: z.B. ergibt
\begin{verbatim}
message "Wurzel aus 81 : \{sqrt(81)}"
\end{verbatim}
die Ausgabe
\begin{verbatim}
Wurzel aus 81 : 9
\end{verbatim}
Der Assembler w"ahlt anhand des Formelergebnistyps die richtige
Ausgabeform, zu vermeiden sind lediglich weitere Stringkonstanten
im Ausdruck, da der Assembler bei der Gro"s-zu-Kleinbuchstabenumwandlung
sonst durcheinander kommt. Integer-Ausdr"ucke werden defaultm"a"sig
hexadezimal ausgegeben, dies l"a"st sich jedoch mit dem
\tty{OUTRADIX}-Befehl "andern.
Bis auf den Einbau von Formelausdr"ucken ist dieser Escape-Mechanismus
auch in als ASCII definierten Integerkonstanten zul"assig, z.B. so:
\begin{verbatim}
move.b #'\n',d0
\end{verbatim}
Jedoch hat alles seine Grenzen, weil der dar"uber liegende Splitter, der
die Zeile in Opcode und Parameter zerlegt, nicht wei"s, womit er da
eigentlich arbeitet, z.B. hier:
\begin{verbatim}
move.l #'\'abc',d0
\end{verbatim}
Nach dem dritten Hochkomma findet er das Komma nicht mehr, weil er
vermutet, da"s eine weitere Zeichenkonstante beginnt, und eine
Fehlermeldung "uber eine falsche Parameterzahl ist die Folge. Abhilfe
w"are z.B., \verb!\h! anstelle \verb!\'! zu schreiben.
\subsection{String- zu Integerwandlung und Zeichenkonstanten}
Fr"uhere Versionen von \asname{} verfolgten eine strikte Trennung von Strings
und sogenannten ''Zeichenkonstanten'': Eine Zeichenkonstante sieht
auf den ersten Blick aus wie ein String, nur sind die Zeichen in
einfache Hochkommas statt doppelte eingeschlossen. Ein solches
Objekt hatte den Datentyp 'Integer', war also eine Zahl, deren Wert
durch den (ASCII-)Wert des jeweiligen Zeichens definiert war, und wurde
strikt von einer String-Konstante unterschieden:
\begin{verbatim}
move.b #65,d0
move.b #'A',d0 ; gleichwertig
move.b #"A",d0 ; nicht erlaubt in aelteren Versionen!
\end{verbatim}
Diese Unterscheidung existiert {\em nicht mehr}, es ist also egal, ob
man einfache oder doppelte Hochkommas verwendet. Wird an einer Stelle eine
Zahl als Argument erwartet, und ein String verwendet, so erfolgt die
Umwandlung anhand der (ASCII-)Werte ''on-the-fly'' an dieser Stelle. Im
obigen Beispiel w"urden alle drei Anweisungen den gleichen Maschinencode
erzeugen.
Eine solche implizite Wandlung findet auch f"ur aus mehreren Zeichen
bestehende Strings statt, die dann bisweilen als ''Mehrzeichenkonstanten''
bezeichnet werden:
\begin{verbatim}
'A' == $41
"AB" == $4142
'ABCD' == $41424344
\end{verbatim}
Mehrzeichenkonstanten sind der einzige Fall, in denen die Verwendung von
einfachen oder doppelten Hochkommas noch einen Unterschied macht. F"ur
viele Zielprozessoren sind Pseudobefehle zur Ablage von Konstanten definiert,
die als Argument verschiedene Datentypen akzeptieren. Will man wirklich
eine Zeichenkette haben, so mu"s man in diesem Fall weiterhin doppelte
Hochkommas verwenden:
\begin{verbatim}
dc.w "ab" ; legt zwei Worte (0x0041,0x0042) ab
dc.w 'ab' ; legt ein Wort (0x4142) ab
\end{verbatim}
Wichtig: dies ist nicht erforderlich, wenn die Zeichenkette l"anger als die
verwendete Operandegr"o"se ist, in diesem Beispiel also l"anger als zwei
Zeichen bzw. 16 Bit.
Die Berechnung von im Formelausdruck entstehenden Zwischenergebnissen
erfolgt immer mit der h"ochsten verf"ugbaren Wortbreite, d.h. 32 oder 64 Bit
f"ur Ganzzahlen, 80 Bit f"ur Gleitkommazahlen und 255 Zeichen f"ur Strings.
Eine eventuelle Pr"ufung auf Wertebereichs"uberschreitung findet erst am
Endergebnis statt.
Die portable C-Version \marginpar{{\em UNIX}} kann nur mit
64-Bit-Gleitkommazahlen umgehen, ist daher auf einen Maximalwert von ca.
$10^{308}$ beschr"ankt. Als Ausgleich werden auf einigen Plattformen
Integers mit 64 Bit Breite behandelt.
Der Assembler stellt zur Verkn"upfung die in Tabelle \ref{TabOps} genannten
Operanden zur Verf"ugung.
\begin{table*}[htbp]
\begin{center}\begin{tabular}{|c|l|c|c|c|c|c|c|}
Op. & Funktion & \#Ops. & Int & Float & String & Register & Rang \\
$<>$ & Ungleichheit & 2 & ja & ja & ja & ja & 14 \\
$!=$ & Alias f"ur $<>$ & & & & & & \\
$>=$ & gr"o"ser o. gleich & 2 & ja & ja & ja & ja & 14 \\
$<=$ & kleiner o. gleich & 2 & ja & ja & ja & ja & 14 \\
$<$ & echt kleiner & 2 & ja & ja & ja & ja & 14 \\
$>$ & echt gr"o"ser & 2 & ja & ja & ja & ja & 14 \\
$=$ & Gleichheit & 2 & ja & ja & ja & ja & 14 \\
$==$ & Alias f"ur $=$ & & & & & & \\
& & & & & & \\
$!!$ & log. XOR & 2 & ja & nein & nein & nein & 13 \\
$||$ & log. OR & 2 & ja & nein & nein & nein & 12 \\
\&\& & log. AND & 2 & ja & nein & nein & nein & 11 \\
\verb! ~~ ! & log. NOT & 1 & ja & nein & nein & nein & 2 \\
& & & & & & \\
- & Differenz & 2 & ja & ja & nein & nein & 10 \\
+ & Summe & 2 & ja & ja & ja & nein & 10 \\
\# & Modulodivision & 2 & ja & nein & nein & nein & 9 \\
/ & Quotient & 2 & ja*) & ja & nein & nein & 9 \\
\verb! * ! & Produkt & 2 & ja & ja & nein & nein & 9 \\
\verb! ^ ! & Potenz & 2 & ja & ja & nein & nein & 8 \\
& & & & & & \\
$!$ & bin"ares XOR & 2 & ja & nein & nein & nein & 7 \\
$|$ & bin"ares OR & 2 & ja & nein & nein & nein & 6 \\
\& & bin"ares AND & 2 & ja & nein & nein & nein & 5 \\
$><$ & Bitspiegelung & 2 & ja & nein & nein & nein & 4 \\
$>>$ & log. Rechtsschieben & 2 & ja & nein & nein & nein & 3 \\
$<<$ & log. Linksschieben & 2 & ja & nein & nein & nein & 3 \\
\verb! ~ ! & bin"ares NOT & 1 & ja & nein & nein & nein & 1 \\
\multicolumn{8}{|l|}{*) Rest wird verworfen} \\
\end{tabular}\end{center}
\end{table*}
Unter ,,Rang'' ist dabei die Priorit"at zu verstehen, die dieser Operator bei
der Teilung eines Ausdruckes in Unterausdr"ucke hat, der rangh"ochste
Operator wird also \ii{zuletzt} ausgewertet. Die Reihenfolge der
Evaluierung l"a"st sich durch Klammerung neu festlegen.
Die Vergleichsoperatoren liefern TRUE, falls die Bedingung zutrifft,
und FALSE falls nicht. Vergleiche betrachten Integerzahlen dabei als
32 oder 64 Bit breit (je nach Host-System) und vorzeichenbehaftet. F"ur
die logischen Operatoren ist ein Ausdruck TRUE, falls er ungleich 0 ist,
ansonsten FALSE.
Bei Vergleichen von Register-Symbolen sind zwei Details zu beachten.
Zum einen sind zwei Register-Symbole dann gleich, wenn sie auf das
gleiche Register verweisen. Da Register bei einigen Prozessoren
Alias-Namen haben, werden diese Aliase als gleich betrachtet. Zum
Beispiel ist das Register {\tt A7} auf einem 68000 auch als {\tt SP}
ansprechbar, und diese beiden Registersymbole sind gleich. Zum anderen
haben manche Prozessoren mehrere S"atze von Registern, auf einem 68040
zum Beispiel die normalen (Integer-)Register und die FPU-Register.
Zwischen zwei Registern aus unterschiedlichen Gruppen l"a"st sich
keine kleiner/gr"o"ser-Beziehung angeben, die entsprechenden Operatoren
liefern immer ein FALSE zur"uck. Lediglich ein Test auf Gleichheit oder
Ungleichheit ergibt einen Sinn.
Die Bitspiegelung ist wohl etwas erkl"arungsbed"urftig: Der Operator
spiegelt die untersten Bits im ersten Operanden, l"a"st die
dar"uberliegenden Bits aber unver"andert. Die Zahl der zu spiegelnden
Bits ist der rechte Operand und darf zwischen 1 und 32 liegen.
Eine keine Fu"sangel beim bin"aren Komplement: Da die Berechnung
grunds"atzlich auf 32- oder 64-Bit-Ebene erfolgt, ergibt seine Anwendung
auf z.B. 8-Bit-Masken "ublicherweise Werte, die durch voranstehende
Einsen nicht mehr im entferntesten in 8-Bit-Zahlen hineinpassen. Eine
bin"are UND-Verkn"upfung mit einer passenden Maske ist daher unvermeidlich!
Zus"atzlich zu den Operatoren definiert der Assembler noch eine Reihe
in erster Linie transzendenter Funktionen mit Gleitkomma-Argument, die
Tabellen \ref{TabFuncs1} und \ref{TabFuncs2} auflisten.
\begin{table*}[htbp]
\begin{center}\begin{tabular}{|l|l|l|l|}
Name & Funktion & Argument & Ergebnis \\
SQRT & Quadratwurzel & $arg \geq 0$ & Gleitkomma \\
& & & \\
SIN & Sinus & $arg \in \rz$ & Gleitkomma \\
COS & Kosinus & $arg \in \rz$ & Gleitkomma \\
TAN & Tangens & $arg \neq (2*n+1)*\frac{\pi}{2}$ & Gleitkomma \\
COT & Kotangens & $arg \neq n*\pi$ & Gleitkomma \\
& & & \\
ASIN & inverser Sinus & $\mid arg \mid \leq 1$ & Gleitkomma \\
ACOS & inverser Kosinus & $\mid arg \mid \leq 1$ & Gleitkomma \\
ATAN & inverser Tangens & $arg \in \rz$ & Gleitkomma \\
ACOT & inverser Kotangens & $arg \in \rz$ & Gleitkomma \\
& & & \\
EXP & Exponentialfunktion & $arg \in \rz$ & Gleitkomma \\
ALOG & 10 hoch Argument & $arg \in \rz$ & Gleitkomma \\
ALD & 2 hoch Argument & $arg \in \rz$ & Gleitkomma \\
SINH & hyp. Sinus & $arg \in \rz$ & Gleitkomma \\
COSH & hyp. Kosinus & $arg \in \rz$ & Gleitkomma \\
TANH & hyp. Tangens & $arg \in \rz$ & Gleitkomma \\
COTH & hyp. Kotangens & $arg \neq 0$ & Gleitkomma \\
& & & \\
LN & nat. Logarithmus & $arg > 0$ & Gleitkomma \\
LOG & dek. Logarithmus & $arg > 0$ & Gleitkomma \\
LD & 2er Logarithmus & $arg > 0$ & Gleitkomma \\
ASINH & inv. hyp. Sinus & $arg \in \rz$ & Gleitkomma \\
ACOSH & inv. hyp. Kosinus & $arg \geq 1$ & Gleitkomma \\
ATANH & inv. hyp. Tangens & $\mid arg \mid < 1$ & Gleitkomma \\
ACOTH & inv. hyp. Kotangens & $\mid arg \mid > 1$ & Gleitkomma \\
& & & \\
INT & ganzzahliger Anteil & $arg \in \rz$ & Integer \\
& & & \\
BITCNT & bin"are Quersumme & Integer & Integer \\
FIRSTBIT & niedrigstes 1-Bit & Integer & Integer \\
LASTBIT & h"ochstes 1-Bit & Integer & Integer \\
BITPOS & einziges 1-Bit & Integer & Integer \\
\end{tabular}\end{center}
\caption{vordefinierte Funktionen in \asname{} - Teil 1 (Integer- und
Gleitkomma-Funktionen)\label{TabFuncs1}}
\end{table*}
\begin{table*}[htb]
\begin{center}\begin{tabular}{|l|l|l|l|}
Name & Funktion & Argument & Ergebnis \\
SGN & Vorzeichen (0/1/-1) & Integer oder & Integer \\
& & Gleitkomma & \\
ABS & Betrag & Integer oder & Integer oder \\
& & Gleitkomma & Gleitkomma \\
TOUPPER & pass. Gro"sbuchstabe & Integer & Integer \\
TOLOWER & pass. Kleinbuchstabe & Integer & Integer \\
UPSTRING & wandelt alle Zeichen & String & String \\
& in Gro"sbuchstaben & & \\
LOWSTRING & wandelt alle Zeichen & String & String \\
& in Kleinbuchstaben & & \\
STRLEN & liefert L"ange eines & String & Integer \\
& Strings & & \\
SUBSTR & extrahiert Teil eines & String, & String \\
& Strings & Integer, & \\
& & Integer & \\
CHARFROMSTR & extrahiert ein & String, & Integer \\
& Zeichen aus einem & Integer & \\
& String & & \\
STRSTR & sucht Teilstring in & String, & Integer \\
& einem String & String & \\
VAL & evaluiert Stringin- & String & abh. von \\
& halt als Ausdruck & & Argument \\
EXPRTYPE & liefert Typ des & Integer, & 0 \\
& Arguments & Gleitkomma, & 1 \\
& & String & 2 \\
\end{tabular}\end{center}
\caption{vordefinierte Funktionen in \asname{} - Teil 2
(Integer- und String-Funk\-tio\-nen)\label{TabFuncs2}}
\end{table*}
Die Funktionen \tty{FIRSTBIT}, \tty{LASTBIT} und \tty{BITPOS} liefern
als Ergebnis -1, falls "uberhaupt kein bzw. nicht genau ein Bit gesetzt
ist. Zus"atzlich gibt \tty{BITPOS} in einem solchen Fall eine
Fehlermeldung aus.
Die String-Funktion \tty{SUBSTR} erwartet als ersten Parameter den
Quellstring, als zweiten die Startposition und als dritten die Anzahl zu
extrahierender Zeichen (eine 0 bedeutet, alle Zeichen bis zum Ende zu
extrahieren). Analog erwartet \tty{CHARFROMSTR} den Quellstring als
erstes Argument und die Zeichenposition als zweites Argument. Falls die
angegebene Position gr"o"ser oder gleich der L"ange des Quellstrings ist,
liefert \tty{SUBSTR} einen Leerstring, w"ahrend \tty{CHARFROMSTR} eine -1
ergibt. Eine Position kleiner Null wird von \tty{SUBSTR} als Null
behandelt, w"ahrend \tty{CHARFROMSTR} in diesem Fall ebenfalls eine -1
liefert.
Hier ein Beispiel, wie man die beiden Funktionen einsetzt, um einen
String im Speicher abzulegen, wobei das String-Ende durch ein gesetztes
MSB gekennzeichnet ist:
\begin{verbatim}
dbstr macro arg
if strlen(arg) > 1
db substr(arg, 0, strlen(arg) - 1)
endif
if strlen(arg) > 0
db charfromstr(arg, strlen(arg) - 1) | 80h
endif
endm
\end{verbatim}
\tty{STRSTR} liefert das erste Auftreten des zweiten Strings
im ersten bzw. -1, falls das Suchmuster nicht gefunden wurde.
Analog zu \tty{SUBSTR} und \tty{CHARFROMSTR} hat das erste
Zeichen den Positionswert 0.
Wenn eine Funktion auch Gleitkommaargumente erwartet, so soll
dies nicht bedeuten, da"s man nicht z.B.
\begin{verbatim}
wur2 equ sqrt(2)
\end{verbatim}
schreiben d"urfte --- in solchen F"allen findet automatisch eine
Typkonvertierung statt. Umgekehrt mu"s allerdings die \tty{INT}-Funktion
angewandt werden, um eine Gleitkommazahl ganz zu bekommen. Bei der
Benutzung dieser Funktion ist zu beachten, da"s sie als Ergebnis
immer einen vorzeichenbehafteten Integer liefert, sie hat also
einen Wertebereich von ca. +/-2.0E9.
Schaltet man \asname{} in den case-sensitiven Modus, so k"onnen im
Gegensatz zu vordefinierten Symbolen die vordefinierten Funktionen
weiterhin in beliebiger Schreibweise angesprochen werden. Bei
selbst definierten Funktionen (siehe Abschnitt \ref{SectFUNCTION}
wird allerdings unterschieden. Dies hat zur Folge, da"s z.B. bei
der Definition einer Funktion \tty{Sin} man mit \tty{Sin} diese
Funktion auch erreicht, mit allen anderen Schreibweisen jedoch die
eingebaute Funktion.
F"ur die korrekte Umwandlung \marginpar{{\em DOS/}} von Klein-zu
Gro"sbuchstaben ist eine DOS-Version $\geq$ 3.30
erforderlich.
\marginpar{{\em DPMI}}
%%---------------------------------------------------------------------------
\section{Vorw"artsreferenzen und andere Desaster}
Dieser Abschnitt ist das Produkt eines gewissen Grolls auf die (durchaus
legale) Art und Weise, wie einige Leute programmieren, die in Zusammenhang
mit \asname{} bisweilen das eine oder andere Problem verursachen kann. Die Rede
ist hier von sogenannten ,,Vorw"artsreferenzen''. Was unterscheidet eine
Vorw"artsreferenz von einer normalen Referenz? Dazu sehe man sich folgendes
Programmbeispiel an (man sehe mir bitte meine -- auch im Rest dieser Anleitung
anzutreffende -- 68000-Lastigkeit nach):
\begin{verbatim}
move.l #10,d0
loop: move.l (a1),d1
beq skip
neg.l d1
skip: move.l d1,(a1+)
dbra d0,loop
\end{verbatim}
Denkt man sich den Scheifenrumpf mit dem Sprung weg, so bleibt ein
"au"serst angenehm zu assemblierendes Programm "ubrig: die einzige
Referenz ist der R"ucksprung zum Anfang des Rumpfes, und da ein
Assembler ein Programm von vorne nach hinten durcharbeitet, hat er
den Symbolwert bereits ermittelt, bevor er ihn zum erstem Mal ben"otigt.
Sofern man ein Programm hat, das nur solche R"uckw"artsreferenzen besitzt,
ist man in der angenehmen Lage, nur einmal durch den Quellcode gehen zu
m"ussen, um den korrekten und optimalen Maschinencode zu finden. Einige
Hochsprachen wie Pascal mit ihrer strikten Regel, da"s alles vor der ersten
Benutzung definiert sein mu"s, nutzen genau diese Eigenschaft aus, um den
"Ubersetzungsvorgang zu beschleunigen.
Leider ist die Sache im Falle von Assembler nicht so einfach, denn man
will ja bisweilen auch vorw"arts im Code springen oder mu"s aus bestimmten
Gr"unden Variablen Definitionen hinter den Code verlegen. Dies ist
im Beispiel der Fall f"ur den bedingten Sprung, mit dem ein anderer
Befehl "ubersprungen wird. Wenn der Assembler im ersten Durchlauf auf
den Sprungbefehl trifft, so sieht er sich mit der Situation konfrontiert,
entweder die Teilfelder der Instruktion, die die Sprungadresse beinhalten,
leer zulassen, oder seitens des Formelparsers (der das Adre"sargument ja
auswerten mu"s) anstelle des korrekten, aber unbekannten Wertes einen Wert
anzubieten, der ,,niemandem wehtut''. Bei einem einfachen Assembler, der
nur eine Zielarchitektur kennt und bei dem sich die betroffenen Befehle
an einer Hand abz"ahlen lassen, wird man sicher die erste Variante w"ahlen,
bei \asname{} mit seinen vielen Dutzend Zielen w"are die Zahl der Sonderabfragen
aber extrem hoch geworden, so da"s nur der zweite Weg in Frage kam: Falls
im ersten Pass ein unbekanntes Symbol auftaucht, so liefert der Formelparser
den momentanen Stand des Programmz"ahlers als Ergebnis zur"uck! Nur dieser
Wert ist geeignet, relativen Spr"ungen mit Sprungdistanzen unbekannter
L"ange eine Adresse anzubieten, die nicht zu Fehlern f"uhrt. Dies beantwortet
auch die bisweilen gestellte Frage, warum in einem Listing des ersten
Passes (dies bleibt z.B. stehen, wenn \asname{} aufgrund anderer Fehler den
zweiten Pass erst gar nicht beginnt), z.T. falsche Adressen im erzeugten
Bin"arcode gezeigt werden - dies sind noch nicht aufgel"oste
Vorw"artsreferenzen.
Das obige Beispiel offenbart allerdings noch eine weitere Schwierigkeit
von Vorw"artsreferenzen: Je nach Abstand von Quelle und Ziel im Code kann
der Sprungbefehl entweder lang oder kurz sein. Diese Entscheidung "uber
die Code-L"ange - und damit auch die Adressen folgender Labels - kann
jedoch mangels genauer Kenntnis der Zieladresse im ersten Pass nicht
erfolgen. Sofern der Programmierer nicht explizit kenntlich gemacht hat,
ob der Sprung lang oder kurz sein soll, behelfen sich reine 2-Pass-Assembler
wie "altere MASM-Versionen von Microsoft damit, im ersten Pass (nach diesem
m"ussen alle Adressen festliegen) Platz f"ur die l"angste Version zu
reservieren und im zweiten Pass den "ubersch"ussigen Platz mit \tty{NOP}s
aufzuf"ullen. \asname{}-Versionen bis 1.37 taten dieses ebenfalls, danach bin
ich auf das Multipass-Verfahren "ubergegangen, das die strenge Einteilung
in zwei Passes aufhebt und beliebig viele Durchg"ange erlaubt. Dazu wird
im ersten Pass der optimale Code mit den angenommenen Symbolwerten erzeugt.
Stellt \asname{} fest, da"s im zweiten Pass durch Codel"angenver"anderungen sich
Werte von Symbolen ge"andert haben, so wird einfach noch ein dritter Pass
eingelegt, und da durch die neuen Symbolwerte des zweiten Passes auch
im dritten Pass sich der Code wieder verk"urzen oder verl"angern kann,
ist ein weiterer Pass nicht unm"oglich. Ich habe schon 8086-Programme
erlebt, bei denen erst nach 12 Durchg"angen alles stimmte. Leider
erlaubt dieser Mechanismus nicht die Vorgabe einer Maximalzahl von
Durchl"aufen, ich kann als Regel nur sagen, da"s die Anzahl von Durchl"aufen
sinkt, je mehr man davon Gebrauch macht, Sprung- oder Adre"sl"angen explizit
vorzugeben.
Speziell bei gro"sen Programmen kann es zu einer interessanten Situation
kommen: Die Lage eines vorw"arts gerichteten Sprunges hat sich
im zweiten Pass so weit gegen"uber dem ersten verschoben, da"s der
jetzt noch benutzte Label-Wert aus dem ersten Pass au"serhalb der
erlaubten Sprungdistanz liegt. \asname{} ber"ucksichtigt solche Situationen,
indem er jegliche Fehlermeldungen "uber zu weite Sprungdistanzen unterdr"uckt,
sobald er erkannt hat, da"s er wegen sich "andernder Symbolwerte ohnehin
einen weiteren Durchlauf machen mu"s. Dies funktioniert zwar in 99\%
aller F"alle, es gibt jedoch auch Konstrukte, in denen der erste, derartig
kritische Befehl bereits auftaucht, bevor \asname{} eine Chance hat, zu erkennen,
da"s ein neuer Pass erforderlich ist. Das folgende Beispiel konstruiert
eine solche Situation mit Hilfe einer Vorw"artsreferenz (und war der
Anla"s f"ur die "Uberschrift dieses Abschnitts...):
\begin{verbatim}
cpu 6811
org $8000
beq skip
rept 60
ldd Var
endm
skip: nop
Var equ $10
\end{verbatim}
Aufgrund der Adre"slage nimmt \asname{} im ersten Pass lange Adressen f"ur die
\tty{LDD}-Befehle an, was eine Code-L"ange von 180 Bytes ergibt und im
zweiten Pass (zum Zeitpunkt des \tty{BEQ}-Befehls ist noch der ,,falsche''
Wert von \tty{skip} aktuell, d.h. \asname{} wei"s zu diesem Zeitpunkt noch nicht,
da"s der Code in Wirklichkeit nur 120 Bytes lang ist) gibt es eine
Fehlermeldung wegen einer "uberschrittenen Sprungdistanz. Dieser Fehler
l"a"st sich auf drei Arten vermeiden:
\begin{enumerate}
\item{Weisen Sie \asname{} explizit darauf hin, da"s er f"ur die \tty{LDD}-Befehle
kurze Adressen verwenden darf (\tty{ldd <Var})}
\item{Entfernen Sie diese vermaledeite, verfluchte Vorw"artsreferenz und
setzen Sie die \tty{EQU}-Anweisung nach vorne, wo sie hingeh"ort
(OK, ich beruhige mich ja schon wieder...)}
\item{F"ur ganz Unentwegte: Benutzten Sie die \tty{-Y}-Option, so da"s \asname{} die
Fehlermeldung beim Erkennen der Adre"sverschiebung nachtr"aglich
verwirft. Nicht sch"on, aber...}
\end{enumerate}
Noch ein Hinweis zum \tty{EQU}-Befehl: Da \asname{} nicht wissen kann, in welchem
Zusammenhang ein mit \tty{EQU} definiertes Symbol sp"ater verwendet wird,
wird ein \tty{EQU} mit Vorw"artsreferenzen im ersten Pass "uberhaupt nicht
durchgef"uhrt. Wird das mit \tty{EQU} definierte Symbol also im zweiten
Pass vorw"arts referenziert:
\begin{verbatim}
move.l #sym2,d0
sym2 equ sym1+5
sym1 equ 0
\end{verbatim}
so handelt man sich im zweiten Pass eine Fehlermeldung wegen eines
undefinierten Symbols ein...aber warum machen Leute eigentlich solche
Dinge ???
Zugegeben, das war ein ziemlich l"anglicher Ausflug, aber es mu"ste einfach
einmal sein. Was sollte man als Erkenntnis aus diesem Abschnitt mitnehmen?
\begin{enumerate}
\item{\asname{} versucht immer, den k"urzest m"oglichen Code zu erzeugen. Dazu
ben"otigt er eine endliche Zahl von Durchl"aufen. Wenn man ihn
nicht gerade knebelt, kennt \asname{} keine R"ucksichten...}
\item{Wenn sinnvoll und m"oglich, Sprung- und Adre"sl"angen explizit
vorgeben. Man kann damit u.U. die Anzahl der Durchl"aufe deutlich
reduzieren.}
\item{Vorw"artsreferenzen auf das allern"otigste beschr"anken. Man
erleichtert sich und \asname{} das Leben damit erheblich!}
\end{enumerate}
%%---------------------------------------------------------------------------
\label{SectRegSyms} \ttindex{Registersymbole}
{\em G"ultigkeit: PowerPC, M-Core, XGate, 4004/4040, MCS-48/(2)51, 80C16x,
AVR, XS1, Z8, KCPSM, Mico8, MSP430(X), ST9, M16, M16C, H8/300,
H8/500, SH7x00, H16, i960, XA, 29K, TLCS-9000, KENBAK, SC/MP}
Manchmal ist es erw"unscht, nicht nur einer Speicheradresse oder einer
Konstanten, sondern auch einem Register einen symbolischen Namen zuzuweisen,
um seine Funktion in einem bestimmten Programmabschnitt zu verdeutlichen.
Dies ist bei Prozessoren, die die Register schlicht als einen weiteren
Adre"sraum behandeln, recht problemlos, da als Register damit auch
Zahlenausdr"ucke erlaubt sind und man solche Symbole mit schlichten
\tty{EQU}s definieren kann (z.B. bei MCS-96 oder TMS7000). Bei den
allermeisten Prozessoren jedoch sind Registernamen festgelegte Literale, und
\asname{} behandelt sie beim Parsing aus Geschwindigkeitsgr"unden gesondert, so da"s auch
ein getrennter Typ von Symbolen f"ur solche Registersymbole oder -aliase existiert.
Registersymbole k"onnen wie gew"ohnliche Symbole mit \tty{EQU} oder \tty{SET}
definiert und umdefiniert werden, zudem existiert eine spezielle \tty{REG}-Anweisung,
die explizit nur Symbole bzw. Ausdr"ucke dieses Typs akzeptiert.
Registersymbole unterliegen einer Reihe von Einschr"ankungen: zum einen ist die
Menge der Literale beschr"ankt und durch den jeweiligen Zielprozessor vorgegeben,
zum anderen kann man mit Registersymbolen nicht rechnen. Etwas in dieser Form:
\begin{verbatim}
myreg reg r17 ; Definition Registersymbol
addi myreg+1,3 ; geht nicht!
\end{verbatim}
ist also {\em nicht} zul"assig. Einfache Zuweisungen sind dagegen auch "uber mehrere
Stufen hinweg erlaubt:
\begin{verbatim}
myreg reg r17 ; Definition Registersymbol
myreg2 reg myreg ; myreg2 -> r17
\end{verbatim}
Des weiteren sind Vorw"artsreferenzen bei Registersymbolen noch kritischer als
bei anderen Typen von Symbolen. Ist ein Symbol nicht definiert, so kann \asname{} nur
mutma"sen, was f"ur ein Typ von Symbol es sein wird, und entscheidet sich in
Zweifelsfall f"ur eine einfache Zahl, was bei den meisten Prozessoren einem Zugriff
auf eine absolute Adresse im Speicher gleichkommt. Nun sind bei den meisten
Prozessoren die Nutzungsm"oglichkeiten f"ur Speicheradressen als Operand deutlich
eingeschr"ankter als f"ur Register. Je nach Situation erh"alt man so eine
Fehlermeldung "uber einen nicht erlaubten Adressierungsmodus, und es kommt zu keinem
zweiten Pass...
Registersymbole sind analog zu normalen Symbolen lokal zu Sektionen,
und es ist auch durch Anh"angen eines in eckige Klammern gesetzten Sektionsnamens
m"oglich, auf ein Registersymbol aus einer bestimmten Sektion zuzugreifen.
%%---------------------------------------------------------------------------
\label{ChapShareMain} \ttindex{SHARED}
Diese Funktion ist ein Abfallprodukt aus den reinen 68000er-Vorg"angern
von \asname{}, da sie vielleicht doch der (die?!) eine oder andere gebrauchen
k"onnte, habe ich sie drin gelassen. Grundproblem ist es, an bestimmte
beim Assemblieren entstehende Symbole heranzukommen, weil man evtl. mit
diesen Adre"sinformationen auf den Speicher des Zielsystems zugreifen
m"ochte. Der Assembler erlaubt es, mit Hilfe des \tty{SHARED}-Pseudobefehles
(siehe dort) Symbolwerte extern zur Verf"ugung zu stellen. Zu diesem
Zweck erstellt der Assembler im zweiten Pass eine Textdatei mit den
gew"unschten Symbolen und ihren Werten, die mittels Include in ein
Hochsprachen-oder weiteres Assemblerprogramm eingebunden werden k"onnen.
Das Format der Textdatei (C, Pascal oder Assembler) wird durch die
Kommandozeilenschalter \tty{p}, \tty{c} oder \tty{a} festgelegt.
\bb{ACHTUNG!} Ist keiner dieser Schalter angegeben, so wird auch keine
Datei erzeugt, egal ob sich \tty{SHARED}-Befehle im Quelltext finden oder
nicht!
\asname{} pr"uft beim Anlegen der Share-Datei nicht, ob bereits eine Datei gleichen
Namens existiert, eine solche wird ggfs. einfach "uberschrieben. Eine
Abfrage halte ich nicht f"ur sinnvoll, da \asname{} dann bei jedem Lauf fragen
w"urde, ob er die alte Version der Share-Datei "uberschreiben darf, und das
w"are doch sehr l"astig...
%%---------------------------------------------------------------------------
Mit Varianten g"angiger Mikrocontroller-Familien ist es wie mit
Kaninchen: Sie vermehren sich schneller, als man mit der Versorgung
hinterher kommen kann. Im Zuge der Entwicklung von Prozessorkernen als
Bausteine f"ur ASICs und von Controller-Familien mit vom Kunden w"ahlbarer
Peripherie wird die Zahl von Controller-Varianten, die sich von einem
bekannten Typ nur in einigen Peripherie-Details unterscheiden, immer
gr"o"ser. Die Unterscheidung der einzelnen Typen ist aber trotz meist
identischer Prozessorkerns wichtig, um z.B. in den Include-Dateien den
korrekten Satz von Peripherieregistern einzublenden. Bisher habe ich
mich zwar immer bem"uht, die wichtigsten Vertreter einer Familie in \asname{}
einzubauen (und werde das auch weiter tun), aber manchmal l"auft mir
die Entwicklung einfach auf und davon...es mu"ste also ein Mechanismus
her, mit dem man die Liste der unterscheidbaren Prozessortypen selbst
erweitern kann.
Das Ergebnis davon sind Prozessor-Aliasse: Mit der Kommandozeilenoption \tty{alias}
kann man einen neuen Prozessortyp definieren, der im Befehlssatz einem
anderen, in \asname{} fest eingebauten Typ entspricht. Bei Benutzung dieses
Typs im \tty{CPU}-Befehl wird sich \asname{} also wie beim ,,Original'' verhalten,
mit einem Unterschied: Die Variablen \tty{MOMCPU} bzw. \tty{MOMCPUNAME}
werden auf den Namen des Alias gesetzt, wodurch der neue Name zur
Unterscheidung z.B. in Include-Dateien dienen kann.
Die Definition dieser Aliasse wurde aus zwei Gr"unden mit
Kommandozeilenoptionen anstatt Pseudobefehlen vorgenommen: zum einen
w"are es ohnehin nicht m"oglich gewesen, die Definition der Aliasse
zusammen mit den Registerdefinitionen in eine Include-Datei zu legen, denn
in einem Programm, das so eine Datei benutzen wollte, m"u"ste sie ja sowohl
vor als auch nach dem \tty{CPU}-Befehl in der Hauptdatei eingebunden
werden - eine Vorstellung, die irgendwo zwischen unelegant und unm"oglich
liegt. Zum zweiten erm"oglicht diese Implementierung, die Definition der
neuen Typen in eine Datei zu legen, die "uber die \tty{ASCMD}-Variable beim
Start automatisch ausgef"uhrt wird, ohne das sich das Programm darum
k"ummern m"u"ste.
%%===========================================================================
\cleardoublepage
Nicht f"ur alle Prozessoren sind alle Pseudobefehle definiert. Vor
der Beschreibung eines Befehls ist deshalb jeweils vermerkt, f"ur
welche Prozessortypen dieser Befehl erlaubt ist.
%%---------------------------------------------------------------------------
%%- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
\ttindex{SET}\ttindex{EQU}
\ttindex{.SET}\ttindex{.EQU}
\ttindex{CONSTANT}
{\em G"ultigkeit: alle Prozessoren, {\tt CONSTANT} nur KCPSM(3)}
\tty{SET} und \tty{EQU} erlauben die Definition typenloser Konstanten, d.h. sie
werden keinem Segment zugeordnet und ihre Verwendung erzeugt in keinem
Fall eine Warnung wegen Segment-Vermischung. W"ahrend \tty{EQU} Konstanten
definiert, die nicht wieder (mit \tty{EQU}) ge"andert werden k"onnen, erlaubt
\tty{SET} die Definition von Variablen, die sich w"ahrend des Assemblerlaufes
ver"andern lassen. Dies ist n"utzlich z.B. bei der Allokation von
Resourcen \`a la Interrupt-Vektoren, wie im folgenden Beispiel:
\begin{verbatim}
VecCnt SET 0 ; irgendwo am Anfang
...
DefVec MACRO Name ; einen neuen Vektor belegen
Name EQU VecCnt
VecCnt SET VecCnt+4
ENDM
...
DefVec Vec1 ; ergibt Vec1=0
DefVec Vec2 ; ergibt Vec2=4
\end{verbatim}
Intern werden Konstanten und Variablen identisch gespeichert, der
einzige Unterschied ist, da"s sie als unver"anderbar markiert werden, wenn
sie mit \tty{EQU} definiert werden. Der Versuch, eine Konstante mit
\tty{SET} zu ver"andern, gibt eine Fehlermeldung.
Mit \tty{EQU/SET} lassen sich Konstanten aller Typen definieren, z.B.
\begin{verbatim}
IntZwei EQU 2
FloatZwei EQU 2.0
\end{verbatim}
Einige Prozessoren besitzen leider bereits selber einen \tty{SET}-Befehl.
Bei diesen mu"s \tty{EVAL} anstelle von \tty{SET} verwendet werden, falls
sich der Maschinenbefehl nicht durch die andere Anzahl der Argumente
erkennen l"a"st. Alternativ ist es auch immer m"oglich, durch einen
vorangestellten Punkt (\tty{.SET} anstelle \tty{SET}) explizit den
Pseudobefehl aufzurufen.
Anstelle von \tty{EQU} darf auch \tty{.EQU} oder einfach ein
Gleichheitszeichen geschrieben werden, analog kann man anstelle
von \tty{SET} bzw. \tty{EVAL} einfach \tty{:=} schreiben. Des weiteren
existiert eine 'alternative' Syntax, bei der der Synbolname nicht aus dem
Feld f"ur das Label genommen wird, sondern das erste Argument ist.
Wahlweise darf man also auch schreiben:
\begin{verbatim}
EQU IntZwei,2
EQU FloatZwei,2.0
\end{verbatim}
Das Feld f"ur das Label mu"s in diesem Fall leer bleiben.
Aus Kompatibilit"atsgr"unden zum Originalassembler gibt es f"ur das
KCPSM-Target auch den {\tt CONSTANT}-Befehl, der im Gegensatz zu {\tt EQU}
Namen und Wert immer als Argumente erwartet, also z.B. so:
\begin{verbatim}
CONSTANT const1, 2
\end{verbatim}
{\tt CONSTANT} ist allerdings auf Integer-Konstanten beschr"ankt.
Defaultm"a"sig sind mit \tty{SET} oder \tty{EQU} definierte Symbole
typenlos, optional kann jedoch als zweites bzw. drittes Argument ein
Segmentname (\tty{CODE, DATA, IDATA, XDATA, YDATA, BITDATA, IO oder REG})
oder \tty{MOMSEGMENT} f"ur das aktuell gesetzte Segment angegeben werden,
um das Symbol einem bestimmten Adre"sraum zuordnen. \asname{} ber"ucksichtigt
dabei nicht, ob der benutzte Adre"sraum bei dem aktuell gesetzten
Zielprozessor auch vorhanden ist!
Als kleines verstecktes Extra ist es m"oglich, "uber \tty{SET} oder \tty{EQU}
den Programmz"ahler zu setzen, also das zu machen, wozu man ansonsten \tty{ORG}
verwenden w"urde. Dazu gibt man als Symbolnamen den Sonderwert an, mit dem
sich auch der aktuelle Programmz"ahler abfragen l"a"st, also je nach
gew"ahlter Zielarchitektur ein Stern, ein Dollarzeichen, ein Punkt oder \tty{PC}.
Falls die gew"ahlte Zielarchitektur ein Attribut an den Befehlen zur Angabe
der Operandengr"o"se unterst"utzt (z.B. 680x0), so ist dieses ebenfalls
bei \tty{SET} und \tty{EQU} erlaubt. Das definierte Symbol wird dann mit
dieser Operandengr"o"se in der Symboltabelle abgelegt. Deren Verwendung
bei Benutzung des Symbols ist architekturab"angig.
%%- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
\ttindex{SFR}\ttindex{SFRB}
{\em G"ultigkeit: diverse, SFRB nur MCS-51}
Diese Befehle funktionieren wie \tty{EQU}, nur sind die damit definierten
Symbole dem direkt adressierbaren Datensegment zugeordnet, d.h. sie
dienen bevorzugt zur Definition von (wie der Name ahnen l"a"st) im Daten- bzw.
I/O-Bereich eingeblendeten Hardwareregistern. Der dabei zugelassene
Wertebereich ist identisch mit dem bei \tty{ORG} f"ur das \tty{DATA} bzw.
\tty{IO}-Segment zugelassenen (s. Abschnitt \ref{SectORG}).
\tty{SFR} und \tty{SFRB} unterscheiden sich darin, da"s \tty{SFRB}
das Register als bitadressierbar kennzeichnet, weshalb \asname{} zus"atzlich 8
Symbole erzeugt, die dem Bitsegment zugeordnet werden und die Namen
\tty{xx.0} bis \tty{xx.7} tragen, z.B.
\begin{verbatim}
PSW SFR 0d0h ; ergibt PSW = D0H (Datensegment)
PSW SFRB 0d0h ; zusaetzlich PSW.0 = D0H (Bit)
; bis PSW.7 = D7H (Bit)
\end{verbatim}
Da beim 80C251 grunds"atzlich alle SFRs ohne zus"atzliche Bit-Symbole
bitadressierbar sind, ist der \tty{SFRB}-Befehl f"ur ihn auch nicht mehr
definiert; die Bits \tty{PSW.0} bis \tty{PSW.7} sind automatisch vorhanden.
\asname{} "uberpr"uft bei der Definition eines bitadressierbaren Registers mit
\tty{SFRB}, ob die Speicherstelle "uberhaupt bitadressierbar ist (Bereich
20h..3fh bzw. 80h, 88h, 90h, 98h...0f8h). Ist sie es nicht, so wird eine
Warnung ausgegeben; die dann erzeugten Bit-Symbole sind undefiniert.
%%- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
\ttindex{XSFR}\ttindex{YSFR}
{\em G"ultigkeit: DSP56xxx}
Auch der DSP56000 hat einige Peripherieregister memory-mapped im
Speicher liegen, die Sache wird jedoch dadurch komplizierter, da"s
es zwei Datenbereiche gibt, den X-und Y-Bereich. Diese Architektur
erlaubt einerseits zwar einen h"oheren Parallelit"atsgrad, zwingt
jedoch andererseits dazu, den normalen \tty{SFR}-Befehl in die beiden
oben genannten Varianten aufzuspalten. Sie verhalten sich identisch zu
\tty{SFR}, nur da"s \tty{XSFR} ein Symbol im X-Adre"sraum definiert
und \tty{YSFR} entsprechend eines im Y-Adre"sraum. Der erlaubte
Wertebereich ist 0..\$ffff.
%%- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
\ttindex{LABEL}
{\em G"ultigkeit: alle Prozessoren}
Die Funktion des \tty{LABEL}-Befehls ist identisch zu \tty{EQU}, nur
wird das Symbol nicht typenlos, sondern erh"alt das Attribut ,,Code''.
\tty{LABEL} wird genau f"ur einen Zweck ben"otigt: Labels in Makros
sind normalerweise lokal, also nicht au"serhalb des Makros zugreifbar.
Mit einem \tty{EQU}-Befehl kann man sich zwar aus der Aff"are ziehen,
die Formulierung
\begin{verbatim}
<Name> label $
\end{verbatim}
erzeugt aber ein Symbol mit korrekten Attributen.
%%- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
\ttindex{BIT}
{\em G"ultigkeit: MCS-(2)51, XA, 80C166, 75K0, STM8, ST9, AVR, S12Z,
SX20/28, H16, H8/300, H8/500, KENBAK, Padauk}
\tty{BIT} dient dazu, ein einzelnes Bit einer Speicherstelle mit einem
symbolischen Namen gleichzusetzen. Da die Art und Weise, wie
verschiedene Prozessoren Bitverarbeitung und -adressierung betreiben,
stark variiert, verh"alt sich auch dieser Befehl je nach Zielplattform
anders:
F"ur die MCS/51-Familie, die einen eigenen Adre"sraum f"ur Bitoperanden
besitzt, ist die Funktion von \tty{BIT} ganz analog zu \tty{SFR}, d.h.
es wird einfach ein Integer-Symbol mit dem angegebenen Wert und dem
Segment BDATA erzeugt. F"ur alle anderen Prozessoren wird die
Bitadressierung dagegen zweidimensional mit Adresse und Bitstelle
vorgenommen. In diesem Fall verpackt \asname{} beide Teile in einer vom
jeweiligen Prozessor abh"angigen Weise in ein Integer-Symbol und dr"oselt
dieses bei der Benutzung wieder in die beiden Teile auseinander.
Letzterer Fall trifft auch schon f"ur den 80C251 zu: W"ahrend zum Beispiel
der Befehl
\begin{verbatim}
Mein_Carry bit PSW.7
\end{verbatim}
auf einem 8051 noch dem Symbol \tty{Mein\_Carry} den Wert 0d7h zuweisen
w"urde, w"urde auf einem 80C251 dagegen ein Wert von 070000d0h generiert
werden, d.h. die Adresse steht in Bit 0..7 sowie die Bitstelle in Bit
24..26. Dieses Verfahren entspricht dem, das auch beim DBIT-
Befehl des TMS370 angewendet wird und funktioniert sinngem"a"s so auch
beim 80C166, nur da"s dort Bitstellen von 0 bis 15 reichen d"urfen:
\begin{verbatim}
MSB BIT r5.15
\end{verbatim}
Beim Philips XA findet sich in Bit 0..9 die Bitadresse, wie sie auch
in die Maschinenbefehle eingesetzt wird, f"ur Bits aus den RAM-Speicher
wird in Bit 16..23 die 64K-Bank eingesetzt.
Noch etwas weiter geht der \tty{BIT}-Befehl bei der 75K0-Familie: Da
dort Bitadressierungen nicht nur absolute Basisadressen verwenden
d"urfen, sind sogar Ausdr"ucke wie
\begin{verbatim}
bit1 BIT @h+5.2
\end{verbatim}
erlaubt.
Beim ST9 ist es hingegen m"oglich, Bits auch invertiert anzusprechen,
was beim \tty{BIT}-Befehl auch ber"ucksichtigt wird:
\begin{verbatim}
invbit BIT r6.!3
\end{verbatim}
N"aheres zum \tty{BIT}-Befehl beim ST9 findet sich bei den
prozessorspezifischen Hinweisen.
Im Falle des H16 sind die Argumente f"ur Speicheradresse und Bitposition
vertauscht. Dies wurde getan, um die Syntax zur Definition von Bit identisch
zu den Maschinenbefehlen zu machen, die einzelne Bits manipulieren.
%%- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
\ttindex{DBIT}
{\em G"ultigkeit: TMS 370xxx}
Die TMS370-Reihe hat zwar kein explizites Bit-Segment, jedoch k"onnen
einzelne Bits als Symbol durch diesen Befehl simuliert werden. \tty{DBIT}
ben"otigt zwei Operanden, n"amlich einmal die Adresse der Speicherstelle,
in der das Bit liegt, sowie die genaue Position des Bits im Byte.
So definiert man z.B. mit
\begin{verbatim}
INT3 EQU P019
INT3_ENABLE DBIT 0,INT3
\end{verbatim}
das Bit, welches Interrupts von Anschlu"s INT3 freigibt. So definierte
Bits k"onnen dann von den Befehlen \tty{SBIT0, SBIT1, CMPBIT, JBIT0}
und \tty{JBIT} genutzt werden.
%%- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
\ttindex{DEFBIT}
\ttindex{DEFBITB}
Der Prozessorkern der S12Z-Familie verf"ugt "uber Befehle, mit denen
sich einzelne Bits in Register oder Speicherzellen manipulieren
lassen. Um Bits im I/O-Bereich des Prozessors (erste 4 KByte des
Adre"sraumes) bequem ansprechen zu k"onnen, kann man einem einzelnen
Bit, definiert durch Speicheradresse und Bitposition, einen
symbolischen Namen geben:
\begin{verbatim}
<Name> defbit[.Size] <Adresse>,<Position>
\end{verbatim}
Die \tty{Adresse} mu"s in den ersten 4 KByte liegen, als Operandengr"o"se
sind 8, 16 oder 32 Bit (\tty{Size}=b/w/l) zugelassen.
Dementsprechend darf \tty{Position} maximal 7, 15 oder 31 sein.
Falls keine Opoerandengr"o"se angegeben wird, werden 8 Bit (.b)
angenommen. Ein solcherma"sen definiertes Bit kann als Argument f"ur
die Befehle {\tt BCLR, BSET, BTGL, BRSET} und {\tt BRCLR} verwendet
werden:
\begin{verbatim}
mybit defbit.b $200,4
bclr.b $200,#4
bclr mybit
\end{verbatim}
Die beiden Aufrufe von {\tt bclr} in diesem Beispiel erzeugen
identischen Code. Da ein solcherma"sen definiertes Bit seine
Operandengr"o"se ''kennt'', kann diese bei der Benutzung fortgelassen
werden.
Bit-Definitionen innerhalb einer Struktur, die sich auf ein Element
einer Struktur beziehen, sind ebenfalls m"oglich:
\begin{verbatim}
mystruct struct dots
reg ds.w 1
flag defbit reg,4
ends
org $100
data mystruct
bset data.flag ; entspricht bset.w $100,#4
\end{verbatim}
Im Gegensatz zum ''klassischen'' Z8 verf"ugt der Super8-Kern "uber
Befehle, mit denen sich Bits in allgemeinen oder Arbeitsregistern
bearbeiten lassen. Dabei ist jedoch zu beachten, da"s einige davon
nur auf Bits arbeiten, die Teil eines der 16 Arbeitsregister sind.
Mit der \tty{DEFBIT}-Anweisung lassen sich Bits beider Sorten
definieren:
\begin{verbatim}
workbit defbit r3,#4
slow defbit emt,#6
\end{verbatim}
Derart definierte Bits lassen sich dann bei den Befehlen wie ein
P"archen aus Register und Bitposition einsetzen:
\begin{verbatim}
ldb r3,emt,#6
ldb r3,slo ; gleich bedeutend
bitc r3,#4
bitc workbit ; gleich bedeutend
\end{verbatim}
Der Z8000 verf"ugt zwar "uber Befehle zum Setzen und R"ucksetzen
von Bits, diese k"onnen jedoch nur auf Adressen im Speicher- und nicht
im I/O-Adre"sraum wirken. Aus diesem Grund lassen sich mit {\tt DEFBIT}
bzw. {\tt DEFBITB} auch nur Bit-Objekte im Speicher-Adre"sraum definieren.
Die Unterscheidung der Operandengr"o"se ist wichtig, weil der Z8000 ein
Big-Endian-Prozessor ist: Bit {\em n} eines 16-Bit-Worts bei Adresse {\em m}
entspr"ache Bit {\em n} eines 8-Bit-Byte bei Adresse {\em m+1}.
Die ersten 16 Byte der Working Area und Sonderregister mit einer Adresse
kleiner 16 sind bitadressierbar.
%%- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
\ttindex{DEFBITFIELD}
{\em G"ultigkeit: S12Z}
Der Prozessorkern der S12Z-Familie kann nicht nur mit einzelnen Bits
umgehen, sondern auch zusammenh"angende Felder von Bits in einem
8/16/24/32-Bit-Wert extrahieren oder schreiben. Analog zu
\tty{DEFBIT} l"a"st sich auch ein Bitfeld symbolisch definieren:
\begin{verbatim}
<Name> defbitfield[.Size] <Adresse>,<Breite>:<Position>
\end{verbatim}
Im Gegensatz zu einzelnen Bits sind hier auch 24 Bits (.p) als
Operandengr"o"se zugelassen, der Wertebereich von \tty{Position} und
\tty{Breite} ist dementsprechend von 0 bis 23 bzw. 1 bis 24. Auch
hier ist es wieder zul"assig, Bitfelder als Teil von Strukturen zu
definieren:
\begin{verbatim}
mystruct struct dots
reg ds.w 1
clksel defbitfield reg,4:8
ends
org $100
data mystruct
bfext d2,data.clksel ; fetch $100.w bits 4..11
; to D2 bits 0..7
bfins data.clksel,d2 ; insert D2 bits 0..7 into
; $100.w bits 4..11
\end{verbatim}
Die interne Darstellung von Bits, die mit \tty{DEFBIT} definiert
wurden, ist gleich der von Bitfeldern der Breite eins. Ein
symbolisch definiertes einzelnes Bit kann also auch als Argument
f"ur \tty{BFINS} und \tty{BFEXT} verwendet werden.
%%- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
\ttindex{PORT}
{\em G"ultigkeit: PALM, 8008/8080/8085/8086, XA, Z80, Z8000, 320C2x/5x, TLCS-47, AVR,
F8, IMP-16}
\tty{PORT} arbeitet analog zu \tty{SFR}, nur wird das Symbol dem I/O-Adre"sbereich
zugeordnet. Erlaubte Werte sind 0..7 beim 3201x und 8008, 0..15 beim 320C2x und PALM,
0..65535 beim 8086, Z8000 und 320C5x, 0..63 beim AVR und 0..255 beim Rest.
Beispiel: eine PIO 8255 liege auf Adresse 20H:
\begin{verbatim}
PIO_Port_A PORT 20h
PIO_Port_B PORT PIO_Port_A+1
PIO_Port_C PORT PIO_Port_A+2
PIO_Ctrl PORT PIO_Port_A+3
\end{verbatim}
%%- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
\ttindex{REG}\ttindex{NAMEREG}
{\em G"ultigkeit: 680x0, AVR, M*Core, ST9, 80C16x, Z8000, KCPSM, \\
PDP-11, WD16 \\
(\tty{NAMEREG} nur f"ur KCPSM(3)), LatticeMico8, MSP430(X)}
Obwohl immer mit gleicher Syntax, hat diese Anweisung von Prozessor
zu Prozessor eine leicht abweichende Bedeutung: Falls der Zielprozessor
f"ur Register einen eigenen Adre"sraum verwendet, so hat \tty{REG}
die Wirkung eines simplen \tty{EQU}s f"ur eben diesen Adre"sraum (z.B. beim
ST9). F"ur alle anderen Prozessoren definiert \tty{REG} Registersymbole,
deren Funktion in Abschnitt \ref{SectRegSyms} beschrieben sind.
{\tt NAMEREG} existiert aus Kompatibilit"atsgr"unden zum Originalassembler
f"ur den KCPSM. Es hat die gleiche Funktion, lediglich werden sowohl
Register- als auch symbolischer Name als Argumente angegeben, z.B. so:
\begin{verbatim}
NAMEREG s08, treg
\end{verbatim}
Auf der PDP-11 darf \tty{REG} zus"atzlich ohne Namen im Label-Feld benutzt
werden. Es wird dann als einziges Argument entweder \tty{ON} oder \tty{OFF}
erwartet, und damit werden die eingebauten Register-Aliase (\tty{Rn} = \tty{\%n},
\tty{SP} = \tty{R6}, \tty{PC} = \tty{R7}) ein- und ausgeschaltet. Sie
sind im Default verf"ugbar, und sollten nur abgeschaltet werden, wenn
sie mit eigenen Symbolnamen in einem Programm kollidieren. Die augenblickliche
Einstellung l"a"st sich aus dem Symbol \tty{DEFAULT\_REGSYMS} lesen.
%%- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
\ttindex{LIV}\ttindex{RIV}
{\em G"ultigkeit: 8X30x}
\tty{LIV} und \tty{RIV} dienen dazu, sogenannte IV-Bus-Objekte zu definieren.
Bei diesen handelt es sich um Bitgruppen in peripheren Speicherzellen
mit einer L"ange von 1..8 Bit, die fortan symbolisch angesprochen
werden k"onnen, so da"s man bei den entsprechenden Befehlen nicht mehr
Adresse, L"ange und Position separat angeben mu"s. Da die
8X30x-Prozessoren zwei periphere Adre"sr"aume besitzen (einen ,,linken''
und einen ,,rechten'', sind auch zwei separate Befehle definiert. Die
Parameter dieser Befehle sind allerdings identisch: es m"ussen drei
Parameter sein, die Adresse, Startposition und L"ange angeben.
Weitere Hinweise zur Benutzung von Busobjekten finden sich in
Abschnitt \ref{8X30xSpec}.
%%- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
\ttindex{CHARSET}\ttindex{CODEPAGE\_VAL}
{\em G"ultigkeit: alle Prozessoren}
Einplatinen-Systeme, zumal wenn sie LCDs ansteuern, benutzen h"aufig
einen anderen Zeichensatz als ASCII, und da"s die Umlautkodierung mit
der im PC "ubereinstimmt, d"urfte wohl reiner Zufall sein. Und dann
gibt es auch (historische) Systeme, die z.B. eine EBCDIC-Variante
verwenden...um nun aber keine fehlertr"achtigen Umkodierungen im Code
per Hand vornehmen zu m"ussen, enth"alt der Assembler eine Umsetzungstabelle
f"ur Zeichen, die jedem (ASCII-)zeichen im Quellcode ein Zielzeichen zuordnet.
Zur Modifikation dieser Tabelle (die initial 1:1 "ubersetzt), dient der
Befehl \tty{CHARSET}. \tty{CHARSET} kann mit verschiedenen Parameterzahlen
und -typen aufgerufen werden:
Ein
\begin{quote}{\tt
CHARSET
}\end{quote}
ohne jegliche Argumente setzt die "Ubersetzungstabelle auf den 1:1-Default
wieder zur"uck.
Wird nur ein Argument gegeben, mu"s es sich dabei um einen String-Ausdruck
handeln, der von \asname{} als Dateiname interpretiert wird:
\begin{verbatim}
CHARSET "mapping.bin"
\end{verbatim}
Aus dieser Datei liest \asname{} dann die ersten 256 Bytes aus und kopiert sie in die
"Ubersetzungstabelle. Hiermit lassen sich also komplexere, extern
erzeugte Tabellen mit einer Anweisung laden.
In allen anderen Varianten wird ein einzelner Eintrag oder ein ganzer
Bereich von Eintr"agen in der Tabelle modifiziert. Mit zwei (Integer-)Argumenten
kann ein einzelner Eintrag neu gesetzt werden. Ein
\begin{quote}{\tt
CHARSET '"a',128
}\end{quote}
bedeutet zum Beispiel, da"s das Zielsystem das "a mit der Zahl 128 kodiert.
Es ist auch m"oglich zu definieren, da"s ein bestimmtes Zeichen "uberhaupt
nicht dargestellt werden kann. Daf"ur l"a"st man das zweite Argument leer:
\begin{quote}{\tt
CHARSET '[',
}\end{quote}
Soll fortan das ,,gel"oschte'' Zeichen irgendwo in einem String im Speicher
abgelegt werden, f"uhrt dies zu einer Fehlermeldung.
Anstelle eines einzelnen Zeichens kann auch ein ganzer Bereich umgemappt
werden. Das erste und zweite Argument geben den Bereich der Zeichen an, das
dritte das Mapping des ersten Zeichens. Falls z.B. das Zielsystem keine
Kleinbuchstaben unterst"utzt, k"onnen mit
\begin{verbatim}
CHARSET 'a','z','A'
\end{verbatim}
alle Kleinbuchstaben auf die passenden Gro"sbuchstaben automatisch
umgesetzt werden. Und auch ein Bereich von Zeichen kann als
,,nicht verf"ugbar'' markiert werden:
\begin{verbatim}
CHARSET 'a','z',
\end{verbatim}
verbietet die Verwendung von Kleinbuchstabem.
In der letzten Variante (wieder mit nur zwei Argumenten) folgt nach dem
Startindex ein String, der das Mapping ab dem Start-Zeichen auflistet.
Das Umlegen von Klein- auf Gro"sbuchstaben k"onnte man also auch so
formulieren:
\begin{verbatim}
CHARSET 'a',"ABCDEFGHIJKLMNOPQRSTUVWXYZ"
\end{verbatim}
\bb{ACHTUNG!} Das durch \tty{CHARSET} definierte Mapping greift nicht nur
beim Ablegen von Strings im Speicher, es greift auch bei Multi-Character-Konstanten,
also als ,,ASCII'' formulierten Integer-Konstanten. Dies bedeutet, da"s
eine bereits modifizierte Umsetzungstabelle in den obigen Beispielen zu
anderen Ergebnissen f"uhren kann!
Mit der eingebauten Funktion \tty{CODEPAGE\_VAL} kann die "Ubersetzung
eines einzelnen Zeichens abgefragt werden. F"ur nicht gemappte Zeichen
liefert die Funktion eine -1 zur"uck.
%%- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
\ttindex{CODEPAGE}
{\em G"ultigkeit: alle Prozessoren}
Mit der \tty{CHARSET}-Anweisung hat man zwar beliebige Freiheiten in der
Zeichenzuordnung zwischen Entwicklungs- und Zielplattform, wenn auf der
Zielplattform jedoch verschiedene Zeichens"atze existieren, kann das
Umschalten zwischen diesen jedoch zu einer umst"andlichen Orgie von
\tty{CHARSET}-Kommandos werden. Mit der \tty{CODEPAGE}-Anweisung kann
man jedoch mehrere Zeichentabellen vorhalten und zwischen diesen mit einem
Befehl umschalten. Als Parameter erwartet \tty{CODEPAGE} ein oder zwei
Namen: zum einen den Namen der fortan zu benutzenden Tabelle, zum anderen
optional den Namen der Tabelle, die die initiale Belegung der Tabelle
vorgibt (dieser Parameter hat somit auch nur eine Bedeutung beim ersten
Umschalten auf eine Tabelle, bei der \asname{} sie automatisch anlegt). Fehlt
der zweite Parameter, so ist die initiale Belegung der neuen Tabelle
gleich der vorher aktiven Tabelle. Alle folgenden
\tty{CHARSET}-Anweisungen ver"andern {\em nur} die momentan aktive Tabelle.
Zu Beginn eines Durchlaufes wird von \asname{} automatisch eine einzelne
Zeichentabelle mit dem Namen \tty{STANDARD} erzeugt und 1:1 vorbelegt.
Verwendet man keine \tty{CODEPAGE}-Anweisungen, so beziehen sich alle mit
\tty{CHARSET} gemachten Einstellungen auf diese Tabelle.
%%- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
\ttindex{ENUM}
\ttindex{NEXTENUM}
\ttindex{ENUMCONF}
{\em G"ultigkeit: alle Prozessoren}
\tty{ENUM} dient analog zu dem entsprechenden Befehl in C dazu,
Aufz"ahlungstypen zu definieren, d.h. eine Reihe von Integer-Konstanten,
denen fortlaufende Werte (von 0 an beginnend) zugewiesen
werden. Als Parameter werden dabei die Namen der zu definierenden
Symbole angegeben, wie in dem folgenden Beispiel:
\begin{quote}{\tt
ENUM SymA,SymB,SymC}
\end{quote}
Dieser Befehl weist den Symbolen \tty{SymA}, \tty{SymB} und \tty{SymC}
die Werte 0, 1 und 2 zu.
M"ochte man eine Aufz"ahlung "uber mehrere Zeilen verteilen, so
verwendet man ab der zweiten Zeile den Befehle \tty{NEXTENUM}
anstelle von \tty{ENUM}. Der interne Z"ahler, der den Symbolen
der Aufz"ahlung fortlaufende Werte zuweist, wird dann nicht
wieder auf Null zur"uck gesetzt, wie in dem folgenden Fall:
\begin{verbatim}
ENUM Januar=1,Februar,Maerz,April,Mai,Juni
NEXTENUM Juli,August,September,Oktober
NEXTENUM November,Dezember
\end{verbatim}
An diesem Beispiel sieht man auch, da"s man einzelnen Symbolen
explizit Werte anstelle des aktuellen Z"ahlerstandes zuweisen
kann. Der interne Z"ahler wird anhand dieses Wertes auch
aktualisiert.
Die Definition von Symbolen mit \tty{ENUM} gleicht einer Definition
mit \tty{EQU}, d.h. es ist nicht m"oglich, einem Symbol einen neuen
Wert zuzuweisen.
Die \tty{ENUMCONF}-Anweisung erlaubt das Verhalten von \tty{ENUM}
zu beeinflussen. \tty{ENUMCONF} akzeptiert ein oder zwei
Argumente, wobei das erste Argument immer der Wert ist, um den
der interne Z"ahler pro Symbol in einer Aufz"ahlung hochgez"ahlt
wird. Mit einem
\begin{verbatim}
ENUMCONF 2
\end{verbatim}
werden den Symbolen also zum Beispiel die Werte 0,2,4,6...
anstelle 0,1,2,3... zugewiesen.
Das zweite (optionale) Argument von \tty{ENUMCONF} bestimmt,
welchen Adre"sraum die Symbole zugeordnet werden. Per Default
sind mit \tty{ENUM} definierte Symbole typenlos, man kann aber
zum Beispiel mit einem
\begin{verbatim}
ENUMCONF 1,CODE
\end{verbatim}
bestimmen, da"s sie im Instruktions-Adre"sraum liegen sollen. Die
Namen der Adre"sr"aume sind die gleichen wie beim
\tty{SEGMENT}-Befehl (\ref{SEGMENT}), zus"atzlich ist als
Argument ein \tty{NOTHING} erlaubt, um wieder typenlose Symbole
zu erzeugen.
%%- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
\ttindex{PUSHV}\ttindex{POPV}
{\em G"ultigkeit: alle Prozessoren}
Mit \tty{PUSHV} und \tty{POPV} ist es m"oglich, den Wert von (nicht
Makro-lokalen) Symbolen tempor"ar zu speichern und zu einem sp"ateren
Zeitpunkt wiederherzustellen. Die Speicherung erfolgt auf {\em Stacks},
d.h. Last-In-First-Out-Speichern. Ein Stack hat einen Namen, der den
allgemeinen Symbolkonventionen gen"ugen mu"s, und existiert so lange,
wie er mindestens ein Element enth"alt: Ein bisher nicht existierender
Stack wird bei \tty{PUSHV} automatisch angelegt, ein durch \tty{POPV} leer
werdender Stack wird automatisch wieder aufgel"ost. Der Name des Stacks,
auf den Symbole abgelegt und von dem sie wieder abgeholt werden sollen,
ist der erste Parameter von \tty{PUSHV} bzw. \tty{POPV}, danach folgt
eine beliebige Menge von Symbolen als weitere Parameter. Alle in der
Liste aufgef"uhrten Symbole m"ussen bereits existieren, es ist also
{\em nicht} m"oglich, mit einem \tty{POPV}-Befehl implizit neue Symbole
zu definieren.
Stacks stellen eine globale Ressource dar, d.h. ihre Namen sind
nicht lokal zu Sektionen.
Wichtig ist, da"s die Variablenliste {\em immer} von links nach rechts
abgearbeitet wird. Wer also mehrere Variablen mit \tty{POPV} von einem
Stack herunter holen will, mu"s diese in genau umgekehrter Reihenfolge
zum entsprechenden \tty{PUSHV} angeben!
Der Name des Stacks kann auch weggelassen werden, etwa so:
\begin{verbatim}
pushv ,var1,var2,var3
.
.
popv ,var3,var2,var1
\end{verbatim}
\asname{} verwendet dann einen internen, vordefinierten Default-Stack.
Nach Ende eines Durchlaufes "uberpr"uft \asname{}, ob noch Stacks existieren,
die nicht leer sind, und gibt deren Namen sowie ,,F"ullstand'' aus. Mit
diesen Warnungen kann man herausfinden, ob an irgendeiner Stelle die
\tty{PUSHV}'s und \tty{POPV}'s nicht paarig sind. Es ist jedoch in
keinem Fall m"oglich, Symbolwerte in einem Stack "uber mehrere Durchl"aufe
hinwegzuretten: Zu Beginn eines Durchlaufes werden alle Stacks geleert!
%%---------------------------------------------------------------------------
%%- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
\label{SectORG}\ttindex{ORG}
{\em G"ultigkeit: alle Prozessoren}
\tty{ORG} erlaubt es, den Assembler-internen Adre"sz"ahler mit einem neuen
Wert zu besetzen. Der Wertebereich ist vom momentan gew"ahlten Segment
und vom Prozessortyp abh"angig (Tabelle \ref{TabORG}).
Die untere Grenze ist dabei immer 0; die obere Grenze der angegebene Wert
minus eins.
Falls in einer Familie verschiedene Varianten unterschiedlich
gro"se Adre"sr"aume haben, ist jeweils der maximale Raum aufgef"uhrt.
ORG wird in erster Linie ben"otigt, um dem Code eine neue Startadresse
zu geben und damit verschiedene, nicht zusammenh"angende Codest"ucke in
einer Quelldatei unterzubringen. Sofern nicht in einem Feld explizit anders
angegeben, ist die vorgegebene Startadresse in einem Segment (d.h. die ohne
{\tt ORG} angenommene) immer 0.
{\bf WICHTIG:} Falls auch mit dem \tty{PHASE}-Befehl gearbeitet
wird, mu"s ber"ucksichtigt werden, da"s das Argument von \tty{ORG}
immer die {\em Ladeadresse} des Codes ist, nicht die {\em
Ausf"uhrungsadresse}. Ausdr"ucke, die sich mit dem \$- oder
\*-Symbol auf den aktuellen Programmz"ahler beziehen, liefern
aber die {\em Ausf"uhrungsadresse} des Codes und f"uhren als
Argument von \tty{ORG} nicht zum gew"unschten Ergebnis. In
solchen F"allen ist die \tty{RORG}-Anweisung (\ref{SectRORG}) das
Mittel der Wahl.
\hfuzz=60pt
\begin{longtable}{|l|c|c|c|c|c|c|c|c|c|c|}
\tin{Ziel} & \tin{CODE} & \tin{DATA} & \tin{I-} & \tin{X-} & \tin{Y-} & \tin{BIT-} & \tin{IO} & \tin{REG} & \tin{ROM-} & \tin{EE-} \\
& & & \tin{DATA} & \tin{DATA} & \tin{DATA} & \tin{DATA} & & & \tin{DATA} & \tin{DATA} \\
\endhead
\input{../doc_COM/taborg.tex}
\multicolumn{11}{|l|}{$^{1}$ Initialwert 80h. } \\
\multicolumn{11}{|l|}{ Da der 8051 kein RAM jenseits 80h hat, mu"s der Initialwert f"ur den 8051} \\
\multicolumn{11}{|l|}{ als Zielprozessor auf jeden Fall mit \tty{ORG} angepa"st werden!} \\
\multicolumn{11}{|l|}{$^{2}$ Da der Z180 weiterhin logisch nur 64K ansprechen kann, ist der} \\
\multicolumn{11}{|l|}{ganze Adre"sraum nur mittels \tty{PHASE}-Anweisungen erreichbar!} \\
\multicolumn{11}{|l|}{$^{3}$ Initialwert 400h.} \\
\multicolumn{11}{|l|}{$^{4}$ Initialwert 800h bzw. 0C00h} \\
\multicolumn{11}{|l|}{$^{5}$ Bereich f"ur Programmcode auf 1 MByte begrenzt} \\
\multicolumn{11}{|l|}{$^{6}$ Gr"o"se ist vom Zielprozessor abh"angig} \\
\multicolumn{11}{|l|}{$^{7}$ Gr"o"se und Verf"ugbarkeit sind vom Zielprozessor abh"angig} \\
\multicolumn{11}{|l|}{$^{8}$ Nur auf Varianten mit \tty{MOVX}-Anweisung} \\
\multicolumn{11}{|l|}{$^{9}$ typabh"angig} \\
\multicolumn{11}{|l|}{$^{10}$ modellabh"angig} \\
\caption{Adre"sbereiche f"ur \tty{ORG}}
\end{longtable}
\hfuzz=0pt
%%- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
\ttindex{RORG}
{\em G"ultigkeit: alle Prozessoren}
\tty{RORG} setzt wie \tty{ORG} den Programmz"ahler neu, erwartet
als Argument allerdings keine absolute Adresse, sondern einen
relativen Wert (positiv oder negativ), der zum Programmz"ahler
addiert wird. Eine Anwendungsm"oglichkeit ist das Freilassen
einer bestimmten Menge von Adre"sraum, oder die Anwendung in
Code-Teilen, die an mehreren Stellen (z.B. via Makros oder
Includes) eingebunden werden und lageunabh"angig arbeiten sollen.
Eine weitere Anwendungsm"oglichkeit ergibt sich in Code, der eine
Ausf"uhrungsadresse unterschiedlich zur Ladeadresse hat (d.h. es
wird mit der \tty{PHASE}-Anweisung gearbeitet). Es gibt kein
Symbol, "uber das man in so einer Situation auf die aktuelle
{\em Ladeadresse} zugreifen kann, aber mittels \tty{RORG} kann man
sich indirekt darauf beziehen.
%%- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
\ttindex{CPU}
{\em G"ultigkeit: alle Prozessoren}
Mit diesem Befehl wird festgelegt, f"ur welchen Prozessor im weiteren
Code erzeugt werden soll. Die Befehle der anderen Prozessorfamilien
sind dann nicht greifbar und erzeugen eine Fehlermeldung!
Die Prozessoren k"onnen grob in Familien unterschieden werden, in den
Familien dienen unterschiedliche Typen noch einmal zur Feinunterscheidung:
%%-----------
\begin{quote}
\begin{tabbing}
a) \> 68008 $\rightarrow$ 68000 $\rightarrow$ 68010 $\rightarrow$ 68012 $\rightarrow$ \\
\> MCF5202 $\rightarrow$ MCF5204 $\rightarrow$ MCF5206 $\rightarrow$ MCF5208$\rightarrow$ \\
\> MCF52274 $\rightarrow$ MCF52277 $\rightarrow$ MCF5307 $\rightarrow$ MCF5329 $\rightarrow$ MCF5373 $\rightarrow$ \\
\> MCF5407 $\rightarrow$ MCF5470 $\rightarrow$ MCF5471 $\rightarrow$ MCF5472 $\rightarrow$ MCF5473 $\rightarrow$ \\
\> MCF5474 $\rightarrow$ MCF5475 $\rightarrow$ MCF51QM $\rightarrow$ \\
\> 68332 $\rightarrow$ 68340 $\rightarrow$ 68360 $\rightarrow$ \\
\> 68020 $\rightarrow$ 68030 $\rightarrow$ 68040
\end{tabbing}
\end{quote}
In dieser Familie liegen die Unterschiede in hinzukommenden Befehlen
und Adressierungsarten (ab 68020). Eine kleine Ausnahme stellt der
Schritt zum 68030 dar, dem 2 Befehle fehlen: \tty{CALLM} und \tty{RTM}.
Die drei Vertreter der 683xx-Familie haben den gleichen Prozessorkern (eine
leicht abgemagerte 68020-CPU), jedoch v"ollig unterschiedliche Peripherie.
MCF5xxx repr"asentiert verschiedene ColdFire-Varianten von Motorola/Freescale/NXP,
zum 680x0 bin"ar abw"artskompatible RISC-Prozesoren. Beim 68040 kommen die zus"atzlichen
Steuerregister (via \tty{MOVEC} erreichbar) f"ur On-Chip-MMU und Caches
sowie einige Systembefehle f"ur selbige hinzu.
%%-----------
\begin{quote}
b) 56000 $\longrightarrow$ 56002 $\longrightarrow$ 56300
\end{quote}
W"ahrend der 56002 nur Befehle zum Inkrementieren und Dekrementieren der
Akkus erg"anzt, ist der 56300-Kern schon fast ein neuer Prozessor: Er
vergr"o"sert alle Adre"sr"aume von 64K-W"ortern auf 16M und verdoppelt fast
die Anzahl der Befehle.
%%-----------
\begin{quote}
c) PPC403 $\rightarrow$ PPC403GC $\rightarrow$ MPC505 $\rightarrow$ MPC601 $\rightarrow$ MPC821 $\rightarrow$ RS6000
\end{quote}
Der PCC403 ist eine abgespeckte Version der PowerPC-Linie ohne
Gleitkommaeinheit, demzufolge sind s"amtliche Gleitkommabefehle
bei ihm gesperrt; daf"ur sind einige Mikrocontroller-spezifische
Befehle enthalten, die er als einziges Mitglied in dieser Familie
kennt. Die GC-Variante des PPC403 hat zus"atzlich eine MMU und deshalb
einige Befehle zu deren Steuerung mehr. Der MPC505 (eine Mikrokontroller-Variante mit FPU)
unterscheidet sich solange vom 601er nur in den Peripherieregistern,
wie ich es nicht besser wei"s - \cite{Mot505} h"alt sich da noch etwas bedeckt...
Die RS6000-Reihe kennt noch einige Befehle mehr (die auf vielen
601er-Systemen emuliert werden, um vollst"andige Kompatibilit"at
herzustellen), au"serdem verwendet IBM z.T. andere Mnemonics f"ur
diese reinen Workstation-Prozessoren, als Remineszenz an die
370er-Gro"srechner...
%%-----------
\begin{quote}
d) IBM5100, IBM5110, IBM5120
\end{quote}
Diese drei Typen referenzieren aktuell alle auf den gleichen (PALM-)
Prozessorkern.
%%-----------
\begin{quote}
e) MCORE
\end{quote}
%%-----------
\begin{quote}
f) XGATE
\end{quote}
%%-----------
\begin{quote}
g) 6800 $\rightarrow$ 6801 $\rightarrow$ 6301 $\rightarrow$ 6811
\end{quote}
W"ahrend der 6301 nur einige neue Befehle definiert (und der 6301
noch ein paar mehr), bietet der 6811 neben weiteren Befehlen ein
zweites Indexregister Y zur Adressierung.
%%-----------
\begin{quote}
h) 6809/6309 und 6805/68HC08/68HCS08
\end{quote}
Diese Prozessoren sind zwar teilweise Quellcode-kompatibel zu den
anderen 68xx-ern, haben aber ein anderes Bin"arcode-Format und einen
deutlich eingeschr"ankteren (6805) bzw. erweiterten (6809) Befehlssatz.
Der 6309 ist eine CMOS-Version des 6809, die zwar offiziell
nur kompatibel zum 6809 ist, inoffiziell aber mehr Register und
deutlich mehr Befehle besitzt (siehe \cite{Kaku}).
%%-----------
\begin{quote}
i) 68HC12 $\longrightarrow$ 68HC12X
\end{quote}
Der 12X-Kern bietet eine Reihe neuer Befehle, bzw. bestehende Befehle
wurden um neue Adressierungsarten erg"anzt.
%%-----------
\begin{quote}
j) S912ZVC19F0MKH, S912ZVC19F0MLF,\\
S912ZVCA19F0MKH, S912ZVCA19F0MLF,\\
S912ZVCA19F0WKH, S912ZVH128F2CLQ,\\
S912ZVH128F2CLL, S912ZVH64F2CLQ,\\
S912ZVHY64F1CLQ, S912ZVHY32F1CLQ,\\
S912ZVHY64F1CLL, S912ZVHY32F1CLL,\\
S912ZVHL64F1CLQ, S912ZVHL32F1CLQ,\\
S912ZVHL64F1CLL, S912ZVHL32F1CLL,\\
S912ZVFP64F1CLQ, S912ZVFP64F1CLL,\\
S912ZVH128F2VLQ, S912ZVH128F2VLL,\\
S912ZVH64F2VLQ, S912ZVHY64F1VLQ,\\
S912ZVHY32F1VLQ, S912ZVHY64F1VL,\\
S912ZVHY32F1VLL, S912ZVHL64F1VLQ
\end{quote}
Alle Derivate beinhalten den gleichen Prozessorkern und den
gleichen Befehlssatz, lediglich die on-Chip-Peripherie und
die Menge eingebauten Speichers (RAM, Flash-ROM, EEPROM)
variieren.
%%-----------
\begin{quote}
k) 68HC16
\end{quote}
%%-----------
\begin{quote}
l) 052001
\end{quote}
Dieser Baustein ist eine Eigenentwicklung von Konami und in
Architektur und Befehlssatz an den Motorola 6809 angelehnt.
Er ist jedoch nicht bin"arkompatibel und stellt auch nicht
alle Befehle und Adressierungsarten des Vorbilds zur Verf"ugung.
%%-----------
\begin{quote}
m) HD6413308 $\longrightarrow$ HD6413309
\end{quote}
Diese beiden Namen repr"asentieren die 300er und 300H-Varianten der
H8-Familie; die H-Version besitzt dabei einen gr"o"seren Adre"sraum
(16 Mbyte statt 64Kbyte), doppelt so breite Register (32 Bit) und
kennt einige zus"atzliche Befehle und Adressierungsarten. Trotzdem
ist sie bin"ar aufw"artskompatibel.
%%-----------
\begin{quote}
n) HD6475328 $\longrightarrow$ HD6475348 $\longrightarrow$
HD6475368 $\longrightarrow$ HD6475388
\end{quote}
Diese Prozessoren besitzen alle den gleichen CPU-Kern; Die unterschiedlichen
Typen dienen lediglich der Einbindung des korrekten Registersatzes
in der Datei \tty{REG53X.INC}.
%%-----------
\begin{quote}
o) SH7000 $\longrightarrow$ SH7600 $\longrightarrow$ SH7700
\end{quote}
Der Prozessorkern des 7600ers bietet eine Handvoll Befehle mehr, die
L"ucken im Befehlssatz des 7000ers schlie"sen (verz"ogerte, bedingte
sowie relative und indirekte Spr"unge, Multiplikationen mit 32-Bit-Operanden
sowie Multiplizier/Addier-Befehle). Die 7700er-Reihe (auch als SH3
gel"aufig) bietet weiterhin eine zweite Registerbank, bessere
Schiebebefehle sowie Befehle zur Cache-Steuerung.
%%-----------
\begin{quote}
p)HD614023 $\longrightarrow$ HD614043 $\longrightarrow$ HD614081
\end{quote}
Diese drei Varianten der HMCS400-Serie unterscheiden sich in der
Gr"o"se des internen ROM- und RAM-Speichers.
%%-----------
\begin{quote}
q) HD641016
\end{quote}
Dies ist aktuell das einzige Target mit H16-Kern.
%%-----------
\begin{quote}
r) 6502 $\rightarrow$ 65(S)C02 $\rightarrow$ 65CE02 / W65C02S /
65C19 / MELPS740 / HUC6280 / 6502UNDOC
\end{quote}
Die CMOS-Version definiert einige zus"atzliche Befehle, au"serdem sind
bei einigen Befehlen Adressierungsarten hinzugekommen, die beim 6502
nicht m"oglich waren. Der W65SC02 erg"anzt den
65C02-Befehlssatz um zwei Befehle, mit denen die Low-Power-Modi
der CPU feiner eingestellt werden k"onnen. Dem 65SC02 fehlen die
Bitmanipulationsbefehle des 65C02. Der 65CE02 erg"anzt Sprungbefehle
mit 16-Bit-Displacement, ein Z-Register, einen 16-bittigen Stack-Pointer,
eine Reihe neuer Befehle und eine programmierbare Base-Page.
Der 65C19 ist {\em nicht} bin"ar aufw"artskompatibel zum
originalen 6502! Einige Adressierungsarten wurden durch andere
ersetzt. Des weiteren enth"alt dieser Prozessor
Befehlssatz-Erweiterungen, die die Implementierung digitaler
Signalverarbeitung erleichtern.
Die Mitsubishi-Mikrokontroller dagegen erweitern den
6502-Befehlssatz in erster Linie um Bitoperationen und
Multiplikations-/Divisionsbefehle. Bis auf den unbedingten Sprung und
Befehle zur Inkrementierung/Dekremetierung des Akkumulators sind die
Erweiterungen disjunkt.
Das herausstechendste Merkmal des HuC 6280 ist der gr"o"sere
Adre"sraum von 2 MByte anstelle 64 KByte, der durch eingebaute
Bankregister erreicht wird. Des weiteren existieren einige
Sonderbefehle zur Kommunikation mit dem Videoprozessor (dieser
Chip wurde in Videospielen eingesetzt) und zum Kopieren von
Speicherbereichen.
Mit dem Prozessortyp 6502UNDOC sind die ,,undokumentierten''
6502-Befehle erreichbar, d.h. die Operationen, die sich bei der Verwendung
nicht als Befehle definierter Bitkombinationen im Opcode ergeben. Die von
\asname{} unterst"utzten Varianten sind im Kapitel mit den prozessorspezifischen
Hinweisen beschrieben.
%%-----------
\begin{quote}
s) MELPS7700, 65816
\end{quote}
Neben einer ,,16-Bit-Version'' des 6502-Befehlssatzes bieten diese
Prozessoren einige Befehlserweiterungen. Diese sind aber gr"o"serenteils
disjunkt, da sie sich an ihren jeweiligen 8-bittigen Vorbildern (65C02
bzw. MELPS-740) orientieren. Z.T.~werden auch andere Mnemonics f"ur
gleiche Befehle verwendet.
%%-----------
\begin{quote}
t) PPS-4
\end{quote}
%%-----------
\begin{quote}
u) MELPS4500
\end{quote}
%%-----------
\begin{quote}
v) M16
\end{quote}
%%-----------
\begin{quote}
w) M16C
\end{quote}
%%-----------
\begin{quote}
x) PDP-11/03, PDP-11/04, PDP-11/05, PDP-11/10, \\
PDP-11/15, PDP-11/20, PDP-11/23, PDP-11/24, \\
PDP-11/34, PDP-11/35, PDP-11/40, PDP-11/44, \\
PDP-11/45, PDP-11/50, MicroPDP-11/53, \\
PDP-11/55, PDP-11/60, PDP-11/70, \\
MicroPDP-11/73, MicroPDP-11/83, PDP-11/84, \\
MicroPDP-11/93, PDP-11/94, T-11
\end{quote}
Die Modelle der PDP-11-Serien unterscheiden sich im
Befehlssatz (sowohl dem eingebauten als auch den verf"ugbaren
Erweiterungen) als auch im verf"ugbaren Adre"sraum (64, 256
oder 4096 KByte).
%%-----------
\begin{quote}
y) WD16
\end{quote}
Der WD16 benutzt den gleichen Prozessor wie der LSI-11,
lediglich mit anderem Mikrocode. Demensprechend sind
Registersatz und Adressierungsarten zur PDP-11 identisch,
der Befehlsumfang ist aber leicht unterschiedlich und
auf der PDP-11 in gleicher Form vorhandene Maschinenbefehle
haben durchg"angig andere Kodierungen.
%%-----------
\begin{quote}
z) CP-3F, LP8000, M380
\end{quote}
Das Prozessorelement des Chipsatzes ist von AEG/Olympia, GI
und SGS-Ates unter den jeweiligen Namen vertrieben worden.
Im Befehlssatz und den Adre"sr"aumen bestehen keine Unterschiede.
%%-----------
\begin{quote}
aa) 4004 $\rightarrow$ 4040
\end{quote}
Der 4040 besitzt gegen"uber seinem Vorg"anger ein gutes Dutzend
zus"atzlicher Maschineninstruktionen.
%%-----------
\begin{quote}
ab) 8008 $\rightarrow$ 8008NEW
\end{quote}
Intel hat 1975 die Mnemonics des umdefiniert, die zweite Variante spiegelt
diesen neuen Befehlssatz wieder. Eine gleichzeitige Unterst"utzung beider
Varianten war nicht m"oglich, da teilweise "Uberschneidungen vorliegen.
%%-----------
\begin{quote}
ac) 8021, 8022, \\
8401, 8411, 8421, 8461, \\
8039, (MSM)80C39, 8048, (MSM)80C48, 8041, 8042, \\
80C382
\end{quote}
Bei den ROM-losen Versionen 8039 und 80C39 sind die Befehle verboten,
die den BUS (Port 0) ansprechen. Der 8021 und 8022 sind Sonderversionen
mit stark abgemagertem Befehlssatz, wof"ur der 8022 zwei A/D-Wandler
und die dazugeh"origen Steuerbefehle enth"alt. MAB8401 bis 8461 sind von
Philips entwickelte Derivate, die in ihrem Befehssatz irgendwo zwischen
dem 8021/8022 und einem 'vollst"andigen'' 8048 stehen. Daf"ur verf"ugen
sie "uber serielle Ports und je nach Variante bis zu 8 KByte Programmspeicher.
Die CMOS-Versionen lassen
sich mit dem \tty{IDL}- bzw. \tty{HALT}-Befehl in einen Ruhezustand niedriger
Stromaufnahme "uberf"uhren. Der 8041 und 8042 haben einige Zusatzbefehle zur
Steuerung der Busschnittstelle, daf"ur fehlen aber einige andere Befehle.
Beim 8041, 8042, 84x1, 8021 und 8022 ist der Programmadre"sraum nicht
extern erweiterbar, weshalb \asname{} das Codesegment bei diesen Prozessoren
auf die Gr"o"se des internen ROM beschr"ankt. Der (SAB)80C382 ist eine von
Siemens speziell f"ur Telefone entwickelte Variante, die ebenfalls
einen \tty{HALT}-Befehl kennt sowie \tty{DJNZ} und \tty{DEC} auch
mit indirekter Adressierung erlaubt. Im Gegenzug wurden einige
Befehle des 'normalen' 8048 entfernt. Die OKI-Varienaten (MSM...)
unterst"utzen ebenfalls \tty{DJNZ} und \tty{DEC} mit indirekter
Adressierung, sowie eine erweiterte Steuerung der
Power-Down-Modi, ohne den Basis-MCS-48-Befehlssatz zu
beschneiden.
%%-----------
\begin{quote}
\begin{tabbing}
ad) \> 87C750 $\rightarrow$ 8051, 8052, 80C320, 80C501, 80C502, \\
\> 80C504, 80515, und 80517 \\
\> $\rightarrow$ 80C390 \\
\> $\rightarrow$ 80C251
\end{tabbing}
\end{quote}
Der 87C750 kann nur max. 2 Kbyte Programmspeicher adressieren, weshalb
die \tty{LCALL}- und \tty{LJMP}-Befehle bei ihm fehlen. Zwischen den
acht mittleren Prozessoren nimmt \asname{} selber "uberhaupt keine Unterscheidung
vor, sondern verwaltet den Unterschied lediglich in der Variablen
\tty{MOMCPU} (s.u.), die man mit \tty{IF}-Befehlen abfragen kann. Eine
Ausnahme stellt lediglich der 80C504, der in seiner momentanen Form noch einen
Maskenfehler zeigt, wenn eine \tty{AJMP}- oder \tty{ACALL}-Anweisung auf der
vorletzten Adresse einer 2K-Seite steht. \asname{} benutzt in einem solchen
Fall automatisch lange Sprungbefehle bzw. gibt eine Fehlermeldung aus. Der
80C251 hingegen stellt einen drastischen Fortschritt in Richtung 16/32 Bit,
gr"o"serer Adre"sr"aume und orthogonalerem Befehlssatz dar. Den 80C390
k"onnte man vielleicht als die 'kleine L"osung' bezeichnen: Dallas
Semiconductor hat den Befehlssatz und die Architektur nur so weit
ver"andert, wie es f"ur die 16 MByte gro"sen Adre"sr"aume notwendig war.
%%-----------
\begin{quote}
ae) 8096 $\rightarrow$ 80196 $\rightarrow$ 80196N $\rightarrow$ 80296
\end{quote}
Neben einem anderen Satz von SFRs (die "ubrigens von Unterversion zu
Unterversion stark differieren) kennt der 80196 eine Reihe von
zus"atzlichen Befehlen und kennt einen ,,Windowing''-Mechanismus, um
das gr"o"sere interne RAM anzusprechen. Die 80196N-Familie wiederum
erweitert den Adre"sraum auf 16 Mbyte und f"uhrt eine Reihe von
Befehlen ein, mit denen man auf Adressen jenseits 64 Kbyte zugreifen
kann. Der 80296 erweitert den CPU-Kern um Befehle zur Signalverarbeitung
und ein zweites Windowing-Register, verzichtet jedoch auf den {\em
Peripheral Transaction Server} (PTS) und verliert damit wieder zwei
Maschinenbefehle.
%%-----------
\begin{quote}
af) 8080 $\rightarrow$ V30EMU $\rightarrow$ 8085 $\rightarrow$ 8085UNDOC
\end{quote}
Der 8085 kennt zus"atzlich die Befehle \tty{RIM} und \tty{SIM} zum Steuern der
Interruptmaske und der zwei I/O-Pins. Der Typ {\tt 8085UNDOC} schaltet
zus"atzliche, nicht von Intel dokumentierte Befehle ein. Diese Befehle
sind in Abschnitt \ref{8085Spec} dokumentiert.
{\tt V30EMU} als Ziel schaltet gegen"uber einem 8080 die Befehle {\tt RETEM}
und {\em CALLN} frei, mit denen die 8080-Emulation auf einem V20/V30/V40/V50
verlassen bzw. unterbrochen werden kann.
%%-----------
\begin{quote}
ag) 8088,8086 \\
$\rightarrow$ 80188,80186 \\
$\rightarrow$ V20,V30,V40,V50 \\
$\rightarrow$ V33,V53 \\
$\rightarrow$ V25,V35 \\
$\rightarrow$ V55 \\
$\rightarrow$ V55SC \\
$\rightarrow$ V55PI
\end{quote}
Prozessoren in der gleichen Zeile verf"ugen "uber den gleichen CPU-Kern und
damit den gleichen Befehlssatz. Von Zeile zu Zeile kommen neue Befehle
hinzu, wobei die NEC-CPUs ausgehend vom 'V20-Basisbefehlssatz' jeweils "uber
unterschiedliche Erweiterungen verf"ugen.
%%-----------
\begin{quote}
ah) 80960
\end{quote}
%%-----------
\begin{quote}
ai) 8X300 $\rightarrow$ 8X305
\end{quote}
Der 8X305 besitzt eine Reihe zus"atzlicher Arbeitsregister, die dem
8X300 fehlen und kann mit diesen auch zus"atzliche Operationen ausf"uhren,
wie das direkte Schreiben von 8-Bit-Werten auf Peripherieadressen.
%%-----------
\begin{quote}
aj) XAG1, XAG2, XAG3
\end{quote}
Diese Prozessoren unterscheiden sich nur in der Gr"o"se des eingebauten
ROMs, die in \tty{STDDEFXA.INC} definiert ist.
%%-----------
\begin{quote}
ak) AT90S1200, AT90S2313, AT90S2323, AT90S233, AT90S2343,\\
AT90S4414, AT90S4433, AT90S4434, AT90S8515,\\
AT90C8534, AT90S8535, ATTINY4, ATTINY5, ATTINY9,\\
ATTINY10, ATTINY11, ATTINY12, ATTINY13, ATTINY13A,\\
ATTINY15, ATTINY20, ATTINY24(A), ATTINY25,\\
ATTINY26, ATTINY28, ATTINY40, ATTINY44(A),\\
ATTINY45, ATTINY48, ATTINY84(A), ATTINY85,\\
ATTINY87, ATTINY88, ATTINY102, ATTINY104,\\
ATTINY167, ATTINY261, ATTINY261A, ATTINY43U,\\
ATTINY441, ATTINY461, ATTINY461A, ATTINY828,\\
ATTINY841, ATTINY861, ATTINY861A, ATTINY1634,\\
ATTINY2313, ATTINY2313A, ATTINY4313, ATMEGA48,\\
ATMEGA8, ATMEGA8515, ATMEGA8535, ATMEGA88,\\
ATMEGA8U2, ATMEGA16U2, ATMEGA32U2,\\
ATMEGA16U4, ATMEGA32U4, ATMEGA32U6, AT90USB646,\\
AT90USB647, AT90USB1286, AT90USB1287, AT43USB355,\\
ATMEGA16, ATMEGA161, ATMEGA162, ATMEGA163,\\
ATMEGA164, ATMEGA165, ATMEGA168, ATMEGA169,\\
ATMEGA32, ATMEGA323, ATMEGA324, ATMEGA325,\\
ATMEGA3250, ATMEGA328, ATMEGA329, ATMEGA3290,\\
ATMEGA406, ATMEGA64, ATMEGA640, ATMEGA644,\\
ATMEGA644RFR2, ATMEGA645, ATMEGA6450,\\
ATMEGA649, ATMEGA6490, ATMEGA103, ATMEGA128,\\
ATMEGA1280, ATMEGA1281, ATMEGA1284,\\
ATMEGA1284RFR2, ATMEGA2560, ATMEGA2561
\end{quote}
Die verschiedenen AVR-Varianten unterscheiden sich in erster Linie in
der Gr"o"se des On-Chip-Speichers (Flash, SRAM, EEPROM) und der integrierten
Peripherie (GPIO, Timer, UART, A/D-Wandler,...). Die ATmegas bringen im
Vergleich zu den AT90...-Vorg"angern auch neue Maschinenbefehle
mit, den ATtinys fehlen wiederum die Multiplikationsbefehle.
%%-----------
\begin{quote}
al) AM29245 $\rightarrow$ AM29243 $\rightarrow$ AM29240 $\rightarrow$ AM29000
\end{quote}
Je weiter man sich in der Liste nach rechts bewegt, desto weniger
Befehle m"ussen in Software emuliert werden. W"ahrend z.B. der 29245
noch nicht einmal einen Hardware-Multiplizierer besitzt, fehlen den
beiden Vertretern in der Mitte nur die Gleitkommabefehle. Der 29000
dient dabei als ,,generischer'' Typ, der alle Befehle in Hardware versteht.
%%-----------
\begin{quote}
am) 80C166 $\longrightarrow$ 80C167,80C165,80C163
\end{quote}
80C167 und 80C165/163 haben anstelle 256 Kbyte max. 16 Mbyte Adre"sraum,
au"serdem kennen sie einige zus"atzliche Befehle f"ur erweiterte
Adressierungsmodi sowie atomare Befehlssequenzen. Untereinander
unterscheiden sich diese Prozessoren der ,,zweiten Generation'' nur in der
eingebauten Peripherie.
%%-----------
\begin{quote}
an) LR35902/GBZ80 $\rightarrow$ Z80 $\rightarrow$ Z80UNDOC \\
$\rightarrow$ Z180 $\rightarrow$ Z380
\end{quote}
W"ahrend f"ur den Z180 nur die zus"atzlichen Befehle definiert sind
(d.h. die Z180-MMU findet noch keine Ber"ucksichtigung), besitzt der
Z380 32-Bit-Register, einen linearen 4Gbyte-Adre"sraum sowie neben
einer Reihe von Befehlserweiterungen, die den Befehlssatz deutlich
orthogonaler machen, neue Adressierungsmodi (Ansprechen der
Indexregisterh"alften, Stack-relativ). Zu einem kleinen Teil existieren
diese Erweiterungen aber auch schon beim Z80 als undokumentierte
Befehle, die mit der Variante \tty{Z80UNDOC} zugeschaltet werden
k"onnen. Eine Liste mit den zus"atzlichen Befehlen findet sich im
Kapitel mit den prozessorspezifischen Hinweisen.
Der im Gameboy verbaute Prozessor (offizielle Bezeichnung LR35902,
umgangssprachlich auch als ,,Gameboy-Z80'' bezeichnet) ist eine
Mischung aus Z80 und 8080. Ihm fehlen die IX/IY-Register, der
I/O-Adre"sraum, die zweite Registerbank sowie eine Reihe von
16-Bit-Befehlen.
%%-----------
\begin{quote}
ao) Z8601, Z8603, Z86C03, Z86E03, Z86C06, Z86E06, \\
Z86C08, Z86C21, Z86E21, Z86C30, Z86C31, Z86C32 Z86C40 \\
$\rightarrow$ Z88C00, Z88C01 \\
$\rightarrow$ eZ8, Z8F0113, Z8F011A, Z8F0123, Z8F012A, \\
Z8F0130, Z8F0131, Z8F0213, Z8F021A, Z8F0223, Z8F022A, \\
Z8F0230, Z8F0231, Z8F0411, Z8F0412, Z8F0413, Z8F041A, \\
Z8F0421, Z8F0422, Z8F0423, Z8F042A, Z8F0430, Z8F0431, \\
Z8F0811, Z8F0812, Z8F0813, Z8F081A, Z8F0821, Z8F0822, \\
Z8F0823, Z8F082A, Z8F0830, Z8F0831, Z8F0880, Z8F1232, \\
Z8F1233, Z8F1621, Z8F1622, Z8F1680, Z8F1681, Z8F1682, \\
Z8F2421, Z8F2422, Z8F2480, Z8F3221, Z8F3222, Z8F3281, \\
Z8F3282, Z8F4821, Z8F4822, Z8F4823, Z8F6081, Z8F6082, \\
Z8F6421, Z8F6422, Z8F6423, Z8F6481, Z8F6482
\end{quote}
Die Varianten mit Z8-Kern unterscheiden sich nur in
Speicherausbau und Peripherie, d.h. die Wahl hat auf den
unterst"utzten Befehlssatz keinen Effekt. Deutlich anders sind
jedoch die Super8- und eZ8-Varianten, jeweils mit (in unterschiedliche
Richtungen) stark erweiterten Befehlss"atzen, die auch auf Quellcode-Ebene
nur g"o"stenteils aufw"arts-kompatibel sind.
%%-----------
\begin{quote}
ap) Z8001, Z8002, Z8003, Z8004
\end{quote}
"Uber die Wahl des Prozessors wird die Betriebsart (segmentiert f"ur
Z8001 und Z8003, nicht segmentiert f"ur Z8002 und Z8004) bestimmt. Eine
Unterscheidung zwischen dem Z8001/8002 einerseits und Z8003/8004 andererseits
findet aktuell nicht statt.
%%-----------
\begin{quote}
aq) KCPSM, KCPSM3
\end{quote}
Bei beiden Prozessorkernen handelt es sich um keine eigenst"andigen
Bausteine, sondern Logik-Kerne f"ur Gate-Arrays der Firma Xilinx. Die
3er-Variante bietet einen gr"o"seren Adre"sraum sowie einige zus"atzliche
Instruktionen. Es ist zu beachten, da"s sie nicht bin"ar
aufw"artskompatibel ist!
%%-----------
\begin{quote}
ar) MICO8\_05, MICO8\_V3, MICO8\_V31
\end{quote}
Leider hat Lattice die Maschinencodes des Mico8 mehrfach ge"andert, so
da"s verschiedene Targets notwendig wurden, um auch alte Designs weiter
zu unterst"utzen. Die erste Variante entspricht der Variante, wie sie
im 2005er-Manual beschrieben wurde, die beiden anderen die Versionen 3.0
bzw. 3.1.
%%-----------
\begin{quote}
as) 96C141, 93C141
\end{quote}
Diese beiden Prozessoren repr"asentieren die beiden Varianten der
Prozessorfamilie: TLCS-900 und TLCS-900L. Die Unterschiede dieser beiden
Varianten werden in Abschnitt \ref{TLCS900Spec} genauer beleuchtet.
%%-----------
\begin{quote}
at) 90C141
\end{quote}
%%-----------
\begin{quote}
au) 87C00, 87C20, 87C40, 87C70
\end{quote}
Die Prozessoren der TLCS-870-Reihe haben zwar den identischen CPU-Kern, je
nach Variante aber eine unterschiedliche Peripherieausstattung. Zum
Teil liegen Register gleichen Namens auf unterschiedlichen Adressen.
Die Datei STDDEF87.INC benutzt analog zur MCS-51-Familie die hier
m"ogliche Unterscheidung, um automatisch den korrekten Symbolsatz
bereitzustellen.
%%-----------
av) TLCS-870/C
Momentan ist nur der Prozessorkern der TLCS-870/C-Familie implmentiert.
%%-----------
\begin{quote}
aw) 47C00 $\rightarrow$ 470C00 $\rightarrow$ 470AC00
\end{quote}
Diese drei Varianten der TLCS-47-Familie haben unterschiedlich gro"se
RAM-und ROM-Adre"sbereiche, wodurch jeweils einige Befehle zur
Bankumschaltung hinzukommen oder wegfallen.
%%-----------
\begin{quote}
ax) 97C241
\end{quote}
%%-----------
\begin{quote}
ay) TC9331
\end{quote}
%%-----------
\begin{quote}
az) 16C54 $\rightarrow$ 16C55 $\rightarrow$ 16C56 $\rightarrow$ 16C57
\end{quote}
Diese Prozessoren unterscheiden sich durch den verf"ugbaren
Adre"sraum im Programmspeicher, d.h. durch die Adresse, ab der
der \asname{} "Uberl"aufe anmeckert.
%%-----------
\begin{quote}
ba) 16C64, 16C84
\end{quote}
Analog zur MCS-51-Familie findet hier keine Unterscheidung im
Codegenerator statt, die unterschiedlichen Nummern dienen lediglich
der Einblendung der korrekten SFRs in STDDEF18.INC.
%%-----------
\begin{quote}
bb) 17C42
\end{quote}
%%-----------
\begin{quote}
bc) SX20, SX28
\end{quote}
Der SX20 steckt in einem kleineren Geh"ause, weshalb der Port C
fehlt.
%%-----------
\begin{quote}
bd) ST6200, ST6201, ST6203, ST6208, ST6209,\\
ST6210, ST6215, ST6218, ST6220, ST6225,\\
ST6228, ST6230, ST6232, ST6235, ST6240,\\
ST6242, ST6245, ST6246, ST6252, ST6253,\\
ST6255, ST6260, ST6262, ST6263, ST6265,\\
ST6280, ST6285
\end{quote}
Die einzelnen ST6-Varianten differieren in der Menge der
On-Chip-Peripherie und dem eingebauten Speicher.
%%-----------
\begin{quote}
be) ST7 \\
ST72251G1, ST72251G2, ST72311J2, ST72311J4, \\
ST72321BR6, ST72321BR7, ST72321BR9, ST72325S4, \\
ST72325S6, ST72325J7, ST72325R9, ST72324J6, \\
ST72324K6, ST72324J4, ST72324K4, ST72324J2, \\
ST72324JK21, ST72325S4, ST72325J7, ST72325R9, \\
ST72521BR6, ST72521BM9, ST7232AK1, ST7232AK2, \\
ST7232AJ1, ST7232AJ2, ST72361AR4, ST72361AR6, \\
ST72361AR7, ST72361AR9, ST7FOXK1, ST7FOXK2, \\
ST7LITES2Y0, ST7LITES5Y0, ST7LITE02Y0, \\
ST7LITE05Y0, ST7LITE09Y0 \\
ST7LITE10F1, ST7LITE15F1, ST7LITE19F1, \\
ST7LITE10BF0, ST7LITE15BF0, ST7LITE15BF1, \\
ST7LITE19BF0, ST7LITE19BF1, \\
ST7LITE20F2, ST7LITE25F2, ST7LITE29F2, \\
ST7LITE30F2, ST7LITE35F2, ST7LITE39F2, \\
ST7LITE49K2, \\
ST7MC1K2, ST7MC1K4, ST7MC2N6, ST7MC2S4, \\
ST7MC2S6, ST7MC2S7, ST7MC2S9, ST7MC2R6, \\
ST7MC2R7, ST7MC2R9, ST7MC2M9, \\
STM8 \\
STM8S001J3, STM8S003F3, STM8S003K3, STM8S005C6,\\
STM8S005K6, STM8S007C8, STM8S103F2, STM8S103F3,\\
STM8S103K3, STM8S105C4, STM8S105C6, STM8S105K4,\\
STM8S105K6, STM8S105S4, STM8S105S6, STM8S207MB,\\
STM8S207M8, STM8S207RB, STM8S207R8, STM8S207R6,\\
STM8S207CB, STM8S207C8, STM8S207C6, STM8S207SB,\\
STM8S207S8, STM8S207S6, STM8S207K8, STM8S207K6,\\
STM8S208MB, STM8S208RB, STM8S208R8, STM8S208R6,\\
STM8S208CB, STM8S208C8, STM8S208C6, STM8S208SB,\\
STM8S208S8, STM8S208S6, STM8S903K3, STM8S903F3,\\
STM8L050J3, STM8L051F3, STM8L052C6, STM8L052R8,\\
STM8L001J3, STM8L101F1, STM8L101F2, STM8L101G2,\\
STM8L101F3, STM8L101G3, STM8L101K3, STM8L151C2,\\
STM8L151K2, STM8L151G2, STM8L151F2, STM8L151C3,\\
STM8L151K3, STM8L151G3, STM8L151F3, STM8L151C4,\\
STM8L151C6, STM8L151K4, STM8L151K6, STM8L151G4,\\
STM8L151G6, STM8L152C4, STM8L152C6, STM8L152K4,\\
STM8L152K6, STM8L151R6, STM8L151C8, STM8L151M8,\\
STM8L151R8, STM8L152R6, STM8L152C8, STM8L152K8,\\
STM8L152M8, STM8L152R8, STM8L162M8, STM8L162R8,\\
STM8AF6366, STM8AF6388, STM8AF6213, STM8AF6223,\\
STM8AF6226, STM8AF6246, STM8AF6248, STM8AF6266,\\
STM8AF6268, STM8AF6269, STM8AF6286, STM8AF6288,\\
STM8AF6289, STM8AF628A, STM8AF62A6, STM8AF62A8,\\
STM8AF62A9, STM8AF62AA, STM8AF5268, STM8AF5269,\\
STM8AF5286, STM8AF5288, STM8AF5289, STM8AF528A,\\
STM8AF52A6, STM8AF52A8, STM8AF52A9, STM8AF52AA,\\
STM8AL3136, STM8AL3138, STM8AL3146, STM8AL3148,\\
STM8AL3166, STM8AL3168, STM8AL3L46, STM8AL3L48,\\
STM8AL3L66, STM8AL3L68, STM8AL3188, STM8AL3189,\\
STM8AL318A, STM8AL3L88, STM8AL3L89, STM8AL3L8A,\\
STM8TL52F4, STM8TL52G4, STM8TL53C4, STM8TL53F4,\\
STM8TL53G4
\end{quote}
Der STM8-Kern erweitert den Adre"sraum auf bis zu 16 MByte und f"uhrt
eine ganze Reihe neuer Befehle ein. Obwohl viele Befehle den
gleichen Maschinencode wie beim ST7 haben, ist er nicht bin"ar
aufw"artskompatibel.
%%-----------
\begin{quote}
bf) ST9020, ST9030, ST9040, ST9050
\end{quote}
Diese 4 Namen vetreten die vier ,,Unterfamilien'' der ST9-Familie, die
sich durch eine unterschiedliche Ausstattung mit On-Chip-Peripherie
auszeichnen. Im Prozessorkern sind sie identisch, so da"s diese
Unterscheidung wieder nur in der Include-Datei mit den Peripherieadressen zum
Zuge kommt.
%%-----------
\begin{quote}
bg) 6804
\end{quote}
%%-----------
\begin{quote}
bh) 32010 $\rightarrow$ 32015
\end{quote}
Der TMS32010 besitzt nur 144 Byte internes RAM, weshalb \asname{} Adressen im
Datensegment auf eben diesen Bereich begrenzt. F"ur den 32015 gilt diese
Beschr"ankung nicht, es kann der volle Bereich von 0--255 angesprochen
werden.
%%-----------
\begin{quote}
bi) 320C25 $\rightarrow$ 320C26 $\rightarrow$ 320C28
\end{quote}
Diese Prozessoren unterscheiden sich nur leicht in der
On-Chip-Peripherie sowie den Konfigurationsbefehlen.
%%-----------
\begin{quote}
bj) 320C30, 320C31 $\rightarrow$ 320C40, 320C44
\end{quote}
Der 320C31 ist eine etwas ,,abgespeckte'' Version des 320C30 mit dem
gleichen Befehlssatz, jedoch weniger Peripherie. In STDDEF3X.INC
wird diese Unterscheidung ausgenutzt. Die C4x-Varianten sind
Quellcode-aufw"artskompatibel, unterscheiden sich im
Maschinencode einiger Befehle jedoch subtil. Auch hier ist ist
der C44 eine abgespeckte Version des C40, mit weniger Peripherie
und kleinerem Adre"sraum.
%%-----------
\begin{quote}
bk) 320C203 $\rightarrow$ 320C50, 320C51, 320C53
\end{quote}
Ersterer ist der generelle Repr"asentant f"ur die
C20x-Signalprozessorfamilie, die eine Untermenge des C5x-Befehlssatzes
implementieren. Die Unterscheidung zwischen den verschiedenen
C5x-Prozessoren wird von \asname{} momentan nicht ausgenutzt.
%%-----------
\begin{quote}
bl) 320C541
\end{quote}
Dies ist momentan der Repr"asentant f"ur die TMS320C54x-Familie...
%%-----------
\begin{quote}
bm) TI990/4, TI990/10, TI990/12 \\
TMS9900, TMS9940, TMS9995, TMS99105, TMS99110
\end{quote}
Die TMS99xx/99xxx-Prozessoren sind im Prinzip Single-Chip-Implementierungen
der TI990-Minicomputer, einige TI990-Modelle basieren auch auf einem solchen
Prozessor anstatt einer diskret aufgebauten CPU. Die einzelnen Modelle
unterscheiden sich im Befehlssatz (der TI990/12 hat den gr"o"sten), und
dem Vorhandensein eines privilegierten Modus.
%%-----------
\begin{quote}
\begin{tabbing}
bn) \> TMS70C00, TMS70C20, TMS70C40, \\
\> TMS70CT20, TMS70CT40, \\
\> TMS70C02, TMS70C42, TMS70C82, \\
\> TMS70C08, TMS70C48 \\
\end{tabbing}
\end{quote}
Alle Mitglieder dieser Familie haben den gleichen CPU-Kern,
unterscheiden sich im Befehlssatz also nicht. Die Unterschiede
finden sich nur in der Datei REG7000.INC, in der Speicherbereiche
und Peripherieadressen definiert werden. Die in einer Zeile
stehenden Typen besitzen jeweils gleiche Peripherie und gleiche
interne RAM-Menge, unterscheiden sich also nur in der Menge
eingebauten ROMs.
%%-----------
\begin{quote}
bo) 370C010, 370C020, 370C030, 370C040 und 370C050
\end{quote}
Analog zur MCS-51-Familie werden die unterschiedlichen Typen nur
zur Unterscheidung der Peripherie in STDDEF37.INC genutzt, der
Befehlssatz ist identisch.
%%-----------
\begin{quote}
bp) MSP430 $\rightarrow$ MSP430X
Die X-Variante des CPU-Kerns erweitert den Adre"sraum von 64
KiByte auf 1 MiByte und erweitert den Befehlssatz, um
Instruktionen mehrfach ausf"uhren zu k"onnen.
\end{quote}
%%-----------
\begin{quote}
bq) TMS1000, TMS1100, TMS1200, TMS1300
\end{quote}
F"ur TMS1000 und TMS1200 sind jeweils 1 KByte ROM und 64 Nibbles
RAM vorgesehen, f"ur TMS1100 und TMS1300 jeweils das doppelte. Des
weiteren hat TI f"ur TMS1100 und TMS1300 einen deutlich anderen
Default-Befehlssatz vorgesehen (\asname{} kennt nur die Default-
Befehlss"atze!).
%%-----------
\begin{quote}
br) IMP-16C/200, IMP-16C/300, IMP-16P/200, IMP-16P/300, IMP-16L
\end{quote}
Beim IMP-16L sind einige zus"atzliche Bits im Statusregister sowie
weitere Sprungbedingungen definiert. Den erweiterten Befehlssatz
unterst"utzt er ebenso wie die 300er-Varianten.
%%-----------
\begin{quote}
bs) IPC-16, INS8900
\end{quote}
Der INS8900 ist lediglich eine Re-Implementierung des PACE in
einem modernerem NMOS-Fertigungsprozess; es bestehen keine
Unterschiede im Befehlssatz.
%%-----------
\begin{quote}
bt) SC/MP
\end{quote}
%%-----------
\begin{quote}
bu) 8070
\end{quote}
Dieser Prozessor repr"asentiert die gesamte 807x-Familie (die mindestens
aus den 8070, 8072 und 8073 besteht), der jedoch ein einheitlicher
CPU-Kern gemeinsam ist.
%%-----------
\begin{quote}
bv) COP87L84
\end{quote}
Dies ist das momentan einzige unterst"utzte Mitglied der COP8-Familie
von National Semiconductor. Mir ist bekannt, da"s die Familie
wesentlich gr"o"ser ist und auch Vertreter mit unterschiedlich gro"sem
Befehlssatz existieren, die nach Bedarf hinzukommen werden. Es ist eben
ein Anfang, und die Dokumentation von National ist ziemlich umfangreich...
%%-----------
\begin{quote}
bw) COP410 $\rightarrow$ COP420 $\rightarrow$ COP440 $\rightarrow$ COP444
Die COP42x-Derivate bieten einige weitere Befehle, des weiteren wurden
Befehlen in ihrem Wertebereich erweitert.
\end{quote}
%%-----------
\begin{quote}
\begin{tabbing}
bx) \> SC14400, SC14401, SC14402, SC14404, SC14405, \\
\> SC14420, SC14421, SC14422, SC14424 \\
\end{tabbing}
\end{quote}
Diese Gruppe von DECT-Controller unterscheidet sich in ihrem
Befehlsumfang, da jeweils unterschiedliche B-Feld Datenformate
unterst"utzt werden und deren Architektur im Laufe der Zeit optimiert
wurde.
%%-----------
\begin{quote}
by) NS16008, NS32008, NS08032, NS16032, NS32016, NS32032, \\
NS32332, NS32CG16, NS32532
\end{quote}
National hat in den ersten Jahren die CPUs der ersten Generation
mehrfach umbenannt, hinter NS16008/NS32008/NS08032 bzw.
NS16032/NS32016 versteckt sich der gleiche Baustein. NS32332
und NS32532 unterst"utzen eine Adre"sraum von 4 GByte statt 16 MByte,
und der NS32CG16 ist eine Embedded-Variante mit Zusatzbefehlen f"ur
Bitblock-Transfers.
%%-----------
\begin{quote}
bz) ACE1101, ACE1202
\end{quote}
%%-----------
\begin{quote}
ca) F3850, MK3850, \\
MK3870, MK3870/10, MK3870/12, "MK3870/20, MK3870/22, \\
MK3870/30, MK3870/32, MK3870/40, MK3870/42, \\
MK3872, MK3873, MK3873/10, MK3873/12, MK3873/20, MK3873/22, \\
MK3874, MK3875, MK3875/22, MK3875/42, MK3876, MK38P70/02, \\
MK38C70, MK38C70/10, \\
MK38C70/20, MK97400, MK97410, MK97500, MK97501, MK97503
\end{quote}
Die gro"se Menge an Varianten ergibt sich zum Teil daraus, da"s
Mostek Anfang der 80er-Jahre diversen Varianten neue Namen gegeben
hat. Am neuen Benamungsschema kann man am Suffix die Menge internen
ROMs (0 bis 4 f"ur 0..4 KByte) bzw. die Menge des eingebauten
Executable RAM (0 oder 2 f"ur 0 oder 64 Byte) ablesen. 3850 und
MK975xx unterst"utzen einen 64 KByte gro"sen Adre"sraum, beim Rest ist
er 4 KByte gro"s. P-Varianten haben einen Piggyback-Sockel f"ur ein
EPROM, C-Varianten sind in CMOS ausgef"uhrt und kennen zwei
neue Maschinenbefehle (HET und HAL). Der MK3873 enth"alt als
,,Spezialit"at'' eine eingebaute serielle Schnittstelle, der
MK3875 bietet einen zweiten Betriebsspannungsanschlu"s, um den
internen RAM-Inhalt im Standby halten zu k"onnen.
%%-----------
\begin{quote}
cb) 7800, 7801, 7802 \\
78C05, 78C06 \\
7807, 7808, 7809 \\
7810 $\rightarrow$ 78C10, 78C11, 78C12, 78C14, 78C17, 78C18
\end{quote}
$\mu$PD7800 bis $\mu$PD7802 repr"asentieren die ''erste Generation'' der
uCOM87-Familie von NEC. $\mu$PD78C05 und $\mu$PD78C06 sind davon abgespeckte
Versionen, die nur eine Untermenge des Befehlssatzes unterst"utzen. 7807
bis 7809 stellen die uCOM87-Serie dar, die um weitere Befehle und erg"anzt
wurde. Alle $\mu$PD781x-Varianten geh"oren zur uCOM87AD-Serie, die dar"uber
hinaus um einen A/D-Wandler erg"anzt wurde, daf"ur wurden die Befehle zur
Verarbeitung von Bits wieder entfernt. \bb{ACHTUNG!} Der Befehlssatz ist
generell nur teilweise bin"ar aufw"artskompatibel! Die NMOS-Version
$\mu$PD7810 besitzt keinen STOP-Modus; der entsprechende Befehl sowie das
ZCM-Register fehlen demzufolge. \bb{VORSICHT!} NMOS- und CMOS-Version
differieren zum Teil in den Reset-Werten einiger Register!
%%-----------
\begin{quote}
cc) 7566 $\leftrightarrow$ 7508
\end{quote}
Es existieren in der $\mu$PD75xx-Familie zwei verschiedene
CPU-Kerne: Der 7566 repr"asentiert den 'instruction set B', der
deutlich weniger Befehle, einige Register weniger und kleinere
Adre"sr"aume erlaubt. Der 7508 repr"asentiert den 'vollen'
Befehlssatz A. {\bf VORSICHT!} Beide Maschinen-Befehlss"atze
sind nicht 100\%-ig bin"arkompatibel!
%%-----------
\begin{quote}
\begin{tabbing}
cd) \> 75402, \\
\> 75004, 75006, 75008, \\
\> 75268, \\
\> 75304, 75306, 75308, 75312, 75316, \\
\> 75328, \\
\> 75104, 75106, 75108, 75112, 75116, \\
\> 75206, 75208, 75212, 75216, \\
\> 75512, 75516 \\
\end{tabbing}
\end{quote}
Dieses ,,F"ullhorn'' an Prozessoren unterscheidet sich innerhalb einer
Gruppe nur durch die RAM- und ROM-Gr"o"se; die Gruppen untereinander
unterscheiden sich einmal durch ihre on-chip-Peripherie und
zum anderen durch die M"achtigkeit des Befehlssatzes.
%%-----------
\begin{quote}
ce) 78070
\end{quote}
Dies ist das einzige, mir momentan vertraute Mitglied der
78K0-Familie von NEC. Es gelten "ahnliche Aussagen wie zur
COP8-Familie!
%%-----------
\begin{quote}
cf) 78214
\end{quote}
Dies ist momentan der Repr"asentant der 78K2-Familie von NEC.
%%-----------
\begin{quote}
cg) 78310
\end{quote}
Dies ist momentan der Repr"asentant der 78K3-Familie von NEC.
%%-----------
\begin{quote}
ch) 784026
\end{quote}
Dies ist momentan der Repr"asentant der 78K4-Familie von NEC.
%%-----------
\begin{quote}
ci) 7720 $\rightarrow$ 7725
\end{quote}
Der $\mu$PD7725 bietet im Vergleich zu seinem Vorg"anger gr"o"sere
Adre"sr"aume und einige zus"atzliche Befehle. {\bf VORSICHT!} Die
Prozessoren sind nicht zueinander bin"arkompatibel!
%%-----------
\begin{quote}
cj) 77230
\end{quote}
%%-----------
\begin{quote}
ck) 70616
\end{quote}
Dies ist momentan der Repr"asentant der V60-Familie von NEC.
%%-----------
\begin{quote}
\begin{tabbing}
cl) \= SYM53C810, SYM53C860, SYM53C815, SYM53C825, \\
\> SYM53C875, SYM53C895
\end{tabbing}
\end{quote}
Die einfacheren Mitglieder dieser Familie von SCSI-Prozessoren besitzen
einige Befehlsvarianten nicht, au"serdem unterscheiden sie sich in ihrem
Satz interner Register.
%%-----------
\begin{quote}
cm) MB89190
\end{quote}
Dieser Prozessortyp repr"asentiert die F$^{2}$MC8L-Serie von Fujitsu...
%%-----------
\begin{quote}
cn) MB9500
\end{quote}
...so wie dieser es momentan f"ur die 16-Bit-Varianten von Fujitsu tut!
%%-----------
\begin{quote}
co) MSM5840, MSM5842, MSM58421, MSM58422, MSM5847
\end{quote}
Diese Varianten der OLMS-40-Familie unterscheiden sich im
Befehlssatz sowie im internen Programm- und Datenspeicher.
%%-----------
\begin{quote}
cp) MSM5054, MSM5055, MSM5056, MSM6051, MSM6052
\end{quote}
Gleiches wie bei der OLMS-40-Familie: Unterschiede im
Befehlssatz sowie im internen Programm- und Datenspeicher.
%%-----------
\begin{quote}
cq) MN1610[ALT] $\rightarrow$ MN1613[ALT]
\end{quote}
Zus"atzlich zu den Funktionen seines Vorg"angers bietet der
MN1613 einen gr"o"seren Adre"sraum, eine Floating-Point-Einheit
sowie eine ganze Reihe neuer Befehle.
%%-----------
\begin{quote}
cr) RXV1, RX110, RX111, RX113, RX130, RX210,\\
RX21A, RX220, RX610, RX621, RX62N, RX630,\\
RX631 $\longrightarrow$ \\
RXV2, RX140, RX230, RX231, RX64M,\\
RX651 $\longrightarrow$ \\
RXV3, RX660, RX671, RX72M, RX72N
\end{quote}
Die Controller der RX-Serie k"onnen grob in drei
Gruppen bzw. Generationen eingeteilt werden, wobei
von Generation zu Generation (RXv1, RXv2, RXv3)
jeweils neue Instruktionen hinzu gekommen sind.
%%-----------
\begin{quote}
cs) PMC150, PMS150, PFS154, PMC131, PMS130, PMS131 \\
PMS132, PMS132B, PMS152, PMS154B, PMS154C, PFS173 \\
PMS133, PMS134, DF69, MCS11, PMC232, PMC234, PMC251 \\
PMC271,PMC884, PMS232, PMS234, PMS271
\end{quote}
Die Padauk-Controller unterscheiden sich allesamt in
der Gr"o"se des internen (ROM/RAM)-Speichers, der Art
des internen ROMs (l"oschbar oder OTP), der eingebauten
Peripherie sowie in Umfang und Kodierung des Befehlssatzes.
%%-----------
\begin{quote}
ct) 1802 $\rightarrow$ 1804, 1805, 1806 $\rightarrow$ 1804A, 1805A
1806A
\end{quote}
1804, 1805 und 1806 haben gegen"uber dem 'Original' 1802 einen leicht
erweiterten Befehlssatz sowie on-chip-RAM und einen integrierten
Timer. Die A-Versionen erweitern den Befehlssatz um \tty{DSAV},
\tty{DBNZ}, sowie um Befehle f"ur Addition und Subtraktion im
BCD-Format.
%%-----------
\begin{quote}
cu) XS1
\end{quote}
Dieser Typ repr"asentiert die XCore-''Familie''.
%%-----------
\begin{quote}
cv) 1750
\end{quote}
MIL STD 1750 ist ein Standard, also gibt es auch nur eine
(Standard-)Variante...
%%-----------
\begin{quote}
cw) KENBAK
\end{quote}
Es hat nie einen KENBAK-2 gegeben...
%%-----------
\begin{quote}
cx) CP-1600
\end{quote}
%%-----------
\begin{quote}
cy) HPNANO
\end{quote}
%%-----------
\begin{quote}
cz) 6100 $\rightarrow$ 6120
\end{quote}
Der IM6120 unterst"utzt einen gr"o"seren Adre"sraum (32K
anstelle 4K) sowie zus"atzliche Maschinenbefehle.
%%-----------
\begin{quote}
da) SC61860
\end{quote}
Dies ist der in den meisten Sharp Pocket Computern (PC-12xx...PC-15xx) verbaute
Prozessor.
%%-----------
\begin{quote}
db) SC62015
\end{quote}
Dies ist der im Sharp PC-E500 verbaute Prozessor.
Ein spezielles, bisher hier nicht aufgelistetes Target ist
NONE. Es ist als Default eingestellt, wenn kein Target
per {\tt -cpu} Argument auf der Kommandozeile vorgegeben
wurde, und auch bisher keine {\tt CPU}-Anweisung assembliert
wurde. Target-unabh"angige Pseudo-Befehle sind in diesem
Zustand weiter m"oglich, aber es kann kein Code erzeugt
werden, weder durch Maschinenbefehle noch durch Datenablage.
Prinzipiell ist es auch m"oglich, dieses Target per {\tt -cpu}
oder {\tt CPU} auszuw"ahlen, aber der praktische Nutzen davon
ist nat"urlich beschr"ankt.
Beim CPU-Befehl mu"s der Prozessortyp als einfaches Literal
angegeben werden, eine Berechnung \`a la
\begin{verbatim}
CPU 68010+10
\end{verbatim}
ist also nicht zul"assig. G"ultige Aufrufe sind z.B.
\begin{verbatim}
CPU 8051
\end{verbatim}
oder
\begin{verbatim}
CPU 6800
\end{verbatim}
Egal, welcher Prozessortyp gerade eingestellt ist, in der
Integervariablen MOMCPU wird der momentane Status als Hexadezimalzahl
abgelegt. F"ur den 68010 ist z.B. \tty{MOMCPU=\$68010}, f"ur den 80C48
\tty{MOMCPU=80C48H}. Da man Buchstaben au"ser A..F nicht als Hexziffer
interpretieren kann, mu"s man sich diese bei der Hex-Darstellung
des Prozessors wegdenken. F"ur den Z80 ist z.B. \tty{MOMCPU=80H}.
Dieses Feature kann
man vorteilhaft einsetzen, um je nach Prozessortyp unterschiedlichen
Code zu erzeugen. Der 68000 z.B. kennt noch keinen Befehl f"ur den
Unterprogrammr"ucksprung mit Stapelkorrektur. Mit der Variablen
\tty{MOMCPU} kann man ein Makro definieren, das je nach Prozessortyp den
richtigen Befehl benutzt oder ihn emuliert:
\begin{verbatim}
myrtd MACRO disp
IF MOMCPU$<$68010 ; auf 68008 und
MOVE.L (sp),disp(sp) ; 68000 emulieren
LEA disp(sp),sp
RTS
ELSEIF
RTD #disp ; ab 68010 direkt
ENDIF ; benutzen
ENDM
CPU 68010
MYRTD 12 ; ergibt RTD #12
CPU 68000
MYRTD 12 ; ergibt MOVE.. /
; LEA.. / RTS
\end{verbatim}
Da nicht alle Prozessornamen nur aus Ziffern und Buchstaben zwischen
A und F bestehen, wird zus"atzlich der volle Name in der
String-Variablen \tty{MOMCPUNAME} abgelegt.
Implizit schaltet der Assembler mit dem \tty{CPU}-Befehl das aktuelle Segment
wieder auf Code zur"uck, da dies das einzige Segment ist, das alle
Prozessoren definieren.
Eine wichtige "Anderung: Das Default-Target ist nich mehr der 68008. Falls
kein {\tt -cpu} Kommandozeilen-Argument gegeben wurde, dann ist bis zur
ersten \tty{CPU}-Anweisung das reservierte Target \tty{NONE} gesetzt. Vom
Target unabh"angig verf"ugbare Pseudo-Anweisungen sind in dieser Situation
weiterhin erlaubt, zum Beispiel um Konstanten oder Makros zu definieren.
Es ist aber nicht m"oglich, irgendwelchen Code zu definieren, weder "uber
Maschinenbefehle, noch durch Ablegen von Daten im Speicher.
F"ur einige Ziele sind Optionen bzw. Varianten definiert, die so grundlegend
sind, da"s sie direkt zusammen mit dem \tty{CPU}-Befehl gew"ahlt werden m"ussen.
Solche Optionen h"angt man direkt an das Argument mit Doppelpunkten an, und sie
haben die Form von Variablenzuweisungen:
\begin{verbatim}
CPU <CPU-Name>:<var1>=<wert1>:<var2>=<wert2>:...
\end{verbatim}
Ob das jeweilige Ziel solche Optionen unterst"utzt, und wenn ja welche, wird im
jeweils zugeh"origen Unterkapitel mit prozessorspezifischen Hinweisen beschrieben.
%%- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
\ttindex{SUPMODE}\ttindex{FPU}\ttindex{PMMU}\ttindex{CUSTOM}
{\em
\begin{itemize}
\item{G"ultigkeit SUPMODE: 680x0, NS32xxx, PDP-11, i960, TLCS-900,
SH7000, i960, 29K, XA, PowerPC, M*CORE, V60 und TMS9900}
\item{G"ultigkeit FPU: 680x0, NS32xxx, 80x86}
\item{G"ultigkeit PMMU: 680x0, NS32xxx}
\item{G"ultigkeit CUSTOM: NS32xxx}
\end{itemize}
}
Mit diesen Schaltern kann bestimmt werden, auf welche Teile des
Befehlssatzes verzichtet werden soll, weil die daf"ur n"otigen
Vorbedingungen im folgenden Codest"uck nicht gegeben sind. Als
Parameter f"ur diese Befehle darf entweder \tty{ON} oder \tty{OFF} gegeben werden,
der momentan gesetzte Zustand kann aus einer Variablen ausgelesen
werden, die entweder TRUE oder FALSE ist. Die Befehle bedeuten im einzelnen
folgendes:
\begin{itemize}
\item{\tty{SUPMODE}: erlaubt bzw. sperrt Befehle, f"ur deren Ausf"uhrung
der Prozessor im Supervisorstatus sein mu"s. Die Statusvariable
hei"st \tty{INSUPMODE}.}
\item{\tty{FPU}: erlaubt bzw. sperrt die Befehle des numerischen Koprozessors
8087, NS32081/32381 bzw. 68881/68882. Die Statusvariable hei"st \tty{FPUAVAIL}.
F"ur NS32xxx als Ziel darf neben einem einfachen \tty{ON} oder \tty{OFF}
auch der FPU-Typ (\tty{NS32081}, \tty{NS32181}, \tty{NS32381} oder \tty{NS32580})
angegeben werden, um die erweiterten Register und Befehle freizugeben oder
zu verbieten.}
\item{\tty{PMMU}: erlaubt bzw. sperrt die Befehle der Speicherverwaltungseinheit
68851 bzw. der im 68030 eingebauten MMU. \bb{ACHTUNG!} Die 68030-MMU
erlaubt nur eine relativ kleine Untermenge der 68851-Befehle, dies wird
"uber den \tty{FULLPMMU}-Befehl gesteuert. Die Statusvariable hei"st
\tty{PMMUAVAIL}. F"ur NS32xxx als Ziel darf neben einem einfachen \tty{ON}
oder \tty{OFF} auch der MMU-Typ (\tty{NS32082}, \tty{NS32382} oder \tty{NS32532})
angegeben werden, um den jeweiligen MUU-Registersatz freizugeben.}
\item{\tty{CUSTOM}: erlaubt bzw. sperrt die f"ur benutzerdefinierte Slave-Prozessoren
vorgesehenen Befehle.}
\end{itemize}
Benutzung von auf diese Weise gesperrten Befehlen erzeugt bei \tty{SUPMODE}
eine Warnung, bei \tty{PMMU} und \tty{FPU} eine echte Fehlermeldung.
%%- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
\ttindex{CIS}\ttindex{EIS}\ttindex{FIS}\ttindex{FP11}
{\em
\begin{itemize}
\item{G"ultigkeit: PDP-11}
\end{itemize}
}
Mit diesen Anweisungen schaltet man die Verf"ugbarkeit bestimmter
PDP-11-Befehlssatzerweiterungen ein oder aus. Voraussetzung f"ur die
Verf"ugbarkeit einer dieser Anweisungen ist, da"s die fraglichen Befehle
nicht bereits im Basis-Befehlssatz enthalten sind, und da"s eine
entsprechende Aufr"ustm"oglichkeit bestanden hat. Im einzelnen:
\begin{itemize}
\item{{\tt CIS}: ,,Commercial Instruction Set'', d.h. Befehle zur
Verarbeitung gepackter und nicht gepackter BCD-Zahlen mit
variabler L"ange. Diese waren auf dem LSI-11 sowie der
PDP-11/44 als Option verf"ugbar.}
\item{{\tt EIS}: Die Befehle {\tt MUL, DIV, ASH} und {\tt ASHC},
die auf fr"uhen bzw. einfachen PDP-11-Systemen nicht Teil
des Basisbefehlssatzes waren. Auf dem LSI-11 bzw. der
PDP-11/35 und PDP-11/40 waren sie per Option nachr"ustbar.}
\item{{\tt FIS}: Stack-orientierte Befehle, die die Grundrechenarten
f"ur Gleitkommazahlen im F-Format (32 Bit) implementieren.
Auf dem LSI-11 bzw. der PDP-11/35 und PDP-11/40 waren sie
per Option nachr"ustbar.}
\item{{\tt FP11}: Volle Gleitkomma-Unterst"utzung mit separaten
FPU-Registern im F- und D-Format (32/64 Bit).}
\end{itemize}
%%- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
\ttindex{FULLPMMU}
{\em G"ultigkeit: 680x0}
Motorola hat zwar ab dem 68030 die PMMU in den Prozessor integriert,
diese aber nur mit einer Funktionsuntermenge der externen PMMU 68851
ausgestattet. \asname{} sperrt bei aktiviertem PMMU-Befehlssatz (s.o.) deshalb
alle fehlenden Befehle, wenn als Zielprozessor 68030 oder h"oher
eingestellt wurde. Nun kann es aber sein, da"s in einem System mit
68030-Prozessor die interne MMU abgeschaltet wurde und der Prozessor
mit einer externen 68851 betrieben wird. Mit \tty{FULLPMMU ON} kann man
\asname{} dann mitteilen, da"s der vollst"andige MMU-Befehlssatz zugelassen
ist. Umgekehrt kann man, wenn man portablen Code erzeugen will, alle
zus"atzlichen Befehle trotz 68020-Zielplattform mit \tty{FULLPMMU OFF}
abschalten. Die Umschaltung darf beliebig oft erfolgen, die momentane
Einstellung kann aus einem gleichnamigen Symbol ausgelesen werden.
\bb{ACHTUNG!} Der \tty{CPU}-Befehl besetzt f"ur 680x0-Argumente implizit
diese Einstellung vor! \tty{FULLPMMU} mu"s also auf jeden Fall nach dem
\tty{CPU}-Befehl kommen!
%%- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
\ttindex{PADDING}
{\em G"ultigkeit: 680x0, 68xx, M*Core, XA, H8, SH7000, TMS9900,\\
MSP430(X), ST7/STM8, AVR (nur wenn die Granularit"at des Code-Segments
8 Bit ist)}
Diverse Prozessorfamilien verlangen, da"s Objekte von mehr als einem
Byte L"ange auf einer geraden Adresse liegen m"ussen. Neben Datenobjekten
schlie"st dies auch Instruktionsworte selber ein - auf einem 68000
l"osen Wortzugriffe auf eine ungerade Adresse zum Beispiel eine
Exception aus, andere Prozessoren wie die H8-Familie setzen das
unterste Adre"sbit bei einem Wortzugriff einfach hart auf Null.
Mit dem \tty{PADDING}-Befehl kann man einen Mechanismus aktivieren,
mit dem der Assembler versucht, solches 'Misalignment' nach M"oglichkeit
zu verhindern. Steht die Situation an, da"s ein Instruktionswort,
oder auch z.B. mit \tty{DC} angelegte Daten von 16 Bit oder mehr auf
einer ungeraden Adresse landen w"urden, dann wird automatisch ein F"ullbyte
davor eingef"ugt. Im Listing wird dieses F"ullbyte in einer separaten
Zeile mit dem Hinweis
\begin{verbatim}
<padding>
\end{verbatim}
ausgewiesen.
Steht in der Quellzeile ein Label, so verweist dieses Label weiterhin
auf den von dieser Zeile erzeugten Code, also auf die Adresse unmittelbar
nach dem F"ullbyte. Das gleiche gilt auch f"ur ein Label in einer
separaten Zeile unmittelbar davor, sofern diese Zeile {\em alleine} das
Label und selber keine Anweisung enth"alt. Im folgenden Beispiel:
\begin{verbatim}
padding on
org $1000
dc.b 1
adr1: nop
dc.b 1
adr2:
nop
dc.b 1
adr3: equ *
nop
\end{verbatim}
w"urden die Labels \tty{adr1} und \tty{adr2} die (durch ein F"ullbyte
auf einen geraden Wert aufgerundete) Adresse der jeweiligen \tty{NOP}-
Instruktion beinhalten, \tty{adr3} w"urde jedoch auf das F"ullbyte {\em vor}
der dritten \tty{NOP}-Instruktion zeigen.
Als Argument zu \tty{PADDING} ist analog zu den vorherigen Befehlen
\tty{ON} oder \tty{OFF} erlaubt, und die augenblickliche Einstellung
kann aus dem gleichnamigen Symbol ausgelesen werden. Defaultm"a"sig
ist \tty{PADDING} nur f"ur die 680x0-Familie eingeschaltet, f"ur alle
anderen werden erst nach Umschaltung Padding-Bytes eingef"ugt.
%%- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
\ttindex{PACKING}\label{SectPACKING}
{\em G"ultigkeit: 56000, AVR, TMS3203x/4x, TMS3206x, MN1610, \\
CP1600, $\mu$PD7720/7725, $\mu$PD77230}
{\tt PACKING} ist in gewisser Weise "ahnlich zu {\tt PADDING}, es arbeitet
nur gewisserma"sen anders herum: w"ahrend {\tt PADDING} die
abgelegten Daten erg"anzt, um komplette Worte und damit ein Alignment zu
erhalten, quetscht {\tt PACKING} mehrere Werte in ein einzelnes Wort.
Dies macht im Code-Segment des AVR Sinn, weil dort mit einem Spezialbefehl
({\tt LPM}) auf einzelne Bytes in den 16-Bit-Worten zugegriffen werden
kann. Ist diese Option eingeschaltet (Argument {\tt ON}), so werden immer
zwei Byte-Werte bei {\tt DATA} in ein Wort gepackt, analog zu den
einzelnen Zeichen von String-Argumenten. Der Wertebereich der
Integer-Argumente reduziert sich dann nat"urlich auf -128...+255. Ist
diese Option dagegen ausgeschaltet, (Argument {\tt OFF}), so bekommt
jedes Integer-Argument sein eigenes Wort und darf auch Werte von
-32768...+65535 annehmen.
Diese Unterscheidung betrifft nur Integer-Argumente von {\tt DATA},
Strings werden immer gepackt. Zu beachten ist weiterhin, da"s dieses
Packen nur innerhalb der Argumente eines {\tt DATA}-Befehls funktionieren
kann, wer also mehrere {\tt DATA}-Befehle hintereinander hat, f"angt sich
bei ungeraden Argumentzahlen trotzdem halbvolle W"orter ein!
%%- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
\ttindex{MAXMODE}
{\em G"ultigkeit: TLCS-900, H8}
Die Prozessoren der TLCS-900-Reihe k"onnen in 2 Betriebsarten arbeiten,
dem Minimum-und Maximum-Modus. Je nach momentaner Betriebsart gelten
f"ur den Betrieb und den Assembler etwas andere Eckwerte. Mit diesem Befehl
und den Parametern \tty{ON} oder \tty{OFF} teilt man \asname{} mit, da"s der
folgende Code im Maximum- oder Minimum-Modus abl"auft. Die momentane
Einstellung kann aus der Variablen \tty{INMAXMODE} ausgelesen werden.
Voreinstellung ist \tty{OFF}, d.h. Minimum-Modus.
Analog dazu teilt man im H8-Modus \asname{} mit diesem Befehl mit, ob
mit einem 64K- oder 16Mbyte-Adre"sraum gearbeitet wird. F"ur den
einfachen 300er ist diese Einstellung immer \tty{OFF} und kann nicht
ver"andert werden.
%%- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
\ttindex{EXTMODE}\ttindex{LWORDMODE}
{\em G"ultigkeit: Z380}
Der Z380 kann in insgesamt 4 Betriebsarten arbeiten, die sich durch
die Einstellung von 2 Flags ergeben: Das XM-Flag bestimmt, ob der
Prozessor mit einem 64 Kbyte oder 4 Gbyte gro"sen Adre"sraum arbeiten
soll und kann nur gesetzt werden (nach einem Reset steht es
Z80-kompatibel auf 0). Demgegen"uber legt das LW-Flag fest, ob
Wort-Befehle mit einer Wortl"ange von 16 oder 32 Bit arbeiten sollen.
Die Stellung dieser beiden Flags beeinflu"st Wertebereichseinschr"ankungen
von Konstanten oder Adressen, weshalb man \asname{} "uber diese beiden Befehle
deren Stellung mitteilen mu"s. Als Default nimmt \asname{} an, da"s beide
Flags auf 0 stehen, die momentane Einstellung (\tty{ON} oder \tty{OFF})
kann aus den vordefinierten Variablen \tty{INEXTMODE} bzw. \tty{INLWORDMODE}
ausgelesen werden.
%%- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
\ttindex{SRCMODE}
{\em G"ultigkeit: MCS-251}
Intel hat den Befehlssatz der 8051er beim 80C251 deutlich erweitert,
hatte aber leider nur noch einen einzigen freien Opcode f"ur diese
Befehle frei. Damit der Prozessor nicht auf alle Ewigkeit durch
einen Pr"afix behindert bleibt, hat Intel zwei Betriebsarten vorgesehen:
Den Bin"ar- und den Quellmodus. Im Bin"armodus ist der Prozessor voll
8051-kompatibel, alle erweiterten Befehle ben"otigen den noch freien
Opcode als Pr"afix. Im Quellmodus tauschen diese neuen Befehle ihre
Position in der Code-Tabelle mit den entsprechenden 8051-Instruktionen,
welche dann wiederum mit einem Pr"afix versehen werden m"ussen.
Damit \asname{} wei"s, wann er Pr"afixe setzen mu"s und wann nicht, mu"s man
ihm mit diesem Befehl mitteilen, ob der Prozessor im Quellmodus (\tty{ON})
oder Bin"armodus (\tty{OFF}) betrieben wird. Die momentane Einstellung
kann man aus der Variablen \tty{INSRCMODE} auslesen. Der Default ist
\tty{OFF}.
%%- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
\ttindex{PLAINBASE}\label{SectPLAINBASE}
{\em G"ultigkeit: 6809}
Historisch erlaubt \asname{}, bei indizierten Adressierungsausdr"ucken ein
leeres, erstes Argument wegzulassen. Ein
\begin{verbatim}
lda x
\end{verbatim}
zum Beispiel war also "aquivalent zu
\begin{verbatim}
lda ,x
\end{verbatim}
Obwohl als Feature gedacht, wurde dies jedoch gelegentlich eher als Bug
angesehen. Deshalb darf ein leeres Index-Argument nicht mehr weggelassen werden
bzw. wird mit einer Fehlermeldung "uber eine falsche Anzahl Argumente quittiert.
Falls die Funktion gew"unscht ist bzw. f"ur existierenden Code gebraucht wird,
kann sie mit einem
\begin{verbatim}
plainbase on
\end{verbatim}
wieder eingeschaltet werden. Die aktuelle Einstellung kann aus dem gleichnamigen
Symbol ausgelesen werden.
%%- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
\ttindex{ENDIAN}\ttindex{BIGENDIAN}\label{SectBIGENDIAN}
{\em G"ultigkeit: MCS-51/251, PowerPC, SC/MP, 2650, NS32000}
Bei den Prozessoren der 8051-Serie ist Intel seinen eigenen Prinzipien
untreu geworden: Der Prozessor verwendet entgegen jeglicher Tradition
eine Big-Endian-Orientierung von Mehrbytewerten! W"ahrend dies bei
den MCS-51-Prozessoren noch nicht gro"sartig auffiel, da der Prozessor
ohnehin nur 8-bittig auf Speicherzellen zugreifen konnte, man sich die
Byte-Anordnung bei eigenen Datenstrukturen also aussuchen konnte, ist
dies beim MCS-251 nicht mehr so, er kann auch ganze (Lang-)Worte aus
dem Speicher lesen und erwartet dabei das MSB zuerst. Da dies nicht der
bisherigen Arbeitsweise von \asname{} bei der Konstantenablage entspricht,
kann man nun mit diesem Befehl umschalten, ob die Befehle \tty{DB, DW, DD,
DQ} und \tty{DT} mit Big- oder Little-Endian-Orientierung arbeiten sollen.
Mit \tty{BIGENDIAN OFF} (Voreinstellung) wird wie bei "alteren \asname{}-Versionen
zuerst das niederwertigste Byte abgelegt, mit \tty{BIGENDIAN ON} wird die
MCS-251-kompatible Variante benutzt. Nat"urlich kann man diese Einstellung
beliebig oft im Code "andern; die momentane Einstellung kann aus dem
gleichnamigen Symbol ausgelesen werden.
F"ur Renesas RX ist die Endianess ebenfalls umschaltbar, aus Kompatibilit"at
zum Original-Assembler hei"st der Befehl hier jedoch \tty{ENDIAN} und
akzeptiert ein \tty{LITTLE} oder \tty{BIG} als Argument.
%%- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
\ttindex{WRAPMODE}
{\em G"ultigkeit: Atmel AVR}
Ist dieser Schalter auf {\tt ON} gesetzt, so veranla"st man \asname{} dazu,
anzunehmen, der Programmz"ahler des Prozessors habe nicht die volle, durch
die Architektur gegebene L"ange von 16 Bits, sondern nur eine L"ange, die
es gerade eben erlaubt, das interne ROM zu adressieren. Im Falle des
AT90S8515 sind dies z.B. 12 Bit, entsprechend 4 KWorten oder 8 KBytes.
Damit werden relative Spr"unge vom Anfang des ROMs zum Ende und umgekehrt
m"oglich, die bei strenger Arithmetik einen out-of-branch ergeben w"urden,
hier jedoch funktionieren, weil die "Ubertragsbits bei der
Zieladressenberechnung 'unter den Tisch' fallen. Vergewissern Sie sich
genau, ob die von Ihnen eingesetzte Prozessorvariante so arbeitet, bevor
Sie diese Option einschalten! Im Falle des oben erw"ahnten AT90S8515 ist
diese Option sogar zwingend n"otig, um "uberhaupt quer durch den ganzen
Adre"sraum springen zu k"onnen...
Defaultm"a"sig steht dieser Schalter auf {\tt OFF}, der momentane Stand
l"a"st sich aus einem gleichnamigen Symbol auslesen.
%%- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
\ttindex{PANEL}
{\em G"ultigkeit: IM61x0}
Mit diesem Schalter teilt man dem Assembler mit, ob der folgende Code
mit gesetztem oder gel"oschtem {\em Control Panel Flip-Flop} ausgef"uhrt
wird. Eine Reihe von {\tt IOT}-Instruktionen sind nur bei einer bestimmten
Stellung des Flip-Flops zul"assig. Ihre Verwendung im anderen Modus
wird vom Assembler mit einer Fehlermeldung quittiert.
Die aktuelle Einstellung kann aus dem Symbol {\tt INPANEL} gelesen werden.
%%- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
\ttindex{SEGMENT}
{\em G"ultigkeit: alle Prozessoren}
Bestimmte Mikrokontroller und Signalprozessoren kennen mehrere
Adre"sbereiche, die nicht miteinander mischbar sind und jeweils auch
verschiedene Befehle zur Ansprache ben"otigen. Um auch diese verwalten zu
k"onnen, stellt der Assembler mehrere Programmz"ahler zur Verf"ugung,
zwischen denen mit dem
\tty{SEGMENT}-Befehl hin-und hergeschaltet werden kann. Dies erlaubt es,
sowohl in mit \tty{INCLUDE} eingebundenen Unterprogrammen als auch im
Hauptprogramm ben"otigte Daten an der Stelle zu definieren, an denen
sie benutzt werden. Im einzelnen werden folgende Segmente mit folgenden
Namen verwaltet:
\begin{itemize}
\item{\tty{CODE}: Programcode;}
\item{\tty{DATA}: direkt adressierbare Daten (dazu rechnen auch SFRs);}
\item{\tty{XDATA}: im extern angeschlossenen RAM liegende Daten oder
X-Adre"sraum beim DSP56xxx oder ROM-Daten beim $\mu$PD772x;}
\item{\tty{YDATA}: Y-Adre"sraum beim DSP56xxx;}
\item{\tty{IDATA}: indirekt adressierbare (interne) Daten;}
\item{\tty{BITDATA}: der Teil des 8051-internen RAMs, der bitweise
adressierbar ist;}
\item{\tty{IO}: I/O-Adre"sbereich;}
\item{\tty{REG}: Registerbank des ST9;}
\item{\tty{ROMDATA}: Konstanten-ROM der NEC-Signalprozessoren;}
\item{\tty{EEDATA}: eingebautes EEPROM.}
\end{itemize}
Zu Adre"sbereich und Initialwerten der Segmente siehe Abschnitt \ref{SectORG}.
(\tty{ORG}). Je nach Prozessorfamilie sind auch nicht alle Segmenttypen
erlaubt.
Das Bitsegment wird so verwaltet, als ob es ein Bytesegment w"are,
d.h. die Adressen inkrementieren um 1 pro Bit.
Labels, die in einem Segment eines bestimmten Typs definiert werden,
erhalten diesen Typ als Attribut. Damit hat der Assembler eine
begrenzte Pr"ufm"oglichkeit, ob mit den falschen Befehlen auf Symbole
in einem Segment zugegriffen wird. In solchen F"allen wird der
Assembler eine Warnung ausgeben.
Beispiel:
\begin{verbatim}
CPU 8051 ; MCS-51-Code
SEGMENT code ; Testcodeblock
SETB flag ; keine Warnung
SETB var ; Warnung : falsches Segment
SEGMENT data
var DB ?
SEGMENT bitdata
flag DB ?
\end{verbatim}
%%- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
\ttindex{PHASE}\ttindex{DEPHASE}
{\em G"ultigkeit: alle Prozessoren}
In manchen Anwendungen (speziell Z80-Systeme) mu"s Code vor der
Benutzung in einen anderen Adre"sbereich verschoben werden. Da der
Assembler davon aber nichts wei"s, w"urde er alle Labels in dem zu
verschiebenden Teil auf die Ladeadressen ausrichten. Der Programmierer
m"u"ste Spr"unge innerhalb dieses Bereiches entweder lageunabh"angig
kodieren oder die Verschiebung bei jedem Symbol ,,zu Fu"s'' addieren.
Ersteres ist bei manchen Prozessoren gar nicht m"oglich, letzteres sehr
fehleranf"allig.
Mit dem Befehlen \tty{PHASE} und \tty{DEPHASE} ist es m"oglich, dem
Assembler mitzuteilen, auf welcher Adresse der Code im Zielsystem
effektiv ablaufen wird:
\begin{verbatim}
PHASE <Adresse>
\end{verbatim}
informiert den Assembler davon, da"s der folgende Code auf der
spezifizierten Adresse ablaufen soll. Der Assembler berechnet
daraufhin die Differenz zum echten Programmz"ahler und addiert diese
Differenz bei folgenden Operationen dazu:
\begin{itemize}
\item{Adre"sangabe im Listing}
\item{Ablage von Labelwerten}
\item{Programmz"ahlerreferenzen in relativen Spr"ungen und
Adre"sausdr"ucken}
\item{Abfrage des Programmz"ahlers mit den Symbolen \verb!*! bzw. \verb!$!}
\end{itemize}
Diese ,,Verschiebung'' wird mit dem Befehl
\begin{verbatim}
DEPHASE
\end{verbatim}
wieder auf den vor der zugeh"origen \tty{PHASE}-Anweisung zur"uck ge"andert.
\tty{PHASE} und \tty{DEPHASE} k"onnen also auf diese Weise geschachtelt
verwendet werden.
Obwohl dieses Befehlspaar vornehmlich in Codesegmenten Sinn macht,
verwaltet der Assembler f"ur alle definierten Segmente Phasenwerte.
%%- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
\ttindex{SAVE}\ttindex{RESTORE}
\ttindex{.SAVE}\ttindex{.RESTORE}
\ttindex{SAVEENV}\ttindex{RESTOREENV}
{\em G"ultigkeit: alle Prozessoren}
Mit dem Befehl \tty{SAVE} legt der Assembler den Inhalt folgender
Variablen auf einen internen Stapel:
\begin{itemize}
\item{momentan gew"ahlter Prozessortyp (mit \tty{CPU} gesetzt);}
\item{momentan aktiver Speicherbereich (mit \tty{SEGMENT} gesetzt);}
\item{Flag, ob Listing ein- oder ausgeschaltet ist (mit \tty{LISTING}
gesetzt);}
\item{Flags, zu welchem Teil Expansionen folgender Makos im Listing
ausgegeben werden sollen (mit \tty{MACEXP\_DFT/MACEXP\_OVR}
gesetzt).}
\item{momentan aktive Zeichen"ubersetzungstabelle (mit \tty{CODEPAGE}
gesetzt).}
\end{itemize}
Mit dem Gegenst"uck \tty{RESTORE} wird entsprechend der zuletzt
gesicherte Zustand von diesem Stapel wieder heruntergeladen. Diese beiden
Befehle sind in erster Linie f"ur Include-Dateien definiert worden, um
in diesen Dateien die obigen Variablen beliebig ver"andern zu k"onnen,
ohne ihren originalen Inhalt zu verlieren. So kann es z.B. sinnvoll sein,
in Include-Dateien mit eigenen, ausgetesteten Unterprogrammen die
Listingerzeugung auszuschalten:
\begin{verbatim}
SAVE ; alten Zustand retten
LISTING OFF ; Papier sparen
.. ; der eigentliche Code
RESTORE ; wiederherstellen
\end{verbatim}
Gegen"uber einem einfachen \tty{LISTING OFF..ON}-P"archen wird hier
auch dann der korrekte Zustand wieder hergestellt, wenn die Listingerzeugung
bereits vorher ausgeschaltet war.
Der Assembler "uberpr"uft, ob die Zahl von \tty{SAVE}-und \tty{RESTORE}-Befehlen
"ubereinstimmt und liefert in folgenden F"allen Fehlermeldungen:
\begin{itemize}
\item{\tty{RESTORE} und der interne Stapel ist leer;}
\item{nach Ende eines Passes ist der Stapel nicht leer.}
\end{itemize}
Falls das aktuell benutzte Target bereits einen Maschinenbefehl namens \tty{SAVE}
bzw. \tty{RESTORE} hat, kann die Funktionalit"at "uber \tty{SAVEENV} bzw.
\tty{RESTOREENV} erreicht werden. Wahlweise ist es auch immer m"oglich, explizit
die Pseudobefehle durch voran gestellte Punkte (\tty{.SAVE} bzw. \tty{.RESTORE})
aufzurufen.
%%- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
\ttindex{ASSUME}
%%. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
{\em G"ultigkeit: diverse}
Mit diesem Befehl kann man \asname{} den aktuellen Stand bestimmter Register
mitteilen, deren Inhalt sich nicht mit einem einfachen \tty{ON} oder
\tty{OFF} beschreiben l"a"st. Typischerweise sind dies Register, die die
Adressierungseinheiten beeinflussen und deren Werte \asname{} wissen mu"s, um
korrekte Adressierungen zu erzeugen. Wichtig ist, da"s man \asname{} mit ASSUME
diese Werte nur mitteilt, es wird {\em kein} Maschinencode erzeugt, der
diese Werte in die entsprechenden Register l"adt!
Ein mit \tty{ASSUME} definierter Wert l"a"st sich mit der
eingebauten Funktion \tty{ASSUMEDVAL} wieder abfragen oder in
Ausdr"ucke einbauen. Dies gilt f"ur alle im folgenden gelisteten
Architekturen mit Ausnahme des 8086.
%%. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Der 65CE02 besitzt ein Register 'B', mit dem die 'Base-Page' festgelegt wird.
Im Gegensatz zum 'einfachen' 6502 l"a"st sich damit die Speicherseite, die
mit kurzen (8-bittigen) Adressen ansprechbar ist, frei im 64K-Adre'sraum hin-
und herschieben. Nach einem Reset steht dieses Register auf Null, der 65CE02
verh"alt sich also wie sein Vorbild. Dies ist auch die Default-Annahme des
Assemblers. Mittels eines \tty{ASSUME B:xx} kann man ihm den aktuellen Wert
mitteilen, und f"ur Adressen in dieser Seite werden dann automatisch kurze
Adressierungsarten benutzt.
%%. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Im Gegensatz zu seinen ,,Vorg"angern'' wie 6800 und 6502 kann beim
6809 die Lage der direct page, d.h. des Adressbereiches, der mit ein
Byte langen Adressen erreichbar ist, frei bestimmt werden. Dazu dient
das sog. ,,Direct Page Register'' (\tty{DPR}), das die Seitennummer
festlegt. Ihm mu"s man mittels \tty{ASSUME} einen passenden Wert
zuweisen, wenn man einen anderen Wert als die Vorgabe von 0 in DPR
schreibt, sonst werden Adressen falscher L"ange erzeugt...
%%. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Auch beim HC11 kamen die Entwickler letzen Endes nicht um eine Form von
Banking herum, um mit 16 Adre"sleitungen mehr als 64 Kbyte anzusprechen. Die
Register {\tt MMSIZ}, {\tt MMWBR}, {\tt MM1CR} und {\tt MM2CR} legen fest,
ob und wie die beiden zus"atzlichen 512K-Bereiche in den Adre"sraum der CPU
eingeblendet werden sollen. Initial nimmt \asname{} den Reset-Zustand
dieser Register an, d.h. alle mit \$00 belegt und das Windowing ist
abgeschaltet.
Weiterhin kann man die Werte der Register {\tt CONFIG}, {\tt INIT} und {\tt INIT2}
festlegen. Aus diesen kann der Assembler die Lage der CPU-internen Register sowie
des CPU-internen RAM/EEPROM bestimmen. Deren Mapping hat eine h"ohere Priorit"at
als die per Windowing eingeblendeten Speicherbereiche.
%%. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Wie die Variante ohne anh"angendes 'X' kennt auch der HC12X eine kurze
direkte Adressierungsart, die hier jedoch auch andere Adre"sbereiche als
die ersten 256 Byte erreichen kann. "Uber das {\tt DIRECT}-Register kann
die 256-Byte-Seite vorgegeben werden, die mit dieser kurzen
Adressierungsart angesprochen wird. Mittels {\tt ASSUME} wird \asname{} der
momentane Stand dieses Registers mitgeteilt, so da"s bei absoluten
Adressen automatisch die effizienteste Adressierungsart gew"ahlt werden
kann. Default ist 0, was auch dem Reset-Zustand entspricht.
Um mit seinen nur 16 Bit breiten Adre"soperanden einen 1 Mbyte gro"sen
Adre"sraum ansprechen zu k"onnen, bedient sich der 68HC16 einer Reihe
von Bank-Registern, die die fehlenden oberen vier Adre"sbits nachliefern.
Davon ist das \tty{EK}-Register f"ur absolute Datenzugriffe (nicht
Spr"unge!) zust"andig. \asname{} "uberpr"uft bei jeder absoluten Adressierung,
ob die oberen vier Bits der Adresse mit dem "uber \tty{ASSUME}
spezifizierten Wert "ubereinstimmen. Differieren die Werte, gibt \asname{} eine
Warnung aus. Der Vorgabewert f"ur \tty{EK} ist 0.
%%. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Im Maximum-Modus wird der erweiterte Adre"sraum dieser Prozessorreihe
durch eine Reihe von Bank-Registern adressiert. Diese tragen die
Namen DP (Register 0..3, absolute Adressen), EP (Register 4/5) und
TP (Stack). Den momentanen Wert von DP ben"otigt \asname{}, um zu "uberpr"ufen,
ob absolute Adressen in der momentan adressierbaren Bank liegen;
die beiden anderen Register werden nur f"ur indirekte Adressierungen
benutzt und entziehen sich daher der Kontrolle; ob man ihre Werte
angibt oder nicht, ist daher Geschmackssache. Wichtig ist dagegen
wieder das BR-Register, das angibt, auf welchen 256-Byte-Bereich
mit kurzen Adressen zugegriffen werden kann. Allen Registern ist
gemeinsam, da"s \asname{} {\em keine} Initialwerte f"ur sie annimmt, da sie nach
einem Prozessor-Reset undefiniert sind; wer absolut adressieren
will, mu"s daher auf jeden Fall DR und DP belegen!
%%. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Die Mikrokontroller dieser Reihe kennen f"ur den \tty{JSR}-Befehl eine
besondere Adressierungsart ,,special page'', mit deren Hilfe man Spr"unge
in die oberste Seite des internen ROMs k"urzer kodieren kann. Diese
ist nat"urlich vom jeweiligen Chip abh"angig, und es gibt mehr Chips,
als es mit dem \tty{CPU}-Befehl sinnvoll w"are, zu kodieren...also mu"s
\tty{ASSUME} herhalten, um die Lage dieser Seite vorzugeben, z.B.
\begin{verbatim}
ASSUME SP:$1f ,
\end{verbatim}
falls das interne ROM 8K gro"s ist.
%%. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Diese Prozessoren beinhalten eine Reihe von Registern, deren Inhalt \asname{}
kennen mu"s, um den korrekten Code zu erzeugen. Es handelt sich um folgende
Register:
\begin{center}\begin{tabular}{|l|l|l|l|}
Name & Bedeutung & Wertebereich & Default\\
DT/DBR & Datenbank & 0-\$ff & 0 \\
PG/PBR & Code-Bank & 0-\$ff & 0 \\
DPR & direkt adr. Seite & 0-\$ffff & 0 \\
X & Indexregisterbreite & 0 oder 1 & 0 \\
M & Akkumulatorbreite & 0 oder 1 & 0 \\
\end{tabular}\end{center}
Um mich nicht in endlose Wiederholungen zu ergehen, verweise ich f"ur die
Benutzung dieser Werte auf Kapitel \ref{MELPS7700Spec}. Die Handhabung
erfolgt ansonsten genauso wie beim 8086, d.h. es k"onnen auch hier mehrere
Werte auf einmal gesetzt werden und es wird \bb{kein} Code erzeugt, der
die Register mit den Werten besetzt. Dies bleibt wieder einzig und allein
dem Programmierer "uberlassen!
%%. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Alle Prozessoren der MCS-96-Familie besitzen ab dem 80196 ein Register \tty{WSR},
mit dessen Hilfe Speicherbereiche aus dem erweiterten internen RAM
oder dem SFR-Bereich in Bereiche des Registerfiles eingeblendet werden
und so mit kurzen Adressen angesprochen werden k"onnen. Teilt man \asname{}
mit Hilfe des \tty{ASSUME}-Befehls mit, welchen Wert das WSR-Register
hat, so stellt er bei absoluten Adressen automatisch fest, ob sie
durch das Windowing mit 1-Byte-Adressen erreicht werden k"onnen;
umgekehrt werden auch f"ur durch das Windowing "uberdeckte Register
automatisch lange Adressen erzeugt. Der 80296 besitzt ein zus"atzliches,
zweites Register \tty{WSR1}, um zwei unterschiedliche Speicherbereiche
gleichzeitig in das Registerfile einblenden zu k"onnen. Sollte
es m"oglich sein, eine Speicherzelle "uber beide Bereiche zu adressieren,
so w"ahlt \asname{} immer den Weg "uber \tty{WSR}!
Bei indirekter Adressierung k"onnen Displacements wahlweise kurz (8 Bit,
-128 bis +127) oder lang (16 Bit) sein. Der Assembler w"ahlt automatisch
anhand des Displacements die k"urzestm"ogliche Kodierung. Es ist aber m"oglich,
durch ein vorangestelltes Gr"o"ser-Zeichen (\verb!>!) eine 16-Bit-Kodierung
des Displacements zu erzwingen. Gleiches gilt f"ur absolute Adressen im
Bereich 0ff80h...0ffffh, die mit einem kurzen Offset relativ zum "Nullregister"
adressiert werden k"onnen.
%%. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Der 8086 kann Daten aus allen Segmenten in einem Befehl adressieren,
ben"otigt jedoch sog. ,,Segment-Pr"afixe'', wenn ein anderes Segmentregister
als DS verwendet werden soll. Zus"atzlich kann es sein, da"s das
DS-Register auf ein anderes Segment verstellt ist, um z.B. "uber l"angere
Strecken nur Daten im Codesegment zu adressieren. Da \asname{} aber keine
Sinnanalyse des Codes vornimmt, mu"s ihm "uber diesen Befehl mitgeteilt
werden, auf welche Segmente die Segmentregister momentan zeigen, z.B.
\begin{verbatim}
ASSUME CS:CODE, DS:DATA .
\end{verbatim}
Allen vier Segmenten des 8086 (SS,DS,CS,ES) k"onnen auf diese Weise Annahmen
zugewiesen werden. Dieser Befehl erzeugt jedoch \bb{keinen} Code, um
die Werte auch wirklich in die Segmentregister zu laden, dies mu"s vom
Programm getan werden.
Die Benutzung diese Befehls hat zum einen die Folge, da"s \asname{} bei
sporadischen Zugriffen ins Codesegment automatisch Pr"afixe voranstellen
kann, andererseits da"s man \asname{} mitteilen kann, da"s das DS-Register verstellt
wurde und man sich im folgenden explizite \tty{CS:}-Anweisungen sparen
kann.
G"ultige Argumente hinter dem Doppelpunkt sind \tty{CODE, DATA} und
\tty{NOTHING}. Letzterer Wert dient dazu, \asname{} mitzuteilen, da"s das
Segmentregister keinen f"ur \asname{} verwendbaren Wert enth"alt.
Vorinitialisiert sind folgende \tty{ASSUME}s :
\begin{verbatim}
CS:CODE, DS:DATA, ES:NOTHING, SS:NOTHING
\end{verbatim}
%%. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Der Z180 besitzt eine eingebaute MMU, die den ,,logischen Adre"sraum'' des
CPU-Kerns von 64 KByte auf einen physischen Adre"sraum von 512 KByte "ubersetzt.
Das genaue Mapping wird durch die drei Register {\tt CBAR}, {\tt CBR} und {\tt BBR}
gesteuert. Im Gegensatz zum 68HC11K4 nimmt der Assembler aktuell keine
automatischen Umrechnungen von physischen auf logische Adressen vor, sondern
h"alt lediglich intern Umrechnungstabellen vor. Es ist aber m"oglich, diese
unter Benutzung der {\tt phys2cpu()}-Funktion zu benutzen.
%%. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Die XA-Familie besitzt einen Datenadre"sraum von 16 Mbyte, ein Proze"s
kann jedoch nur immer innerhalb einer 64K-Seite adressieren, die
durch das DS-Register vorgegeben wird. \asname{} mu"s man den momentanen
Wert dieses Registers vorgeben, damit er Zugriffe auf absolute
Adressen "uberpr"ufen kann.
%%. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Die Prozessoren der 29K-Familie besitzen ein Register \tty{RBP}, mit dessen
Hilfe B"anke von 16 Registern vor der Benutzung im User-Modus gesch"utzt
werden k"onnen. Dazu kann man ein entsprechendes Bit in diesem Register
setzen. Mit \tty{ASSUME} kann man \asname{} nun mitteilen, welchen Wert RBP
gerade hat. Auf diese Weise kann \asname{} warnen, falls versucht wird, im
User-Modus auf gesch"utzte Register zuzugreifen.
%%. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Obwohl keines der Register im 80C166/167 breiter als 16 Bit ist, besitzt
dieser Prozessor 18/24 Adre"sleitungen, kann also bis zu 256 Kbyte/16 Mbyte
adressieren. Um diesen Widerspruch unter einen Hut zu bekommen, verwendet
er nicht die von Intel her bekannte (...und ber"uchtigte) Segmentierung oder
hat unflexible Bankregister...nein, er macht Paging! Dazu wird der ,,logische''
Adre"sraum von 64 Kbyte in 4 Seiten zu 16 Kbyte eingeteilt, und f"ur jede
Seite existiert ein Seitenregister (bezeichnet als \tty{DPP0...DPP3}), das
bestimmt, welche der physikalischen 16/1024 Seiten dort eingeblendet wird. \asname{} versucht
nun, den Adre"sraum grunds"atzlich mit 256 Kbyte/16 Mbyte aus der Sicht des
Programmierers zu verwalten, d.h. bei absoluten Zugriffen ermittelt \asname{} die
physikalische Seite und schaut in der mit \tty{ASSUME} eingestellten
Seitenverteilung nach, wie die Bits 14 und 15 der logischen Adresse gesetzt
werden m"ussen. Pa"st kein Seitenregister, so wird eine Warnung ausgegeben.
Defaultm"a"sig nimmt \asname{} an, da"s die vier Register linear die ersten 64 Kbyte
abbilden, etwa in der folgenden Form:
\begin{verbatim}
ASSUME DPP0:0,DPP1:1,DPP2:2,DPP3:3
\end{verbatim}
Der 80C167 kennt noch einige Befehle, die die Seitenregister in ihrer
Funktion "ubersteuern k"onnen. Wie diese Befehle die Adre"sgenerierung
beeinflussen, ist im Kapitel mit den prozessorspezifischen Hinweisen
beschrieben.
Einige Maschineninstruktionen kennen ein verk"urzte Kodierung, wenn das
Argument in einem bestimmten Wertebereich liegt:
\begin{itemize}
\item{\verb!MOV Rn,#<0..15>!}
\item{\verb!ADD/ADDC/SUB/SUBC/CMP/XOR/AND/OR Rn, #<0..7>!}
\item{\verb!LOOP Rn,#<0..15>!}
\end{itemize}
Der Assembler verwendet im Default automatisch die k"urzere Kodierung
wenn m"oglich. Falls man die l"angere erzwingen m"ochte, schreibt
man analog zum 65xx/68xx ein Gr"o"serzeichen vor den Operanden (hinter
das Doppelkreuz!). Umgekehrt kann man auch ein Kleinerzeichen schreiben,
wenn man die kurze Kodierung erzwingen will. Falls der Operand nicht
im erlaubten Wertebereich liegt, gibt es eine Fehlermeldung. Singem"a"s
das gleiche gilt f"ur Spr"unge, die mit kurzem Displacement oder langem,
absolutem Argument kodiert werden k"onnen.
%%. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Der von der Architektur her vorgegebene Datenadre"sraum dieser
Prozessoren (egal ob man direkt oder "uber das HL-Register adressiert)
betr"agt lediglich 256 Nibbles. Da die ,,besseren'' Familienmitglieder
aber bis zu 1024 Nibbles RAM on chip haben, war Toshiba gezwungen, einen
Bankingmechanismus "uber das DMB-Register einzuf"uhren. \asname{} verwaltet
das Datensegment als einen durchgehenden Adre"sraum und pr"uft bei jeder
direkten Adressierung, ob die Adresse in der momentan aktiven Bank
liegt. Die von \asname{} momentan angenommene Bank kann mittels
\begin{verbatim}
ASSUME DMB:<0..3>
\end{verbatim}
festgelegt werden. Der Default ist 0.
%%. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Der Prozessor verf"ugt "uber einen Eingangs-Pin namens {\tt BPS}, mit dem man
w"ahlen kann, welcher Adre"sbereich direkt adressierbar sein soll: entweder
die untersten 256 Worte des Speichers, oder die jeweils obersten und untersten
128 Worte. Der Default is ersteres, mit einem {\tt ASSUME BPS:1} schaltet man
auf die zweite Variante um.
%%. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Die Mikrokontroller der ST6-Reihe sind in der Lage, einen Teil (64 Byte)
des Codebereiches in den Datenbereich einzublenden, z.B. um Konstanten aus
dem ROM zu laden. Dies bedeutet aber auch, da"s zu einem Zeitpunkt immer
nur ein Teil des ROMs adressiert werden kann. Welcher Teil dies ist, wird
durch ein bestimmtes Register bestimmt. Dem Inhalt dieses Registers kann
\asname{} zwar nicht direkt kontrollieren, man kann ihm aber mit diesem Befehl
mitteilen, wenn man dem Register einen neuen Wert zugewiesen hat. \asname{} kann
dann pr"ufen und ggfs. warnen, falls auf Adressen im Codesegment
zugegriffen wird, die nicht im ,,angek"undigten'' Fenster liegt.
Hat die Variable \tty{VARI} z.B. den Wert 456h, so setzt
\begin{verbatim}
ASSUME ROMBASE:VARI>>6
\end{verbatim}
die \asname{}-interne Variable auf 11h, und ein Zugriff auf \tty{VARI} erzeugt einen
Zugriff auf die Adresse 56h im Datensegment.
Anstelle eines Symbols kann auch schlicht \tty{NOTHING} angegeben
werden, z.B. wenn das Bank-Register tempor"ar als Speicherzelle benutzt
wird. Dieser Wert ist auch die Voreinstellung.
Der Programmz"ahler dieser Mikrokontroller ist lediglich 12 Bit breit. Das
bedeutet f"ur Varianten mit mehr als 4 KByte Programmspeicher, da"s man sich
eine Art von Banking einfallen lassen mu"ste. Dazu werden Adre"sraum und
Programmspeicher in 2 KByte-Seite eingeteilt. Seite 1 des Adre"sraumes
greift immer auf Seite 1 des Programmspeichers zu. "Uber das bei diesen
Varianten vorhandene \tty{PRPR}-Register kann der Programmierer bestimmen,
welche Seite des Programmspeichers "uber die Adressen 000h bis 7ffh
zugegriffen wird. \asname{} betrachtet den Adre"sraum in erster N"aherung als
linear und von der Gr"o"se des Programmspeichers. Erfolgt ein Sprung von
Seite 1 aus auf eine Adresse au"serhalb dieser Seite, wird gepr"uft, ob deren
Adresse mit dem aktuell angenommenen Wert des \tty{PRPR}-Registers identisch
ist. Erfolgt ein Sprung von einer anderen Seite aus auf eine Adresse au"serhalb
Seite 1, wird gepr"uft, ob die Zieladresse innerhalb der gleichen Seite
liegt. {\bf WICHTIG}: Da der Programmz"ahler nur 12 Bit breit ist, ist
es nicht m"oglich, ohne einen Umweg "uber Seite 1 von einer Seite in eine
andere zu springen - Mit einem Umsetzen des \tty{PRPR}-Registers au"serhalb
von Seite 1 w"urde man sich seinen eigenen Code unter den F"u"sen wegziehen.
%%. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Die ST9-Familie verwendet zur Adressierung von Code- und Datenbereich
exakt die gleichen Befehle. Welcher Adre"sraum dabei jeweils
angesprochen wird, h"angt vom Stand des DP-Flags im Flag-Register ab.
Damit \asname{} bei absoluten Zugriffen "uberpr"ufen kann, ob man mit Symbolen
aus dem korrekten Adre"sraum arbeitet (das funktioniert nat"urlich {\em nur}
bei absoluten Zugriffen!), mu"s man ihm per \tty{ASSUME} mitteilen, ob das
DP-Flag momentan auf 0 (Code) oder 1 (Daten) steht. Der Initialwert
dieser Annahme ist 0.
%%. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Diese Prozessoren besitzen ein Register (V), mit dessen Hilfe die
,,Zeropage'', d.h. die Lage der mit nur einem Byte adressierbaren
Speicherzellen sich in Seitengrenzen im Speicher frei verschieben l"a"st.
Da man aber aus Bequemlichkeitsgr"unden nicht mit Ausdr"ucken wie
\begin{verbatim}
inrw Lo(Zaehler)
\end{verbatim}
arbeiten will, "ubernimmt \asname{} diese Arbeit, allerdings nur unter der
Voraussetzung, da"s man ihm "uber einen \tty{ASSUME}-Befehl den
Inhalt des V-Registers mitteilt. Wird ein Befehl mit Kurzadressierung
benutzt, so wird "uberpr"uft, ob die obere H"alfte des Adre"sausdrucks
mit dem angenommenen Inhalt "ubereinstimmt. Stimmt sie nicht, so erfolgt
eine Warnung.
%%. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
78K2 ist eine 8/16-Bit-Architektur, die nachtr"aglich durch Banking auf
einen (Daten-)Adre"sraum von einem MByte erweitert wurde. Das Banking
wird mit den Registern PM6 (Normalfall) bzw. P6 (alternativer Fall mit
vorangestelltem \verb!&!) realisiert, die die fehlenden oberen vier Bits
nachliefern. Zumindest bei absoluten Adressen kann \asname{} "uberpr"ufen, ob
die gerade angesprochene, lineare 20-bittige Adresse innerhalb des
gegebenen 64K-Fensters liegt.
%%. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Prozessoren mit 78K3-Kern besitzen Registerb"anke mit insgesamt 16 Registern,
die man "uber ihre Nummern ansprechen kann (\tty{R0} bis \tty{R15}) oder ihre symbolischen
Namen (\tty{X=R0, A=R1, C=R2, B=R3, VPL=R8, VPH=R9, UPL=R10, UPH=R11, E=R12,
D=R13, L=R14, H=R15}). Der Prozessorkern besitzt ein Register-Auswahlbit
(\tty{RSS}), mit dem man das Mapping von A/X und B/C von R0..R3 auf R4..R7
umschaltet. Dies ist in erste Linie f"ur Befehle wichtig, die implizit eines
dieser Register benutzen (d.h. bei denen die Registernummer nicht im Maschinenbefehl
kodiert ist). Man kann dem Assembler aber auch "uber ein
\begin{verbatim}
assume rss:1
\end{verbatim}
mitteilen, da"s die folgenden Befehle mit diesem ge"anderten Mapping arbeiten. Der
Assembler wird f"ur Befehle, in denen die Registernummer explizit kodiert ist, dann
auch die alternativen Registernummern einsetzen. Umgekehrt wird dann z.B. auch
\tty{R5} statt \tty{R1} im Quellcode wie \tty{A} behandelt.
%%. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
78K4 war als 'Upgrade-Pfad' vom 78K3 konzipiert, deshalb besitzt
dessen Prozessorkern auch ein RSS-Bit, mit dem man das Mapping
der Register AX und BC umschalten kann (auch wenn NEC von dessen
Verwendung in neuem Code abr"at).
Neben vielen neuen Befehlen und Adressierungsarten ist die
wesentliche Erweiterung der gr"o"sere Adre"raum von 16 MByte, von
dem allerdings nur das erste MByte f"ur Programmcode genutzt
werden kann. Das CPU-interne RAM sowie die Special Function
Register k"onnen wahlweise am oberen Ende des ersten MByte oder
der ersten 64 KByte Seite liegen. Dies teilt man dem Prozessor
durch den \tty{LOCATION}-Befehl mit, der als Argument wahlweise
eine 0 oder 15 akzeptiert. Parallel damit schaltet der Prozessor
auch die Adre"sbereiche um, die mit kurzen (8-Bit) Adressen
erreicht werden k"onnen. Parallel dazu mu"s man dem Assembler
mittels \tty{ASSUME LOCATION:..} ebenfalls dieser Wert mitgeteilt
werden, damit er kurze Adressen in den dazu passenden Bereichen
erzeugt. Der Assembler nimmt f"ur LOCATION einen Default von Null
an.
%%. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Da alle Instruktionsworte dieser Prozessorfamilie nur 32 Bit lang
sind, und von diesen 32 Bit nur 16 Bit f"ur absolute Adressen vorgesehen
wurden, m"ussen die fehlenden oberen 8/16 Bit aus dem DP-Register
erg"anzt werden. Bei Adressierungen kann man aber trotzdem die volle
24/32-Bit-Adresse angeben, \asname{} pr"uft dann, ob die oberen 8/16 Bit mit dem
angenommenen Inhalt von DP "ubereinstimmen. Gegen"uber dem \tty{LDP}-Befehl
weicht \tty{ASSUME} darin ab, da"s man hier nicht eine beliebige Adresse
aus der Speicherbank angeben kann, das Herausziehen der oberen Bits
mu"s man also ,,zu Fu"s'' machen, z.B. so:
\begin{verbatim}
ldp @adr
assume dp:adr>>16
.
.
.
ldi @adr,r2
\end{verbatim}
%%. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Da selbst mit Hilfe von Doppelregistern (8 Bit) nicht der komplette
Adre"sraum von 12 Bit zu erreichen ist, mu"ste NEC (wie andere auch...)
auf Banking zur"uck greifen: Die oberen 4 Adre"sbits werden aus dem
\tty{MBS}-Register geholt (welchem demzufolge mit \tty{ASSUME} Werte
zwischen 0 und 15 zugeordnet werden k"onnen), das aber nur beachtet
wird, falls das \tty{MBE}-Flag auf 1 gesetzt wurde. Steht es (wie
die Vorgabe ist) auf 0, so kann man die obersten und untersten 128
Nibbles des Adre"sraumes ohne Bankumschaltung erreichen. Da der 75402
weder \tty{MBE}-Flag noch \tty{MBS}-Register kennt, ist f"ur ihn der
\tty{ASSUME}-Befehl nicht definiert; Die Initialwerte von \tty{MBE} und
\tty{MBS} lassen sich daher nicht "andern.
%%. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Wie viele andere Mikrokontroller auch, leidet diese Familie etwas unter
der Knauserei seiner Entwickler: einem 24 Bit breiten Adre"sraum stehen 16
Bit breite Adre"sregister etwas unterbemittelt gegen"uber. Also mu"sten
wieder mal Bank-Register her. Im einzelnen sind dies PCB f"ur den
Programmcode, DTB f"ur alle Datenzugriffe, ADB f"ur indirekte Zugriffe
"uber RW2/RW6 und SSB/USB f"ur die Stacks. Sie k"onnen alle Werte
zwischen 0 und 255 annehmen. Defaultm"a"sig stehen alle Annahmen von \asname{}
auf 0, mit Ausnahme von 0ffh f"ur PCB.
Des weiteren existiert das DPR-Register, das angibt, welche Seite
innerhalb der durch DTB gegebenen 64K-Bank mit 8-Bit-Adressen erreicht
werden kann. Der Default f"ur DPR ist 1, zusammen mit dem Default f"ur
DTB ergibt dies also eine Default-Seite bei 0001xxh.
%%. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Beim MN1613 wurde eine Architektur mit 16-Bit-Adressen nachtr"aglich erweitert,
Dies wird durch einen Satz vier Bit breiter ,,Segment-Register'' (CSBR, SSBR, TSR0
und TSR1) erreicht, deren Wert (um 14 Bit nach links geschoben) zu den 16-Bit-
Adressen hinzu addiert wird. Ein Proze"s kann auf diese Weise immer ein 64 KWorte
gro"ses Fenster im 256 KWorte gro"sen Adre"sraum adressieren. Der Assembler
benutzt die per \tty{ASSUME} mitgeteilten Werte, um zu warnen, wenn eine absolute
Adresse innerhalb des 256K-Adre"sraums mit den aktuellen Werten nicht adressierbar
ist, und rechnet ansonsten den korrekten 16-bittigen Offset aus. Bei indirekter
Adressierung ist so eine Pr"ufung (naturgem"a"s) nicht m"oglich.
%%. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Diese Mikroprozessoren implementieren den Befehlssatz einer PDP/8 und unterst"utzen
grunds"atzlich einen Adre"sraum von 4 Kiloworten. Durch Banking kann dieser
auf acht ,,Felder'' von 4 Kiloworten erweitert werden. Adressierung von Daten
und Spr"unge sind prinzipiell nur im gleichen Feld m"oglich, mit einer Ausnahme:
"uber das IB-Register sind Spr"unge in ein anderes 4K-Feld m"oglich. Dieses gibt
die oberen Bits der insgesamt 15 Bit langen Zieladresse vor, falls IB per \tty{ASSUME}
auf einen Wert ungleich \tty{NOTHING} gesetzt ist.
%%- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
\ttindex{CKPT}
{\em G"ultigkeit: TI990/12}
Typ 12-Instruktionen erfordern f"ur ihre Ausf"uhrung ein sogenanntes {\em Checkpoint
Register}. Dieses Register kann entweder explizit als viertes Argument angegeben
werden, oder es wird mit dieser Anweisung ein Default f"ur allen folgenden Code
festgelegt. Wenn weder eine \tty{CKPT}-Anweisung noch ein explizites Register
angegeben wurde, wird eine Fehlermeldung ausgegeben. Der Default von keinem
Default-Register kann wiederhergestellt werden, indem man die \tty{CKPT}-Anweisung
mit {\tt NOTHING} als Argument aufruft.
%%- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
\ttindex{EMULATED}
{\em G"ultigkeit: 29K}
AMD hat die Ausnahmebehandlung f"ur undefinierte Befehle bei der
29000-Serie so definiert, da"s f"ur jeden einzelnen Befehl ein
Exception-Vektor zur Verf"ugung steht. Dies legt es nahe, durch
gezielte Software-Emulationen den Befehlssatz eines kleineren
Mitgliedes dieser Familie zu erweitern. Damit nun aber \asname{} diese
zus"atzlichen Befehle nicht als Fehler anmeckert, erlaubt es der
\tty{EMULATED}-Befehl, \asname{} mitzuteilen, da"s bestimmte Befehle doch
erlaubt sind. Die Pr"ufung, ob der momentan gesetzte Prozessor
diesen Befehl beherrscht, wird dann "ubergangen. Hat man z.B. f"ur
einen Prozessor ohne Gleitkommaeinheit ein Modul geschrieben, das
aber nur mit 32-Bit-IEEE-Zahlen umgehen kann, so schreibt man
\begin{verbatim}
EMULATED FADD,FSUB,FMUL,FDIV
EMULATED FEQ,FGE,FGT,SQRT,CLASS
\end{verbatim}
{\tt BRANCHEXT} mit \tty{ON} oder \tty{OFF} als Argument legt fest, ob \asname{}
kurze, nur mit einem 8-Bit-Displacement verf"ugbare Spr"unge automatisch
,,verl"angern'' soll, indem z.B. aus einem einfachen
\begin{verbatim}
bne target
\end{verbatim}
automatisch eine l"angere Sequenz mit gleicher Funktion wird, falls das
Sprungziel zu weit von momentanen Programmz"ahler entfernt ist. F"ur
{\tt bne} w"are dies z.B. die Sequenz
\begin{verbatim}
beq skip
jmp target
skip:
\end{verbatim}
Falls f"ur eine Anweisung aber kein passendes ,,Gegenteil'' existiert,
kann die Sequenz auch l"anger werden, z.B. f"ur {\tt jbc}:
\begin{verbatim}
jbc dobr
bra skip
dobr: jmp target
skip:
\end{verbatim}
Durch dieses Feature gibt es bei Spr"ungen keine eineindeutige Zuordnung
von Maschinen- und Assemblercode mehr, und bei Vorw"artsreferenzen handelt
man sich m"oglicherweise zus"atzliche Passes ein. Man sollte dieses
Feature daher mit Vorsicht einsetzen!
%%- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
\ttindex{Z80SYNTAX}
{\em G"ultigkeit: 8008, 8080/8085, $\mu$PD78xx}
Mit \tty{ON} als Argument kann man Assmebler-Befehle wahlweise
auch in der Form schreiben, wie sie Zilog f"ur den Z80 definiert hat.
Zum Beispiel benutzt man einfach nur noch \tty{LD} mit sich selbst
erkl"arenden Operanden, wo man in der originalen Syntax (bzw.
neueren 8008-Syntax) je nach Operanden \tty{MVI, LXI, MOV, STA, LDA,
SHLD, LHLD, LDAX, STAX} oder \tty{SPHL} schreiben mu"s.
Weil einige Mnemonics in der originalen und Z80-Syntax unterschiedliche
Bedeutung haben, kann man nicht zu 100\% im 'Z80-Stil' programmieren.
Alternativ schaltet man f"ur 8080/8085 mit einem \tty{EXCLUSIVE} als
Argument die originale Syntax ganz ab. Details zu dieser Betriebsart
kann man im Abschnitt \ref{8080Spec} nachlesen.
Ein eingebautes Symbol mit gleichem Namen gestattet es, die aktuelle
Betriebsart auszulesen. Es gilt \tty{0=OFF}, \tty{1=ON} und
\tty{2=EXCLUSIVE}.
%%- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
\ttindex{EXPECT}
\ttindex{ENDEXPECT}
Mit diesen beiden Befehlen rahmt man ein St"uck Quellcode ein, in dem ein
oder mehrere Fehler {\em erwartet} werden. Treten die "uber ihre Nummern
(siehe Kapitel \ref{ChapErrMess}) identifizierten Fehler oder Warnungen auf, werden
sie unterdr"uckt, und die Assemblierung l"auft ohne Fehler durch - nat"urlich
ohne an dieser Stelle Code zu erzeugen. Erwartete, aber nicht aufgetretene
Fehler oder Warnungen l"osen ihrerseits jedoch eine Fehlermeldung von
\tty{ENDEXPECT} aus. Der Haupt-Anwendungszweck dieser Befehle findet sich
in den Selbst-Tests im tests/-Unterverzeichnis. Z.B. kann man so testen,
ob Wertebereiche korrekt gepr"uft werden:
\begin{verbatim}
cpu 68000
expect 1320 ; immediate-Shift nur 1..8
lsl.l #10,d0
endexpect
\end{verbatim}
%%---------------------------------------------------------------------------
Die hier beschriebenen Befehle "uberschneiden sich teilweise in ihrer
Funktionalit"at, jedoch definiert jede Prozessorfamilie andere Namen
f"ur die gleiche Funktion. Um mit den Standardassemblern konform zu
bleiben, wurde diese Form der Implementierung gew"ahlt.
Sofern nicht ausdr"ucklich anders erw"ahnt, kann bei allen Befehlen zur
Datenablage (nicht bei denen zur Speicherreservierung!) eine beliebige Zahl
von Parametern angegeben werden, die der Reihe nach abgearbeitet werden.
%%- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
\ttindex{DC}
{\em G"ultigkeit: 680x0, M*Core, 68xx, H8, SH7x00, DSP56xxx,\\
XA, ST7/STM8, MN161x, IM61x0, CP-3F, SC61860}
Dieser Befehl legt eine oder mehrere Konstanten des beim durch
das Attribut bestimmten Typs im Speicher ab. Die Attribute entsprechen
den in Abschnitt \ref{AttrTypes} definierten, zus"atzlich ist f"ur
Byte-Konstanten die M"oglichkeit vorhanden, Stringausdr"ucke im Speicher
abzulegen, wie z.B.
\begin{verbatim}
String dc.b "Hello world!\0"
\end{verbatim}
Die Parameterzahl darf zwischen 1 und 20 liegen, zus"atzlich darf jedem
Parameter ein in eckigen Klammern eingeschlossener Wiederholungsfaktor
vorausgehen, z.B. kann man mit
\begin{verbatim}
dc.b [(*+255)&$ffffff00-*]0
\end{verbatim}
den Bereich bis zur n"achsten Seitengrenze mit Nullen f"ullen.
\bb{Vorsicht!}
Mit dieser Funktion kann man sehr leicht die Grenze von 1 Kbyte erzeugten
Codes pro Zeile Quellcode "uberschreiten!
Sollte die Byte-Summe ungerade sein, so kann vom Assembler automatisch
ein weiteres Byte angef"ugt werden, um die Wortausrichtung von Daten zu
erhalten. Dieses Verhalten kann mit dem \tty{PADDING}-Befehl ein-
und ausgeschaltet werden.
Mit diesem Befehl abgelegte Dezimalgleitkommazahlen (\tty{DC.P} ...) k"onnen
zwar den ganzen Bereich der extended precision "uberstreichen, zu beachten
ist dabei allerdings, da"s die von Motorola verf"ugbaren Koprozessoren
68881/68882 beim Einlesen solcher Konstanten die Tausenderstelle des
Exponenten ignorieren!
Default-Attribut ist \tty{W}, also 16-Bit-Integerzahlen.
Beim DSP56xxx ist der Datentyp auf Integerzahlen festgelegt (ein
Attribut ist deshalb weder n"otig noch erlaubt), die im Bereich
-8M..16M-1 liegen d"urfen. Stringkonstanten sind ebenfalls erlaubt,
wobei jeweils drei Zeichen in ein Wort gepackt werden.
Es ist im Gegensatz zum Original Motorola-Assembler auch erlaubt, mit
diesem Kommando Speicher zu reservieren, indem man als Argument ein
Fragezeichen angibt. Diese Erweiterung haben wohl einige Drittanbieter
von 68K-Assemblern eingebaut, in Anlehnung an das, was Intel-Assembler
machen. Wer dies benutzt, sollte sich aber im klaren sein, da"s dies
zu Problemen beim Portieren von Code auf andere Assembler f"uhren kann.
Des weiteren d"urfen Fragezeichen als Operanden nicht mit 'normalen'
Konstanten in einer Anweisung gemischt werden.
%%- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
\ttindex{DS}
{\em G"ultigkeit: 680x0, M*Core, 68xx, H8, SH7x00, DSP56xxx,\\
XA, ST7/STM8, MN161x, IM61x0, CP-3F, PPS-4, SC61860}
Mit diesem Befehl l"a"st sich zum einen Speicherplatz f"ur die angegebene
Zahl im Attribut beschriebener Zahlen reservieren. So reserviert
\begin{verbatim}
DS.B 20
\end{verbatim}
z.B. 20 Bytes Speicher,
\begin{verbatim}
DS.X 20
\end{verbatim}
aber 240 Byte !
Die andere Bedeutung ist die Ausrichtung des Programmz"ahlers, die
mit der Wertangabe 0 erreicht wird. So wird mit
\begin{verbatim}
DS.W 0
\end{verbatim}
der Programmz"ahler auf die n"achste gerade Adresse aufgerundet, mit
\begin{verbatim}
DS.D 0
\end{verbatim}
dagegen auf die n"achste Langwortgrenze. Eventuell dabei freibleibende
Speicherzellen sind nicht etwa mit Nullen oder NOPs gef"ullt,
sondern undefiniert.
Vorgabe f"ur die Operandengr"o"se ist --- wie "ublich --- W, also 16 Bit.
Beim 56xxx ist die Operandengr"o"se auf Worte (a 24 Bit) festgelegt,
Attribute gibt es deswegen wie bei \tty{DC} auch hier nicht.
%%- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
\ttindex{BLKB}\ttindex{BLKW}\ttindex{BLKL}\ttindex{BLKD}
{\em G"ultigkeit: Renesas RX}
Mit diesen Befehlen wird auf dem Renesas RX Speicher reserviert. Die
Gesamtgr"o"se des reservierten Speicher resultiert aus dem Produkt des
Arguments und der durch den Befehl gegebenen Operandengr"o"se (1 Byte
f"ur \tty{BLKB}, 2 Byte f"ur \tty{BLKW}, 4 Byte f"ur \tty{BLKL} und
8 Byte f"ur \tty{BLKD}).
%%- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
\ttindex{DN}\ttindex{DB}\ttindex{DW}\ttindex{DD}\ttindex{DQ}\ttindex{DT}
{\em\begin{tabbing}
G"ultigkeit: \= Intel (au"ser 4004/4040), Zilog, Toshiba, NEC, TMS370,\\
\> Siemens, AMD, M16(C), MELPS7700/65816, National, ST9,\\
\> Atmel, TMS7000, TMS1000, $\mu$PD77230, Signetics,\\
\> Fairchild, Intersil,\\
\> XS1, SC62015
\end{tabbing}}
Diese Befehle stellen sozusagen das Intel-Gegenst"uck zu \tty{DS}
und \tty{DC} dar, und wie nicht anders zu erwarten, ist die Logik
etwas anders:
Zum einen wird die Kennung der Operandengr"o"se in das Mnemonic
verlegt:
\begin{itemize}
\item{\tty{DN}: 4-Bit-Integer}
\item{\tty{DB}: Byte oder ASCII-String wie bei \tty{DC.B}}
\item{\tty{DW}: 16-Bit-Integer oder Half Precision}
\item{\tty{DD}: 32-Bit-Integer oder Single Precision}
\item{\tty{DQ}: Double Precision (64 Bit)}
\item{\tty{DT}: Extended Precision (80 Bit)}
\end{itemize}
Zum anderen erfolgt die Unterscheidung, ob Konstantendefinition oder
Speicherreservierung, im Operanden. Eine Reservierung von Speicher
wird durch ein \tty{?} gekennzeichnet:
\begin{verbatim}
db ? ; reserviert ein Byte
dw ?,? ; reserviert Speicher fuer 2 Worte (=4 Byte)
dd -1 ; legt die Konstante -1 (FFFFFFFFH) ab !
\end{verbatim}
Speicherreservierung und Konstantendefinition d"urfen \bb{nicht in einer
Anweisung} gemischt werden:
\begin{verbatim}
db "Hallo",? ; -->Fehlermeldung
\end{verbatim}
\ttindex{DUP}
Zus"atzlich ist noch der \tty{DUP}-Operator erlaubt, der die mehrfache Ablage
von Konstantenfolgen oder die Reservierung ganzer Speicherbl"ocke erlaubt:
\begin{verbatim}
db 3 dup (1,2) ; --> 1 2 1 2 1 2
dw 20 dup (?) ; reserviert 40 Byte Speicher.
\end{verbatim}
Wie man sehen kann, mu"s das \tty{DUP}-Argument geklammert werden, darf daf"ur
aber auch wieder aus mehreren Teilen bestehen, die selber auch wieder
\tty{DUP}s sein k"onnen...das ganze funktioniert also rekursiv.
\tty{DUP} ist aber auch eine Stelle, an der man mit einer anderen Grenze des
Assemblers in Ber"uhrung kommen kann: maximal k"onnen 1024 Byte Code
oder Daten in einer Zeile erzeugt werden. Dies bezieht sich \bb{nicht}
auf die Reservierung von Speicher, nur auf die Definition von
Konstantenfeldern!
Der \tty{DUP}-Operator wird nur erkannt, wenn er selber geklammert ist
und links von ihm ein nicht-leeres Argument steht; auf diese Weise ist es
m"oglich ein eventuell definiertes Symbol gleichen Namens auch als Argument
zu verwenden.
Auf verschiedenen Plattformen existieren Befehle mit identischer
Funktionalit"at, jedoch anderem Namen:
\begin{itemize}
\ttindex{DEFB}\ttindex{DEFW}
\item{Um mit dem M80 vertr"aglich zu sein, darf im Z80-Modus anstelle
von \tty{DB}/\tty{DW} auch \tty{DEFB}/\tty{DEFW} geschrieben
werden.}
\ttindex{BYTE}\ttindex{WORD}\ttindex{ADDR}\ttindex{ADDRW}
\item{\tty{BYTE/ADDR} bzw. \tty{WORD/ADDRW} beim COP4/8 stellen einen
Alias f"ur \tty{DB} bzw. \tty{DW} dar, wobei die beiden Paare sich
jedoch in der Byte-Order unterscheiden: Die Befehle, die von
National zur Adre"sablage vorgesehen waren, benutzen Big-Endian,
\tty{BYTE} bzw. \tty{WORD} jedoch Little-Endian.}
\ttindex{BYTE}\ttindex{WORD}
\item{\tty{BYTE} bzw. \tty{WORD} stehen auf der PDP-11 und WD16 als
Alias f"ur \tty{DB} bzw. \tty{DW} zur Verf"ugung.}
\ttindex{BYTE}\ttindex{WORD}\ttindex{LWORD}\ttindex{FLOAT}\ttindex{DOUBLE}
\item{Auf dem Renesas RX existieren:
\begin{itemize}
\item{\tty{BYTE} (wie \tty{DB})}
\item{\tty{WORD} (wie \tty{DW}, nur Ganzzahl-Argumente)}
\item{\tty{LWORD} (wie \tty{DD}, nur Ganzzahl-Argumente)}
\item{\tty{FLOAT} (wie \tty{DD}, nur Gleitkomma-Argumente)}
\item{\tty{DOUBLE} (wie \tty{DQ}, nur Gleitkomma-Argumente)}
\end{itemize}}
\end{itemize}
Wird \tty{DB} in einem Adre"sraum angewendet, der nicht byte-adressierbar
ist (z.B. das \tty{CODE}-Segment des Atmel AVR), so werden immer zwei Bytes
in ein 16-Bit-Wort gepackt, entsprechend der durch die Architektur gegebenen
Endinaness - das untere Byte wird bei Little-Endian also zuerst gef"ullt. Ist
die Gesamtmenge aller Bytes ungerade, so bleibt die andere Worth"alfte ungenutzt
und ist quasi ''Padding''. Sie wird auch nicht genutzt, falls im Quellcode
eine weitere \tty{DB}-Anweisung unmittelbar folge sollte. Sinngem"a"s gilt
das gleiche f"ur \tty{DN}, nur werden hier zwei oder vier Nibbles in ein Byte
oder 16-Bit-Wort gepackt.
Der NEC 77230 nimmt mit seiner \tty{DW}-Anweisung eine Sonderstellung ein:
Sie funktioniert eher wie \tty{DATA} bei seinen kleineren Br"udern,
akzeptiert aber neben String- und Integerargumenten auch Gleitkommawerte
(und legt sie prozessorspezifischen 32-Bit-Format ab). \tty{DUP} gibt es {\em
nicht}!
%%- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
\ttindex{FLT2}\ttindex{FLT3}\ttindex{FLT4}
{\em\begin{tabbing}
G"ultigkeit: \= PDP-11 (\tty{FLT2, FLT4}),\\
\> WD16 (\tty{FLT3})
\end{tabbing}}
\tty{FLT2} und \tty{FLT4} funktionieren analog zu \tty{DD} bzw. \tty{DQ},
legen jedoch ausschlie"slich Gleitkomma-Konstanten im DEC-eigenen F- bzw.
D-Format ab. Der WD16 verwendet hingegen ein eigenes, 48 Bit (drei
Maschinenworte) langes Format. Gleitkomma-Konstanten in diesem Format
k"onnen mit der \tty{FLT3}-Anweisung im Speicher abgelegt werden.
%%- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
\ttindex{DS}
\ttindex{DS8}
{\em\begin{tabbing}
G"ultigkeit: \= Intel, Zilog, Toshiba, NEC, TMS370, Siemens, AMD, M16(C),\\
\> National, ST9, TMS7000, TMS1000, Intersil, 6502, 68xx
\end{tabbing}}
Dieser Befehl stellt eine Kurzschreibweise dar, um Speicherbereiche
zu reservieren:
\begin{quote}{\tt
DS $<Anzahl>$
}\end{quote}
ist eine Kurzschreibweise f"ur
\begin{quote}{\tt
DB $<Anzahl>$ DUP (?)
}\end{quote}
dar, lie"se sich also prinzipiell auch einfach "uber ein Makro realisieren,
nur scheint dieser Befehl in den K"opfen einiger mit Motorola-CPUs gro"s
gewordener Leute (gell, Michael?) so fest verdrahtet zu sein, da"s sie
ihn als eingebauten Befehl erwarten...hoffentlich sind selbige jetzt
zufrieden {\tt ;-)}
{\tt DS8} ist beim National SC14xxx als Alias f"ur {\tt DS} definiert.
Achten Sie aber darauf, da"s der Speicher dieser Prozessoren in Worten zu
16 Bit organisiert ist, d.h. es ist unm"oglich, einzelne Bytes zu
reservieren. Falls das Argument von {\tt DS} ungerade ist, wird es auf
die n"achstgr"o"sere gerade Zahl aufgerundet.
%%- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
\ttindex{BYT}\ttindex{FCB}
{\em G"ultigkeit: 6502, 68xx, SC61860}
Mit diesem Befehl werden im 65xx/68xx-Modus Byte-Konstanten oder
ASCII-Strings abgelegt, er entspricht also \tty{DC.B} beim 68000 oder
bei Intel dem \tty{DB} (was ebenfalls erlaubt ist). Ein Wiederholungsfaktor
darf analog zu \tty{DC} jedem einzelnen Parameter in eckigen Klammern
vorangestellt werden.
%%- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
\ttindex{BYTE}
{\em G"ultigkeit: ST6, 320C2(0)x, 320C5x, MSP, TMS9900, CP-1600}
Dito. Ein im 320C2(0)x/5x-Modus vor dem Befehl stehendes Label wird
als untypisiert gespeichert, d.h. keinem Adre"sraum zugeordnet.
Der Sinn dieses Verhaltens wird bei den prozessorspezifischen
Hinweisen erl"autert.
Ob beim MSP bzw. TMS9900 ungerade Mengen von Bytes automatisch um
ein Null-Byte erg"anzt werden sollen, kann mit dem PADDING-Befehl
eingestellt werden.
Auf dem CP-1600 weicht die Verhaltensweise von {\tt BYTE} etwas ab:
die angegebenen 16-Bit-Werte werden in jeweils zwei aufeinanderfolgenden
W"ortern aufgeteilt abgelegt (LSB zuerst). Wenn einzelne Bytes (gepackt)
abgelegt werden sollen, mu"s stattdessen {\tt TEXT} verwendet werden!
%%- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
\ttindex{DC8}
{\em G"ultigkeit: SC144xx}
Dieser Befehl ist ein Alias f"ur {\tt DB}, d.h. mit ihm k"onnen
Byte-Konstanten oder Strings im Speicher abgelegt werden.
%%- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
\ttindex{ADR}\ttindex{FDB}
{\em G"ultigkeit: 6502, 68xx, SC61860}
Mit diesem Befehl werden im 65xx/68xx-Modus Wortkonstanten
abgelegt, er entspricht also \tty{DC.W} beim 68000 oder bei Intel
dem \tty{DW} (was auch zul"assig ist). Ein Wiederholungsfaktor darf
analog zu \tty{DC} jedem einzelnen Parameter in eckigen Klammern vorangestellt
werden.
%%- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
\ttindex{DDB}
{\em G"ultigkeit: 6502, MELPS-7700}
Dieser Befehl funktioniert analog zu \tty{ADR}, nur mit dem Unterschied, da"s
die 16-BitWerte im Big-Endian-Format im Speicher abgelegt werden.
%%- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
\ttindex{DCM}
{\em G"ultigkeit: 6502}
Mit diesem Befehl werden Gleitkomma-Konstanten im Speicher abgelegt, und
zwar in dem in \cite{AppleFloat} beschriebenen Format: Ein Exponent
von 8 Bit und eine 24-bittige Mantisse im Zweierkomplement, im Big-Endian-Format
abgelegt.
%%- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
\ttindex{WORD}
{\em G"ultigkeit: ST6, i960, 320C2(0)x, 320C3x/C4x/C5x, MSP, CP-1600,\\
IMP-16, IPC-16}
F"ur den 320C3x/C4x und i960 werden hiermit 32-Bit-Worte abgelegt, f"ur die
alle anderen Familien 16-Bit-Worte. Ein im 320C2(0)x/5x-Modus vor dem Befehl
stehendes Label wird als untypisiert gespeichert, d.h. keinem Adre"sraum
zugeordnet. Der Sinn dieses Verhaltens wird bei den prozessorspezifischen
Hinweisen erl"autert.
%%- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
\ttindex{DW16}
{\em G"ultigkeit: SC144xx}
Dieser Befehl ist beim SC144xx der Weg, Konstanten mit Wortl"ange (16 Bit)
im Speicher abzulegen und damit ein ALIAS f"ur DW.
%%- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
\ttindex{ACON}
{\em G"ultigkeit: 2650}
{\tt ACON} arbeitet analog zu {\tt DW}, jedoch werden die 16-Bit-Zahlenwerte
im Big-Endian-Format abgelegt.
%%- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
\ttindex{LONG}
{\em G"ultigkeit: 320C2(0)x, 320C5x}
Hiermit werden 32-Bit-Integer im Speicher abgelegt, und zwar in
der Reihenfolge LoWord-HiWord. Ein eventuell vor dem Befehl
stehendes Label wird dabei wieder als untypisiert abgelegt
(der Sinn dieser Ma"snahme ist in den prozessorspezifischen
Hinweisen erl"autert).
%%- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
\ttindex{SINGLE}\ttindex{DOUBLE}\ttindex{EXTENDED}
{\em G"ultigkeit: 320C3x/C4x (nicht {\tt DOUBLE}), 320C6x (nicht {\tt
EXTENDED})}
Mit diesen Befehlen werden Gleitkomma-Konstanten im Speicher abgelegt,
jedoch beim 320C3x/C4x nicht im IEEE-Format, sondern in den vom Prozessor
verwendeten 32- und 40-Bit-Formaten. Da 40 Bit nicht mehr in eine
Speicherzelle hineinpassen, werden im Falle von \tty{EXTENDED} immer derer
2 pro Wert belegt. Im ersten Wort finden sich die oberen 8 Bit (der
Exponent), der Rest (Vorzeichen und Mantisse) in zweiten Wort.
%%- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
\ttindex{FLOAT}\ttindex{DOUBLE}
{\em G"ultigkeit: 320C2(0)x, 320C5x}
Mit diesen Befehlen k"onnen 32- bzw. 64-Bit-Gleitkommazahlen
im IEEE-Format im Speicher abgelegt werden. Dabei wird das
niederwertigste Byte jeweils auf der ersten Speicherstelle
abgelegt. Ein eventuell vor dem Befehl stehendes Label wird
wieder als untypisiert gespeichert (der Sinn dieser Ma"snahme
ist in den prozessorspezifischen Hinweisen erl"autert).
%%- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
\ttindex{SINGLE}\ttindex{DOUBLE}
{\em G"ultigkeit: TMS99xxx}
Mit diesen Befehlen k"onnen 32- bzw. 64-Bit-Gleitkommazahlen
im prozessoreigenen Format im Speicher abgelegt werden. Das
Format entspricht dem IBM/360-Gleitkommaformat.
%%- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
\ttindex{EFLOAT}\ttindex{BFLOAT}\ttindex{TFLOAT}
{\em G"ultigkeit: 320C2(0)x, 320C5x}
Auch diese Befehle legen Gleitkommazahlen im Speicher ab,
jedoch in einem nicht-IEEE-Format, das evtl. leichter von
Signalprozessoren zu verarbeiten ist:
\begin{itemize}
\item{\tty{EFLOAT}: Mantisse mit 16 Bit, Exponent mit 16 Bit}
\item{\tty{BFLOAT}: Mantisse mit 32 Bit, Exponent mit 16 Bit}
\item{\tty{TFLOAT}: Mantisse mit 64 Bit, Exponent mit 32 Bit}
\end{itemize}
Gemeinsam ist den Befehlen, da"s die Mantisse vor dem
Exponenten abgelegt wird (Lo-Word jeweils zuerst) und
beide im Zweierkomplement dargestellt werden. Ein eventuell
vor dem Befehl stehendes Label wird wieder als untypisiert
gespeichert (der Sinn dieser Ma"snahme ist in den
prozessorspezifischen Hinweisen erl"autert).
%%- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
\ttindex{Qxx}\ttindex{LQxx}
{\em G"ultigkeit: 320C2(0)x, 320C5x}
Mit diesen Befehlen k"onnen Gleitkommazahlen in einem Festkommaformat
abgelegt werden. \tty{xx} ist dabei eine zweistellige Zahl, mit deren
Zweierpotenz der Gleitkommawert vor der Umwandlung in eine ganze Zahl
multipliziert werden soll. Er bestimmt also praktisch, wieviele Bits
f"ur die Nachkommastellen reserviert werden sollen. W"ahrend aber
\tty{Qxx} nur ein Wort (16 Bit) ablegt, wird das Ergebnis bei \tty{LQxx}
in 2 Worten (LoWord zuerst) abgelegt. Das sieht dann z.B. so
aus:
\begin{verbatim}
q05 2.5 ; --> 0050h
lq20 ConstPI ; --> 43F7h 0032h
\end{verbatim}
Mich m"oge niemand steinigen, wenn ich mich auf meinem HP28
verrechnet haben sollte...
%%- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
\ttindex{DATA}
{\em G"ultigkeit: PIC, 320xx, AVR, MELPS-4500, H8/500, \\
HMCS400, 4004/4040, $\mu$PD772x, OLMS-40/50, Padauk}
Mit diesem Befehl werden Daten im aktuellen Segment abgelegt,
wobei sowohl Integer- als auch Stringwerte zul"assig sind. Bei
Strings belegt beim 16C5x/16C8x, 17C4x im Datensegment, beim
4500er, 4004 und HMCS400 im Code-Segement ein Zeichen ein Wort,
bei AVR, 17C4x im Codesegment, $\mu$PD772x in den Datensegmenten
und 3201x/3202x passen zwei Zeichen in ein Wort (LSB zuerst),
beim $\mu$PD7725 drei und beim 320C3x/C4x sogar derer 4 (MSB
zuerst). Im Gegensatz dazu mu"s im Datensegment des 4500 bzw.
ein Zeichen auf zwei Speicherstellen verteilt werden, ebenso wie
beim 4004 und HMCS400. Der Wertebereich f"ur Integers entspricht
der Wortbreite des jeweiligen Prozessors im jeweiligen Segment.
Das bedeutet, da"s \tty{DATA} beim 320C3x/C4x die Funktion von
\tty{WORD} mit einschlie"st (die von \tty{SINGLE} "ubrigens auch,
wenn \asname{} das Argument als Gleitkommazahl erkennt).
%%- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
\ttindex{ZERO}
{\em G"ultigkeit: PIC, CP-1600}
Dieser Befehl legt einen durch den Parameter spezifizierte
Zahl von Nullworten (=NOP bei PIC) im Speicher ab.
%%- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
\ttindex{FB}\ttindex{FW}
{\em G"ultigkeit: COP4/8}
Mit diesen Befehlen kann ein gr"o"serer Block von Speicher (dessen L"ange
in Bytes bzw. Worten der erste Parameter angibt) mit einer Byte- bzw.
Wortkonstanten gef"ullt werden, die durch den zweiten Parameter angegeben
wird.
%%- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
\ttindex{ASCII}\ttindex{ASCIZ}
{\em G"ultigkeit: ST6, \tty{ASCII} auch IMP-16 und IPC-16}
Mit diesen beiden Befehlen k"onnen Stringkonstanten im Speicher
abgelegt werden. W"ahrend ASCII nur die reinen Daten im Speicher
ablegt, versieht \tty{ASCIZ} automatisch \ii{jeden} angegebenen String
mit einem NUL-Zeichen am Ende.
%%- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
\ttindex{STRING}\ttindex{RSTRING}
{\em G"ultigkeit: 320C2(0)x, 320C5x}
Diese Anweisungen funktionieren analog zu {\tt DATA}, jedoch werden
hier Integer-Ausdr"ucke grunds"atzlich als {\it Bytes} mit einem
entsprechend eingeschr"ankten Wertebereich betrachtet, wodurch es
m"oglich wird, die Zahlen zusammen mit anderen Zahlen oder Zeichen
paarweise in Worte zu verpacken.
Die beiden Befehle unterscheiden sich lediglich in der Reihenfolge
der Bytes in einem Wort: Bei {\tt STRING} wird zuerst das
obere und danach das untere gef"ullt, bei {\tt RSTRING} ist es
genau umgekehrt.
Ein eventuell vor dem Befehl stehendes Label wird wieder als
untypisiert gespeichert. Der Sinn dieser Ma"snahme ist im
entsprechenden Kapitel mit den prozessorspezifischen Befehlen
erl"autert.
%%- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
\ttindex{FCC}
{\em G"ultigkeit: 6502, 68xx}
Mit diesem Befehl werden im 65xx/68xx-Modus String-Konstanten abgelegt.
Beachten Sie jedoch, da"s im Gegensatz zum Originalassembler
AS11 von Motorola (dessentwegen dieser Befehl existiert, bei \asname{} ist
diese Funktion im \tty{BYT}-Befehl enthalten), String-Argumente nur in
G"ansef"u"schen und nicht in Hochkommas oder Schr"agstrichen eingeschlossen
werden d"urfen! Ein Wiederholungsfaktor darf analog zu \tty{DC} jedem
einzelnen Parameter in eckigen Klammern vorangestellt werden.
%%- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Mit diesem Befehl werden im CP-1600-Modus String-Konstanten gepackt,
d.h. zwei Zeichen pro Wort, abgelegt.
%%- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
\ttindex{DFS}\ttindex{RMB}
{\em G"ultigkeit: 6502, 68xx}
Dieser Befehl dient im 65xx/68xx-Modus zur Reservierung von
Speicher, er entspricht \tty{DS.B} beim 68000 oder \tty{DB ?}
bei Intel.
%%- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
\ttindex{BLOCK}
{\em G"ultigkeit: ST6}
Dito.
%%- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
\ttindex{SPACE}
{\em G"ultigkeit: i960}
Dito.
%%- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
\ttindex{RES}
{\em G"ultigkeit: PIC, MELPS-4500, HMCS400, 3201x, 320C2(0)x,\\
320C5x, AVR, $\mu$PD772x, OLMS-40/50, Padauk, CP-1600,\\
PPS-4, 2650}
Dieser Befehl dient zur Reservierung von Speicher. Er reserviert
im Codesegment immer W"orter (10/12/14/16 Bit), im Datensegment bei
den PICs Bytes, beim 4500er, PPS-4 und OLMS-40/50 Nibbles sowie bei
TI W"orter.
%%- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
\ttindex{BSS}
{\em G"ultigkeit: 320C2(0)x, 320C3x/C4x/C5x/C6x, MSP}
\tty{BSS} arbeitet analog zu \tty{RES}, lediglich ein eventuell vor dem
Befehl stehendes Symbol wird beim 320C2(0)x/5x als untypisiert gespeichert.
Der Sinn dieser Ma"snahme kann im Kapitel mit den prozessorspezifischen
Hinweisen nachgelesen werden.
%%- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
\ttindex{DSB}\ttindex{DSW}
{\em G"ultigkeit: COP4/8}
Diese beiden Befehle stellen im COP4/8-Modus die zum ASMCOP von National
kompatible Methode dar, Speicher zu reservieren. W"ahrend \tty{DSB} nur
einzelne Bytes freih"alt, reserviert \tty{DSW} W"orter und damit effektiv
doppelt soviel Bytes wie \tty{DSB}.
%%- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
\ttindex{DS16}
{\em G"ultigkeit: SC144xx}
Dieser Befehl reserviert Speicher in Schritten von vollst"andigen Worten,
d.h. 16 Bit. Er stellt einen Alias zu {\tt DW} dar.
%%- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
\ttindex{ALIGN}
{\em G"ultigkeit: alle Prozessoren}
\tty{ALIGN} mit einem Integerausdruck als Argument erlaubt es, den
Programmz"ahler auf eine bestimmte Adresse auszurichten. Die
Ausrichtung erfolgt dergestalt, da"s der Programmz"ahler so weit
erh"oht wird, da"s er ein ganzzahliges mehrfaches des Argumentes
wird. In seiner Funktion entspricht \tty{ALIGN} also \tty{DS.x 0}
beim den 680x0ern, nur ist die Ausrichtung noch flexibler.
Beispiel:
\begin{verbatim}
align 2
\end{verbatim}
macht den Programmz"ahler gerade. Wird \tty{ALIGN} in dieser Form mit nur
einem Argument verwendet, ist der Inhalt des dadurch frei bleibenden
Speicherbereichs nicht definiert. Alternativ kann als zweites Argument ein
(Byte-)Wert angegeben werden, mit dem dieser Bereich gef"ullt wird.
%%- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
\ttindex{LTORG}
{\em G"ultigkeit: SH7x00, IM61x0, IMP-16, IPC-16}
Da der SH7000-Prozessor seine Register immediate nur mit 8-Bit-Werten
laden kann, \asname{} dem Programmierer jedoch vorgaukelt, da"s es eine solche
Einschr"ankung nicht g"abe, mu"s er die dabei entstehenden Konstanten
irgendwo im Speicher ablegen. Da es nicht sinnvoll w"are, dies einzeln
zu tun (wobei jedes Mal Sprungbefehle anfallen w"urden...), werden die
Literale gesammelt und k"onnen vom Programmierer mit diesem Befehl
gezielt blockweise (z.B. am Ende eines Unterprogrammes) abgelegt werden.
Zu den zu beachtenden Details und Fallen sei auf das Kapitel mit den
SH7000-spezifischen Dingen hingewiesen.
%%---------------------------------------------------------------------------
{\em G"ultigkeit: alle Prozessoren}
Kommen wir nun zu dem, was einen Makroassembler vom normalen Assembler
unterscheidet: der M"oglichkeit, Makros zu definieren (ach was ?!).
Unter Makros verstehe ich hier erst einmal eine Menge von Anweisungen
(normal oder Pseudo), die mit bestimmten Befehlen zu einem Block
zusammengefa"st werden und dann auf bestimmte Weise bearbeitet
werden k"onnen. Zur Bearbeitung solcher Bl"ocke kennt der Assembler
folgende Befehle:
%%- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
\ttindex{MACRO}\ttindex{ENDM}
ist der wohl wichtigste Befehl zur Makroprogrammierung. Mit der
Befehlsfolge
\begin{verbatim}
<Name> MACRO [Parameterliste]
<Befehle>
ENDM
\end{verbatim}
wird das Makro \tty{$<$Name: $>$} als die eingeschlossene Befehlsfolge
definiert. Diese Definition alleine erzeugt noch keinen Code! Daf"ur kann
fortan die Befehlsfolge einfach durch den Namen abgerufen werden, das Ganze
stellt also eine Schreiberleichterung dar. Um die ganze Sache etwas
n"utzlicher zu machen, kann man der Makrodefinition eine Parameterliste
mitgeben.
W"ahrend der Makroname selber nur den "ublichen Regeln f"ur Symbolnamen
(\ref{SectSymConv}) gen"ugen mu"s, gilt f"ur die Namen der (kommaseparierten)
Parameternamen die weitere Einschr"ankung, da"s sie keine Unterstriche
enthalten d"urfen. Dies kann durch den Kommandozeilen-Parameter
\tty{-underscore-macroargs} aufgehoben werden, hat aber Nebenwirkungen
bei der Expansion von Makros und sollte nur eingesetzt werden, wenn
unbedingt n"otig.
Sowohl Makronamen als auch -parameter sind von einer Umschaltung
von \asname{} in den case-sensitiven Modus betroffen.
Makros sind "ahnlich wie Symbole lokal, d.h. bei Definition in
einer Sektion sind sie nur in dieser Sektion und ihren Untersektionen
bekannt. Dieses Verhalten l"a"st sich aber durch die weiter unten
beschriebenen Optionen \tty{PUBLIC} und \tty{GLOBAL} in weiten Grenzen
steuern.
F"ur jeden Makroparameter kann ein Defaultwert mit angeh"angtem
Gleichheitszeichen angegeben werden. Dieser Wert wird f"ur den
Parameter eingesetzt, wenn beim Makroaufruf kein Argument f"ur
diesen Parameter angegeben wird, bzw. wenn ein Positionsargument
(s.u.) f"ur diesen Parameter leer ist.
Neben den eigentlichen Makroparametern k"onnen in der Parameterliste
auch Steuerparameter enthalten sein, die die Abarbeitung des betroffenen
Makros beeinflussen; diese Parameter werden von normalen Parametern
dadurch unterschieden, da"s sie in geschweifte Klammern eingeschlossen
sind. Es sind folgende Steuerparameter definiert:
\begin{itemize}
\item{\tty{EXPAND/NOEXPAND} : legen fest, ob bei der sp"ateren
Verwendung diese Makros der expandierte Code mit angezeigt
werden soll. Default ist der durch den Pseudobefehl
\tty{MACEXP\_DFT} festgelegte Wert.}
\item{\tty{EXPIF/NOEXPIF} : legen fest, ob bei der sp"ateren
Verwendung diese Makros Befehle zur bedingten Assemblierung
und dadurch ausgeschlossener Code angezeigt werden soll. Default
ist der durch den Pseudobefehl \tty{MACEXP\_DFT} festgelegte Wert.}
\item{\tty{EXPMACRO/NOEXPMACRO} : legen fest, ob bei der sp"ateren
Verwendung diese Makros darin definierte Makros angezeigt werden
sollen. Default ist der durch den Pseudobefehl
\tty{MACEXP\_DFT} festgelegte Wert.}
\item{\tty{EXPREST/NOEXPREST} : legen fest, ob bei der sp"ateren
Verwendung Code-Zeilen angezeigt werden sollen, die weder
Makro-Definitionen, bedingte Assemblierung noch durch bedingte
Assemblierung ausgeschlossene Zeilen sind. Default ist der durch den
Pseudobefehl \tty{MACEXP\_DFT} festgelegte Wert.}
\item{\tty{PUBLIC[:Sektionsname]} : ordnet das Makro nicht der
aktuellen, sondern einer ihr "ubergeordneten Sektion zu.
Auf diese Weise kann eine Sektion Makros f"ur die ,,Au"senwelt''
zur Verf"ugung stellen. Fehlt eine Sektionsangabe, so wird das
Makro v"ollig global, d.h. ist "uberall benutzbar.}
\item{\tty{GLOBAL[:Sektionsname]} : legt fest, da"s neben diesem
Makro noch ein weiteres Makro abgelegt werden soll, das zwar
den gleichen Inhalt hat, dessen Name aber zus"atzlich mit dem
Namen der Sektion versehen ist, in der es definiert wurde und
das der spezifizierten Sektion zugeordnet werden soll. Bei
dieser mu"s es sich um eine Obersektion zu der aktuellen Sektion
handeln; fehlt die Angabe, so wird das zus"atzliche Makro
global sichtbar. Wird z.B. ein Makro \tty{A} in der Sektion \tty{B}
definiert, die wiederum eine Untersektion der Sektion \tty{C} ist,
so w"urde neben z.B. dem Makro A ein weiteres globales mit dem
Namen \tty{C\_B\_A} erzeugt. W"urde dagegen \tty{C} als Zielsektion
angegeben, so w"urde das Makro \tty{B\_A} hei"sen und der Sektion
\tty{C} zugeordnet. Diese Option ist defaultm"a"sig ausgeschaltet und
hat auch nur einen Effekt, falls sie innerhalb einer Sektion
benutzt wird. Das lokal bekannte Originalmakro wird von ihr
nicht beeinflu"st.}
\item{\tty{EXPORT/NOEXPORT} : legen fest, ob die Definition dieses
Makros in einer getrennten Datei abgelegt werden soll, falls
die Kommandozeilenoption \tty{-M} gegeben wurde. Auf diese
Weise k"onnen einzelne Definitionen ,,privater'' Makros selektiv
ausgeblendet werden. Der Default ist FALSE, d.h. die Definition
wird nicht in der Datei abgelegt. Ist zus"atzlich die
\tty{GLOBAL}-Option gegeben worden, so wird das Makro mit dem
modifizierten Namen abgelegt.}
\item{\tty{INTLABEL/NOINTLABEL} : legen fest, ob ein in der Zeile mit
dem Makroaufruf definiertes Label innerhalb des Rumpfes als
zus"atzlicher Parameter verwendet werden soll, als einfach
nur die Adresse dieser Zeile zu 'labeln'.}
\item{\tty{GLOBALSYMBOLS/NOGLOBALSYMBOLS} : legt fest, ob im
Makro definierte Labels lokal zu diesem Makro sein sollen
oder auch au"serhalb des Makros verf"ugbar sein sollen.
Der Default ist, da"s Labels lokal sind, weil mehrfache
Benutzung eines Makros ansonsten schwierig w"are.}
\end{itemize}
Diese eben beschriebenen Steuerparameter werden von \asname{} aus der
Parameterliste ausgefiltert, haben also keine weitere Wirkung in
der folgenden Verarbeitung und Benutzung.
Beim Aufruf eines Makros werden die beim Aufruf angegebenen
Parameternamen "uberall textuell im Befehlsblock eingesetzt und der
sich so ergebene Assemblercode wird normal assembliert. Sollten
beim Aufruf zu wenige Parameter angegeben werden, werden Nullstrings
eingef"ugt. Wichtig ist zu wissen, da"s bei der Makroexpansion keine
R"ucksicht auf eventuell in der Zeile enthaltene Stringkonstanten
genommen wird. Zu diesem Detail gilt die alte IBM-Regel:
\begin{quote}
\ii{It's not a bug, it's a feature!}
\end {quote}
Diese L"ucke kann man bewu"st ausnutzen, um Parameter mittels
Stringvergleichen abzupr"ufen. So kann man auf folgende Weise
z.B. pr"ufen, wie ein Makroparameter aussieht:
\begin{verbatim}
mul MACRO para,parb
IF UpString("PARA")<>"A"
MOV a,para
ENDIF
IF UpString("PARB")<>"B"
MOV b,parb
ENDIF
!mul ab
ENDM
\end{verbatim}
Wichtig ist bei obigem Beispiel, da"s der Assembler alle
Parameternamen im case-sensitiven Modus in Gro"sbuchstaben
umsetzt, in Strings aber nie eine Umwandlung in Gro"sbuchstaben
erfolgt. Die Makroparameternamen m"ussen in den Stringkonstanten
daher gro"s geschrieben werden.
Des weiteren wird die Parameter-Ersetzung davon beeinflusst, ob
Unterstriche im Parameternamen erlaubt sind oder nicht. Falls
nicht --- was der Default ist --- wirken Unterstriche auch
als 'Begrenzungszeichen', um Parameternamen im Makrorumpf zu
erkennen. Im Default w"urde also im folgenden Beispiel
\begin{verbatim}
setled macro led,value
out led,value
ld led_shadow,value
endm
\end{verbatim}
der Parameter 'led' in beiden Zeilen ersetzt, mit dem Kommandozeilen-Schalter
\tty{-underscore-macroargs} jedoch nur in der ersten. Diverse
der mitgelieferten Include-Dateien setzen das Default-Verhalten
voraus, weshalb dieser Schalter nur wenn unbedingt n"otig genutzt
werden sollte.
Argumente an ein Makro k"onnen in zwei Formen angegeben werden:
als {\em Positionsargumente} oder als {\em
Schl"usselwortargumente}.
Bei Positionsargumenten ergibt sich
die Zuordnung von Argumenten zu Makro-Parametern einfach durch
ihre Position in der Aufrufliste, d.h. das erste Argument wird dem
ersten Parameter zugeordnet, das zweite Argument dem zweiten
Parameter usw.. Werden weniger Argumente angegeben als das Makro
Parameter hat, werden eventuell definierte Defaultwerte oder ein
Leerstring eingesetzt. Gleiches gilt auch f"ur leere Argumente.
Schl"usselwortargumente geben jedoch explizit an, f"ur welchen
Makro-Parameter sie gelten, indem der Parametername dem Wert
vorangestellt wird, z.B. so:
\begin{verbatim}
mul para=r0,parb=r1
\end{verbatim}
Wiederum wird f"ur nicht definierte Parameter ein eventuell
vorhandener Default oder ein Leerstring eingesetzt.
Im Unterschied zu Positionsargumenten ist es mit
Schl"usselwortargumenten auch m"oglich, einem Parameter einen
Leerstring zuzuweisen, der einen nicht-leeren Default-Wert hat.
Positions- und Schl"usselwortargumente d"urfen auch in einem
Aufruf gemischt werden, jedoch d"urfen ab dem ersten
Schl"usselwortargument keine Positionsargumente mehr verwendet
werden.
F"ur die Makroparameter gelten die gleichen Konventionen wie bei
normalen Symbolen, mit der Ausnahme, da"s hier nur Buchstaben
und Ziffern zugelassen sind, also weder Punkte noch
Unterstriche. Diese Einschr"ankung hat ihren Grund in einem
verstecktem Feature: Der Unterstrich erlaubt es, einzelne
Makroparameternamen zu einem Symbol zusammenzuketten, z.B. in
folgendem Beispiel:
\begin{verbatim}
concat MACRO part1,part2
CALL part1_part2
ENDM
\end{verbatim}
Der Aufruf
\begin{verbatim}
concat Modul,Funktion
\end{verbatim}
ergibt also
\begin{verbatim}
CALL Modul_Funktion
\end{verbatim}
Neben den am Makro selber angegebenen Parametern existieren vier weitere
'implizite' Parameter, die immer vorhanden sind und daher nicht als eigene
Makroparameter verwendet werden sollten:
\begin{itemize}
\item{{\tt ATTRIBUTE} bezeichnet bei Architekturen, die Attribute f"ur
Prozessorbefehle zulassen, das bei einem Makroaufruf angeh"angte
Argument. F"ur ein Beispiel siehe z.B. unten!}
\item{{\tt ALLARGS} bezeichnet eine kommaseparierte Liste aller
Makroargumente, z.B., um sie an eine {\tt IRP}-Anweisung
weiterzureichen.}
\item{{\tt ARGCOUNT} bezeichnet die tat"achlich "ubergebene Anzahl der
an das Makro "ubergebenen Argumente. Zu beachten ist allerdings,
da"s diese Zahl niemals geringer als die Zahl der formalen Parameter
ist, da \asname{} fehlende Argumente mit Leerstrings auff"ullt!}
\item{{\tt \_\_LABEL\_\_} bezeichnet das Label, das in der das Makro aufrufenden
Zeile stand. Diese Ersetzung findet nur statt, wenn f"ur dieses
Makro die {\tt INTLABEL}-Option gesetzt wurde!}
\end{itemize}
{\bf WICHTIG:} Die Namen dieser impliziten Parameter sind auch
case-insensitiv, wenn \asname{} insgesamt angewiesen wurde, case-sensitiv
zu arbeiten!
Der Zweck, ein Label 'intern' im Makro verwenden zu k"onnen, ist sicher
nicht unmittelbar einleuchtend. Den einen oder anderen Fall mag es ja
geben, in dem es sinnvoll ist, den Einsprungpunkt in ein Makro irgendwo
in seinen Rumpf zu verschieben. Der wichtigste Anwendungsfall sind aber
TI-Signalprozessoren, die eine Parallelisierung von Befehlen durch einen
doppelten senkrechten Strich in der Label-Spalte kennzeichnen, etwa so:
\begin{verbatim}
instr1
|| instr2
\end{verbatim}
(da die beiden Instruktionen im Maschinencode in ein Wort verschmelzen,
kann man die zweite Instruktion "ubrigens gar nicht separat anspringen -
man verliert also durch das Belegen der Label-Position nichts). Das
Problem ist aber, da"s einige 'Bequemlichkeits-Befehle' durch Makros
realisiert werden. Ein vor das Makro geschriebenes
Parallelisierungssymbol w"urde normalerweise dem Makro selber zugeordnet,
{\it nicht dem ersten Befehl im Makro selber}. Aber mit diesem Trick
funktioniert's:
\begin{verbatim}
myinstr macro {INTLABEL}
__LABEL__ instr2
endm
instr1
|| myinstr
\end{verbatim}
Das Ergebnis nach der Expansion von {\tt myinstr} ist identisch zu dem
vorherigen Beispiel ohne Makro.
Rekursion von Makros, also das wiederholte Aufrufen eines Makros innerhalb
seines Rumpfes oder indirekt "uber andere von ihm aufgerufene Makros ist
vollkommen legal. Wie bei jeder Rekusion mu"s man dabei nat"urlich
sicherstellen, da"s sie irgendwann ein Ende findet. F"ur den Fall, da"s
man dies vergessen hat, f"uhrt \asname{} in jedem definierten Makro einen Z"ahler
mit, der bei Beginn einer Makroexpansion inkrementiert und an deren Ende
wieder dekrementiert wird. Bei rekursiven Aufrufen eines Makros erreicht
dieser Z"ahler also immer h"ohere Werte, und bei einem per {\tt NESTMAX}
einstellbaren Wert bricht \asname{} ab. Vorsicht, wenn man diese Bremse
abschaltet: der Speicherbedarf auf dem Heap kann so beliebig steigen und
selbst ein Unix-System in die Knie zwingen...
Um alle Klarheiten auszur"aumen, ein einfaches Beispiel:
Ein an ,,Intel-Syntax'' gew"ohnter Programmierer m"ochte diex Befehle \tty{PUSH/POP}
unbedingt auch auf dem 68000 haben. Er l"ost das
folgenderma"sen:
\begin{verbatim}
push MACRO op
MOVE.ATTRIBUTE op,-(sp)
ENDM
pop MACRO op
MOVE.ATTRIBUTE (sp)+,op
ENDM
\end{verbatim}
Schreibt man nun im Code
\begin{verbatim}
push d0
pop.l a2 ,
\end{verbatim}
so wird daraus
\begin{verbatim}
MOVE. d0,-(sp)
MOVE.L (sp)+,a2
\end{verbatim}
Eine Makrodefinition darf nicht "uber Include-Datei-Grenzen hinausgehen.
In Makror"umpfen definierte Labels werden immer als lokal betrachtet,
au"ser bei der Definition des Makros wurde die
\tty{GLOBALSYMBOLS}-Option verwendet. Ist es aus irgendwelchen Gr"unden
erforderlich, ein einzelnes Label in einem Makro global zu
machen, das ansonsten lokale Labels benutzt, so kann man es mit
\tty{LABEL} definieren, dessen Anwendung (wie bei \tty{BIT,SFR}...)
immer globale Symbole ergibt :
\begin{verbatim}
<Name> LABEL *
\end{verbatim}
Da der Assembler beim Parsing einer Zeile zuerst die Makroliste und
danach die Prozessorbefehle abklappert, lassen sich auch Prozessorbefehle
neu definieren. Die Definition sollte dann aber vor der ersten Benutzung
des Befehles durchgef"uhrt werden, um Phasenfehler wie im folgenden
Beispiel zu vermeiden:
\begin{verbatim}
BSR ziel
bsr MACRO target
JSR ziel
ENDM
BSR ziel
\end{verbatim}
Im ersten Pass ist bei der Assemblierung des \tty{BSR}-Befehles das Makro
noch nicht bekannt, es wird ein 4 Byte langer Befehl erzeugt. Im
zweiten Pass jedoch steht die Makrodefinition sofort (aus dem ersten
Pass) zur Verf"ugung, es wird also ein 6 Byte langer \tty{JSR} kodiert.
Infolgedessen sind alle darauffolgenden Labels um zwei zu niedrig,
bei allen weiteren Labels sind Phasenfehler die Folge, und ein weiterer
Pass ist erforderlich.
Da durch die Definition eines Makros ein gleichnamiger Maschinen- oder
Pseudobefehl nicht mehr zugreifbar ist, gibt es eine Hintert"ur, die
Originalbedeutung zu erreichen: Stellt man dem Mnemonic ein \tty{!} voran,
so wird das Durchsuchen der Makroliste unterdr"uckt. Das kann
beispielsweise n"utzlich sein, um Befehle in ihrer M"achtigkeit zu
erweitern, z.B. die Schiebebefehle beim TLCS-90:
\begin{verbatim}
srl macro op,n ; Schieben um n Stellen
rept n ; n einfache Befehle
!srl op
endm
endm
\end{verbatim}
Fortan hat der \tty{SRL}-Befehl einen weiteren Parameter...
Wird ein Makro im Quellcode aufgerufen, wird der durch dieses Makro definierte
Quellcode, inklusiver eingesetzter Parameter, an dieser Stelle im Listing
expandiert. Das kann das Listing stark aufbl"ahen und schwerer lesbar
machen. Es ist daher m"oglich, diese Expansion ganz oder teilweise zu
unterdr"ucken. Generell teilt \asname{} die in einem Makrorumpf enthaltenen
Quelltext-Zeilen in drei Klassen ein:
\begin{itemize}
\item{Darin enthaltene Makrodefinitionen, d.h. das Makro wird benutzt, um
seinerseits weitere Makros zu definieren, oder es enth"alt \tty{REPT/
IRP/IRPC/WHILE}-Bl"ocke.}
\item{Befehle zur bedingten Assemblierung plus Zeilen, die aufgrund
solcher Anweisungen {\it nicht} assembliert werden. Da bedingte
Assemblierung von Makro-Parametern abh"angig sein darf, kann diese
Untermenge ebenfalls davon abh"angen.}
\item{Alle restlichen Zeilen, die nicht unter die beiden ersten Klassen
fallen.}
\end{itemize}
F"ur jedes Makro kann einzeln festgelegt werden, welche Teile im Listing
auftauchen oder nicht auftauchen sollen. Vorgabewert bei der Definition
eines Makros ist dabei die zuletzt mit dem Befehl \tty{MACEXP\_DFT}
(\ref{MACEXPDFT}) vorgegebene Menge. Wird bei der Definition eines
Makros eine der Direktiven \tty{EXPAND/NOEXPAND}, \tty{EXPIF/NOEXPIF},
\tty{EXPMACRO/NOEXPMACRO} oder \tty{EXPREST/NOEXPREST} gegeben, so wirken
diese {\it zus"atzlich} und mit h"oherer Priorit"at. Ist z.B. die Expansion
global komplett ausgeschaltet (\tty{MACEXP\_DFT OFF}), so bewirkt das
Hinzuf"ugen von \tty{EXPREST}, da"s bei der Benutzung dieses Makro nur
die Zeilen im Listing angezeigt werden, die nach Auswertung bedingter
Assemblierung verblieben sind und auch keine Makrodefinition selber sind.
Daraus ergibt sich, da"s eine "Anderung der Untermenge per \tty{MACEXP\_DFT}
keine Auswirkungen mehr auf Makros hat, die {\it vor} dieser Anweisung
{\it definiert} wurden. Im Listing f"uhrt der Abschnitt mit definierten Makros
f"ur jedes Makro auf, welche Direktiven in der Summe f"ur dieses Makro
gelten. Die in geschweiften Klammern aufgef"uhrte Liste ist dabei soweit
gek"urzt, da"s f"ur jede Klasse nur die letztg"ultige Direktive aufgef"uhrt
wird. Ein per \tty{MACEXP\_DFT} gegebenes \tty{NOIF} taucht dort also
nicht mehr auf, falls speziell f"ur dieses Makro die Direktive \tty{EXPIF}
gegeben wurde.
In Einzelf"allen kann es sinnvoll sein, die f"ur ein Makro definierten
Expansionsregeln zu "ubersteuern, egal ob diese per \tty{MACEXP\_DFT} oder
Direktiven gesetzt wurden. Dazu dient der Befehl \tty{MACEXP\_OVR}
(\ref{MACEXPOVR}), der auf in der Folge {\it expandierte} Makros wirkt. Auch
bei diesem Befehl gilt, da"s damit gegebene Direktiven zus"atzlich zu
denen in einem Makro hinterlegten und mit h"oherer Priorit"at wirken. Ein
\tty{MACEXP\_OVR} ohne jegliche Argumente schaltet so einen ''Override''
wieder ab.
%%- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
\ttindex{IRP}
ist die eine vereinfachte Form von Makrodefinitionen f"ur den Fall,
da"s eine Befehlsfolge einmal auf mehrere Operanden angewendet werden
soll und danach nicht mehr gebraucht wird. \tty{IRP} ben"otigt als ersten
Parameter ein Symbol f"ur den Operanden, und danach eine (fast)
beliebige Menge von Parametern, die nacheinander in den Befehlsblock
eingesetzt werden. Um eine Menge von Registern auf den Stack zu
schieben, kann man z.B. schreiben
\begin{verbatim}
IRP op, acc,b,dpl,dph
PUSH op
ENDM
\end{verbatim}
was in folgendem resultiert:
\begin{verbatim}
PUSH acc
PUSH b
PUSH dpl
PUSH dph
\end{verbatim}
Die Argumentliste darf analog zu einer Makro-Definition die
Steueranweisungen \tty{GLOBALSYMBOLS} bzw. \tty{NOGLOBALSYMBOLS} (durch
geschweifte Klammern als solche gekennzeichnet) enthalten, um zu
steuern, ob benutzte Labels f"ur jeden Durchgang automatisch lokal
sind oder nicht.
%%- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
\ttindex{IRPC}
\tty{IRPC} ist eine Variante von \tty{IRP}, bei der das erste Argument in
den bis \tty{ENDM} folgenden Zeilen nicht sukzessiv durch die weiteren
Parameter, sondern durch die Zeichen eines Strings ersetzt wird. Einen
String kann man z.B. also auch ganz umst"andlich so im Speicher ablegen:
\begin{verbatim}
irpc char,"Hello World"
db 'CHAR'
endm
\end{verbatim}
\bb{ACHTUNG!} Wie das Beispiel schon zeigt, setzt \tty{IRPC} nur das
Zeichen selber ein, da"s daraus ein g"ultiger Ausdruck entsteht (also hier
durch die Hochkommas, inklusive des Details, da"s hier keine automatische
Umwandlung in Gro"sbuchstaben vorgenommen wird), mu"s man selber
sicherstellen.
%%- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
\ttindex{REPT}
ist die einfachste Form der Makrobenutzung. Der im Rumpf angegebene
Code wird einfach sooft assembliert, wie der Integerparameter von
\tty{REPT} angibt. Dieser Befehl wird h"aufig in kleinen Schleifen anstelle
einer programmierten Schleife verwendet, um den Schleifenoverhead zu
sparen.
Der Vollst"andigkeit halber ein Beispiel:
\begin{verbatim}
REPT 3
RR a
ENDM
\end{verbatim}
rotiert den Akku um 3 Stellen nach rechts.
Ob Symbole f"ur jede einzelne Repetition lokal sind oder nicht,
kann wiederum durch die Steuerparameter \tty{GLOBALSYMBOLS} bzw.
\tty{NOGLOBALSYMBOLS} (durch geschweifte Klammern als solche
gekennzeichnet) bestimmt werden.
Ist das Argument von \tty{REPT} kleiner oder gleich Null, so wird
"uberhaupt keine Expansion durchgef"uhrt. Dies ist ein Unterschied
zu fr"uheren Versionen von \asname{}, die hier etwas ,,schlampig'' waren
und immer mindestens eine Expansion ausf"uhrten.
%%- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
\ttindex{WHILE}
\tty{WHILE} arbeitet analog zu \tty{REPT}, allerdings tritt an die
Stelle einer festen Anzahl als Argument ein boolescher Ausdruck, und
der zwischen \tty{WHILE} und \tty{ENDM} eingeschlossene Code wird sooft
assenbliert, bis der Ausdruck logisch falsch wird. Im Extremfall kann
dies bedeuten, da"s der Code "uberhaupt nicht assembliert wird, falls die
Bedingung bereits beim Eintritt in das Konstrukt falsch ist. Andererseits
kann es nat"urlich auch passieren, da"s die Bedingung immer wahr bleibt,
und \asname{} l"auft bis an das Ende aller Tage...hier sollte man also etwas
Umsicht walten lassen, d.h. im Rumpf mu"s eine Anweisung stehen, die die
Bedingung auch beeinflu"st, z.B. so:
\begin{verbatim}
cnt set 1
sq set cnt*cnt
while sq<=1000
dc.l sq
cnt set cnt+1
sq set cnt*cnt
endm
\end{verbatim}
Dieses Beispiel legt alle Quadratzahlen bis 1000 im Speicher ab.
Ein unsch"ones Detail bei \tty{WHILE} ist im Augenblick leider noch,
da"s am Ende der Expansion eine zus"atzliche Leerzeile, die im Quellrumpf
nicht vorhanden war, eingef"ugt wird. Dies ist ein ,,Dreckeffekt'',
der auf einer Schw"ache des Makroprozessors beruht und leider nicht so
einfach zu beheben ist. Hoffentlich st"ort es nicht allzusehr....
%%- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
\ttindex{EXITM}
\tty{EXITM} stellt einen Weg dar, um eine Makroexpansion oder einen der
Befehle \tty{REPT}, \tty{IRP} oder \tty{WHILE} vorzeitig abzubrechen.
Eine solche M"oglichkeit hilft zum Beispiel, umfangreichere Klammerungen
mit \tty{IF-ENDIF}-Sequenzen in Makros "ubersichtlicher zu gestalten.
Sinnvollerweise ist ein \tty{EXITM} aber selber auch immer bedingt, was zu
einem wichtigen Detail f"uhrt: Der Stack, der "uber momentan offene
\tty{IF}- oder \tty{SWITCH}-Konstrukte Buch f"uhrt, wird auf den Stand vor
Beginn der Makroexpansion zur"uck gesetzt. Dies ist f"ur bedingte
\tty{EXITM}'s zwingend notwendig, da das den \tty{EXITM}-Befehl in
irgendeiner Form einschlie"sende \tty{ENDIF} oder \tty{ENDCASE} nicht mehr
erreicht wird und \asname{} ohne einen solchen Trick eine Fehlermeldung erzeugen
w"urde. Weiterhin ist es f"ur verschachtelte Makrokonstruktionen
wichtig, zu beachten, da"s \tty{EXITM} immer nur das momentan innerste
Konstrukt abbricht! Wer aus seiner geschachtelten Konstruktion
vollst"andig ,,ausbrechen'' will, mu"s auf den h"oheren Ebenen ebenfalls
\tty{EXITM}'s vorsehen!
%%- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
\ttindex{SHIFT}\ttindex{.SHIFT}\ttindex{SHFT}
{\tt SHIFT} ist ein Mittel, um Makros mit variablen Argumentlisten
abzuarbeiten: Es verwirft den ersten Parameter, so da"s der zweite
Parameter seinen Platz einnimmt usw. Auf diese Weise k"onnte man
sich durch eine variable Argumentliste durcharbeiten...wenn man es richtig
macht. Folgendes funktioniert zum Beispiel {\em nicht}...
\begin{verbatim}
pushlist macro reg
rept ARGCOUNT
push reg
shift
endm
endm
\end{verbatim}
...weil das Makro {\em einmal} expandiert wird, seine Ausgabe von {\tt
REPT} aufgenommen und dann n-fach ausgef"uhrt wird. Das erste Argument
wird also n-fach gesichert...besser geht es schon so:
\begin{verbatim}
pushlist macro reg
if "REG"<>""
push reg
shift
pushlist ALLARGS
endif
endm
\end{verbatim}
Also eine Rekursion, in der pro Schritt die Argumentliste ({\tt ALLARGS})
um eins verk"urzt wird. Der wichtige Trick ist, da"s jedes Mal eine neue
Expansion gestartet wird...
Auf Plattformen, bei denen {\tt SHIFT} bereits eine Maschineninstruktion ist,
kann stattdessen {\tt SHFT} geschrieben werden, oder man spricht explizit
die Pseudoinstruktion durch einen vorangestellten Punkt (\tty{.SHIFT} anstelle
\tty{SHIFT}) an.
%%- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
\ttindex{MAXNEST}
Mit {\tt MAXNEST} kann man einstellen, wie oft ein Makro maximal rekursiv
aufgerufen werden kann, bevor \asname{} mit einer Fehlermeldung abbricht. Dies
darf ein beliebiger ganzer, positiver Wert sein, wobei der Sonderwert 0
diese Sicherheitsbremse komplett abschaltet (vorsicht damit...). Der
Vorgabewert f"ur die maximale Verschachtelungstiefe ist 256; die
momentane Einstellung kann aus einer gleichnamigen Variablen gelesen
werden.
%%- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
\ttindex{FUNCTION}
\tty{FUNCTION} ist zwar kein Makrobefehl im engeren Sinne, da
hierbei aber "ahnliche Mechanismen wie bei Makroersetzungen
angewendet werden, soll er hier beschrieben werden.
Dieser Befehl dient dazu, neue Funktionen zu definieren, die in
Formel\-ausdr"ucken wie die vordefinierten Funktionen verwendet werden
k"onnen. Die Definition mu"s in folgender Form erfolgen:
\begin{verbatim}
<Name> FUNCTION <Arg>,..,<Arg>,<Ausdruck>
\end{verbatim}
Die Argumente sind die Werte, die sozusagen in die Funktion
,,hineingesteckt'' werden. In der Definition werden f"ur die Argumente
symbolische Namen gebraucht, damit der Assembler bei der Benutzung
der Funktion wei"s, an welchen Stellen die aktuellen Werte einzusetzen
sind. Dies kann man an folgendem Beispiel sehen:
\begin{verbatim}
isgit FUNCTION ch,(ch>='0')&&(ch<='9')
\end{verbatim}
Diese Funktion "uberpr"uft, ob es sich bei dem Argument (wenn man es
als Zeichen interpretiert) um eine Ziffer im momentan g"ultigen
Zeichencode handelt (der momentane Zeichencode ist mittels \tty{CHARSET}
ver"anderbar, daher die vorsichtige Formulierung).
Die Argumentnamen (in diesem Falle \tty{CH}) m"ussen den gleichen h"arteren
Symbolkonventionen gen"ugen wie Parameter bei einer Makrodefinition,
d.h. die Sonderzeichen . und \_ sind nicht erlaubt.
Selbst definierte Funktionen werden genauso benutzt wie eingebaute,
d.h. mit einer durch Kommas getrennten, geklammerten Argumentliste:
\begin{verbatim}
IF isdigit(Zeichen)
message "\{Zeichen} ist eine Ziffer"
ELSEIF
message "\{Zeichen} ist keine Ziffer"
ENDIF
\end{verbatim}
Bei dem Aufruf der Funktion werden die Argumente nur einmal berechnet
und danach an allen Stellen der Formel eingesetzt, um den
Rechenaufwand zu reduzieren und Seiteneffekte zu vermeiden.
Bei Funktionen mit mehreren Argumenten m"ussen die einzelnen Argumente
bei der Benutzung durch Kommata getrennt werden.
\bb{ACHTUNG!} Analog wie bei Makros kann man mit der Definition von
Funktionen bestehende Funktionen umdefinieren. Damit lassen sich auch
wieder Phasenfehler provozieren. Solche Definitionen sollten daher auf
jeden Fall vor der ersten Benutzung erfolgen!
Da die Berechnung des Funktionsergebnisses anhand des Formelausdruckes
auf textueller Ebene erfolgt, kann der Ergebnistyp von dem Typ des
Eingangsargumentes abh"angen. So kann bei folgender Funktion
\begin{verbatim}
double function x,x+x
\end{verbatim}
das Ergebnis ein Integer, eine Gleitkommazahl oder sogar ein String
sein, je nach Typ des Arguments!
Bei der Definition und Ansprache von Funktionen wird im case-sensitiven
Modus zwischen Gro"s- und Kleinschreibung unterschieden, im Gegensatz
zu eingebauten Funktionen!
%%---------------------------------------------------------------------------
\ttindex{STRUCT}\ttindex{ENDSTRUCT}\ttindex{UNION}\ttindex{ENDUNION}
\ttindex{STRUC}\ttindex{ENDSTRUC}\ttindex{ENDS}
\ttindex{DOTTEDSTRUCTS}
{\em G"ultigkeit: alle Prozessoren}
Auch in Assemblerprogrammen ergibt sich dann und wann die Notwendigkeit,
analog zu Hochsprachen zusammengesetzte Datenstrukturen zu definieren.
\asname{} unterst"utzt sowohl die Definition als auch die Nutzung von Strukturen
mit einer Reihe von Konstrukten und Anweisungen, die im folgenden
erl"autert werden sollen:
Die Definition einer Struktur wird duch den Befehl \tty{STRUCT}
eingeleitet und durch \tty{ENDSTRUCT} abgeschlossen (schreibfaule
Zeitgenossen d"urfen aber auch stattdessen {\tt STRUC} bzw. {\tt
ENDSTRUC} oder {\tt ENDS} schreiben). Ein eventuell diesen Befehlen
voranstehendes Label wird als Name der zu definierenden Struktur
genommen; am Ende der Definition ist der Name optional und kann von
zur Festlegung des L"angennamens (s.u.) genutzt werden. Das
restliche Verfahren ist simpel: Mit einem \tty{STRUCT} wird der
momentane Programmz"ahler gesichert und auf Null zur"uck gesetzt.
Alle zwischen \tty{STRUCT} und \tty{ENDSTRUCT} definierten Labels
ergeben mithin die Offsets der einzelnen Datenfelder in der Struktur.
Die Reservierung des Platzes f"ur die einzelnen Felder erfolgt mit
den f"ur den jeweils aktiven Zielprozessor zul"assigen Befehlen zur
Speicherplatzreservierung, also z.B. \tty{DS.x} f"ur die Motorolas
oder \tty{DB} \& Co. f"ur Intels. Es gelten hier auch gleichfalls
die Regeln f"ur das Aufrunden von L"angen, um Alignments zu erhalten
- wer also 'gepackte' Strukturen definieren will, mu"s eventuell ein
{\tt PADDING OFF} voranstellen. Umgekehrt lassen sich Ausrichtungen
nat"urlich mit Befehlen wie {\tt ALIGN} erzwingen.
Da eine solche Definition nur eine Art 'Prototypen' darstellt, k"onnen nur
Befehle benutzt werden, die Speicherplatz reservieren, aber keine solchen,
die Konstanten im Speicher ablegen oder Code erzeugen.
Innerhalb von Strukturen definierte Labels (also die Namen der Elemente)
werden nicht direkt abgespeichert, sondern es wird ihnen der Name der
Struktur vorangestellt, durch ein Trennzeichen verbunden, bei dem es sich
defaultm"a"sig um den Unterstrich (\_) handelt. Dieses Verhalten l"a"st
sich aber durch dem \tty{STRUCT}-Befehl mitgegebene Argumente steuern:
\begin{itemize}
\item{\tty{NOEXTNAMES} unterdr"uckt das Voranstellen des Strukturnamens.
Der Programmierer ist in diesem Falle selber daf"ur verantworlich,
da"s Feldnamen nicht mehrfach verwendet werden.}
\item{\tty{DOTS} weist \asname{} an, als verbindendes Zeichen einen Punkt
anstelle des Unterstriches zu verwenden. Es sei jedoch
ausdr"ucklich darauf hingewiesen, da"s der Punkt bei vielen
Zielprozessoren ein Sonderfunktion zur Bitadressierung hat und
diese zu Problemen f"uhren kann!}
\end{itemize}
Des weiteren ist es m"oglich, die Verwendung des Punktes durch den Befehl
\begin{verbatim}
dottedstructs <on|off>
\end{verbatim}
dauerhaft ein- bzw. auszuschalten.
Neben den Namen der Elemente definiert \asname{} beim Abschlu"s der Definition
ein weiteres Symbol mit dem Namen {\tt LEN}, das nach dem gleichen Regeln
um den Namen der Struktur erweitert wird - oder um den Label-Namen, der
optional bei \tty{ENDSTRUCT} angegeben werden kann.
Das ganze sieht dan in der Praxis z.B. so aus:
\begin{verbatim}
Rec STRUCT
Ident db ?
Pad db ?
Pointer dd ?
Rec ENDSTRUCT
\end{verbatim}
Hier w"urde z.B. dem Symbol {\tt REC\_LEN} der Wert 6 zugewiesen.
Ist eine Struktur einmal definiert, ist die Nutzung denkbar einfach und
"ahnlich wie ein Makro: ein einfaches
\begin{verbatim}
thisrec Rec
\end{verbatim}
reserviert Speicher in der Menge, wie er von der Struktur belegt wird, und
definiert gleichzeitig f"ur jedes Element der Struktur ein passendes
Symbol mit dessen Adresse, in diesem Falle also {\tt THISREC\_IDENT,
THISREC\_PAD} und {\tt THISREC\_POINTER}. Das Label darf bei dem Aufruf
einer Struktur naturgem"a"s nicht fehlen; wenn doch, gibt's eine
Fehlermeldung.
"Uber zus"atzliche Argumente ist es m"oglich, nicht nur Speicher f"ur eine
einzelne Struktur, sondern ein ganzes Feld davon zu reservieren. Die (bis zu
drei) Dimensionen werden "uber in eckige Klammern gesetzte Argumente definiert:
\begin{verbatim}
thisarray Rec [10],[2]
\end{verbatim}
In diesem Beispiel wird Platz f"ur $2*10=20$ Strukturen reserviert, und f"ur
jede Einzelstruktur werden Symbole erzeugt, die die Indizes im Namen enthalten.
Es ist ohne weiteres erlaubt, eine bereits definierte Struktur in einer
anderen Struktur aufzurufen. Das dabei ablaufende Verfahren ist eine
Kombination aus den beiden vorigen Punkten: Elemente der Substruktur
werden definiert, mit dem Namen dieser Instanz vorangestellt, und vor
diese zusammengesetzten Namen wird wieder der Name der Struktur bzw.
sp"ater bei einer Benutzung gesetzt. Das sieht dann z.B. so aus:
\begin{verbatim}
TreeRec struct
left dd ?
right dd ?
data Rec
TreeRec endstruct
\end{verbatim}
Ebenso ist es erlaubt, eine Struktur direkt in einer anderen
Struktur zu definieren:
\begin{verbatim}
TreeRec struct
left dd ?
right dd ?
TreeData struct
name db 32 dup(?)
id dw ?
TreeData endstruct
TreeRec endstruct
\end{verbatim}
Eine Union ist eine Sonderform einer Struktur, bei der die einzelnen
Elemente nicht hintereinander, sondern {\em "ubereinander} liegen, d.h.
alle Elemente liegen an Startadresse 0 innerhalb der Struktur und belegen
den gleichen Speicherplatz. Naturgem"a"s tut so eine Definition nicht
mehr, als einer Reihe von Symbolen den Wert Null zuzuweisen, sie kann aber
sinnvoll sein, um programmtechnisch die "Uberlappung der Elemente zu
verdeutlichen und den Code so etwas 'lesbarer' zu gestalten. Die Gr"o"se
einer Struktur ist das Maximum der Gr"o"sen aller Elemente.
Der Name einer Struktur oder Union ist optional, allerdings nur, wenn
diese Teil einer anderen, nicht namenlosen Struktur ist. Elemente
dieser Struktur werden dann Teil der 'n"achsth"oheren' benamten
Struktur:
\begin{verbatim}
TreeRec struct
left dd ?
right dd ?
struct
name db 32 dup(?)
id dw ?
endstruct
TreeRec endstruct
\end{verbatim}
erzeugt also die Symbole {\tt TREEREC\_NAME} und {\tt TREEREC\_ID}.
Des weiteren wird f"ur namenlose Strukturen oder Unions kein Symbol
mit deren L"ange angelegt.
Im Verlaufe der Definition oder der Nutzung von Strukturen definierte
Symbole werden genauso behandelt wie normale Symbole, d.h. bei der Nutzung
innerhalb einer Sektion werden diese Symbole als lokal zu dieser Sektion
definiert. Analoges gilt aber auch f"ur die Strukturen selber, d.h. eine
innerhalb einer Sektion definierte Struktur kann nicht au"erhalb der
Sektion benutzt werden.
Will man Strukturen "uber Makros instanziieren, so mu"s man die
\tty{GLOBALSYMBOLS}-Option bei der Definition des Makros
benutzen, damit die dar"uber erzeugten Symbole auch au"serhalb
des Makros verwendbar sind. Eine Reihe von Strukturen kann man
z.B. so anlegen:
\begin{verbatim}
irp name,{GLOBALSYMBOLS},rec1,rec2,rec3
name Rec
endm
\end{verbatim}
%%---------------------------------------------------------------------------
{\em G"ultigkeit: alle Prozessoren}
Der Assembler unterst"utzt die bedingte Assemblierung mit Hilfe der
Konstrukte \tty{IF}... sowie \tty{SWITCH}... . Diese Befehle wirken zur
Assemblierzeit, indem entsprechend der Bedingung Teile "ubersetzt oder
"ubersprungen werden. Diese Befehle sind also \ii{nicht} mit den
IF-Statements h"oherer Programmiersprachen zu vergleichen (obwohl es
sehr verlockend w"are, den Assembler um die Strukturierungsbefehle
h"oherer Sprachen zu erweitern...).
Die folgenden Konstrukte d"urfen beliebig (bis zum Speicher"uberlauf)
geschachtelt werden.
%%- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
\ttindex{IF}
\ttindex{ELSEIF}\ttindex{ELSE}
\ttindex{ENDIF}
\tty{IF} ist das gebr"auchlichere und allgemeiner verwendbare Konstrukt.
Die allgemeine Form eines \tty{IF}-Befehles lautet folgenderma"sen:
\begin{verbatim}
IF <Ausdruck 1>
<Block 1>
ELSEIF <Ausdruck 2>
<Block 2>
(evtl. weitere ELSEIFs)
ELSEIF
<Block n>
ENDIF
\end{verbatim}
\tty{IF} dient als Einleitung und wertet den ersten Ausdruck aus und assembliert
Block 1, falls der Ausdruck wahr (d.h. ungleich 0) ist. Alle weiteren
\tty{ELSEIF}-Teile werden dann ignoriert. Falls der Ausdruck aber nicht wahr
ist, wird Block 1 "ubersprungen und Ausdruck 2 ausgewertet. Sollte dieser
nun wahr sein, wird Block 2 assembliert. Die Zahl der \tty{ELSEIF}-Teile ist
variabel und ergibt eine \tty{IF-THEN-ELSE}-Leiter beliebiger L"ange. Der dem
letzten \tty{ELSEIF} (ohne Parameter) zugeordnete Block wird nur assembliert,
falls alle vorigen Ausdr"ucke falsch ergaben und bildet sozusagen einen
,,Default-Zweig''. Wichtig ist, da"s von den Bl"ocken immer nur \ii{einer}
assembliert wird, und zwar der erste, dessen zugeordnetes \tty{IF/ELSEIF} einen
wahren Ausdruck hatte.
Die \tty{ELSEIF}-Teile sind optional, d.h. auf \tty{IF} darf auch direkt \tty{ENDIF}
folgen, ein parameterloses \tty{ELSEIF} bildet aber immer den letzten Zweig.
Ein \tty{ELSEIF} bezieht sich immer auf das letzte, noch nicht abgeschlossene \tty{IF}.
Neben \tty{IF} sind noch folgende weitere bedingte Befehle definiert:
\ttindex{IFDEF}\ttindex{IFNDEF}
\ttindex{IFUSED}\ttindex{IFNUSED}
\ttindex{IFEXIST}\ttindex{IFNEXIST}
\ttindex{IFB}\ttindex{IFNB}
\begin{itemize}
\item{\tty{IFDEF} $<$Symbol$>$ : wahr, falls das Symbol definiert wurde.
Die Definition mu"s vor \tty{IFDEF} erfolgt sein.}
\item{\tty{IFNDEF} $<$Symbol$>$ : Umkehrung zu \tty{IFDEF}}
\item{\tty{IFUSED} $<$Symbol$>$ : wahr, falls das Symbol bisher mindestens einmal
benutzt wurde.}
\item{\tty{IFNUSED} $<$Symbol$>$ : Umkehrung zu \tty{IFUSED}}
\item{\tty{IFEXIST} $<$Name: $>$ : wahr, falls die angegebene Datei existiert.
F"ur Schreibweise und Suchpfade gelten gleiche Regeln wie beim
\tty{INCLUDE}-Befehl (siehe Abschnitt \ref{SectInclude}).}
\item{\tty{IFNEXIST} $<$Name: $>$ : Umkehrung zu \tty{IFEXIST}}
\item{\tty{IFB} $<$Arg-Liste$>$ : wahr, falls alle Argumente der Parameterliste leer
sind.}
\item{\tty{IFNB} $<$Arg-Liste$>$ : Umkehrung zu IFB.}
\end{itemize}
Anstelle von {\tt ELSEIF} darf auch {\tt ELSE} geschrieben werden, weil
das wohl alle so gewohnt sind....
Zu jeder {\tt IF...}-Anweisung geh"ort ein entsprechendes {\tt ENDIF},
'offene' Konstrukte f"uhren zu einer Fehlermeldung am Ende des
Assemblierungslaufes. Die Zuordnung, welches {\tt ENDIF} \asname{} mit welchem
{\tt IF...} 'gepaart' hat, l"a"st sich im Listing erkennen: dort wird die
Zeilennummer des entsprechenden {\tt IF}s angezeigt.
%%- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
\ttindex{SWITCH}\ttindex{.SWITCH}\ttindex{SELECT}
\ttindex{CASE}\ttindex{ELSECASE}\ttindex{ENDCASE}
\tty{SWITCH} ist ein Spezialfall von \tty{IF} und f"ur den Fall gedacht, da"s ein
Ausdruck mit einer Reihe von Werten verglichen werden soll. Dies ist
nat"urlich auch mit \tty{IF} und einer Reihe von \tty{ELSEIF}s machbar, die folgende
Form
\begin{verbatim}
SWITCH <Ausdruck>
...
CASE <Wert 1>
...
<Block 1>
...
CASE <Wert 2>
...
<Block 2>
...
(weitere CASE-Konstrukte)
...
CASE <Wert n-1>
...
<Block n-1>
...
ELSECASE
...
<Block n>
...
ENDCASE
\end{verbatim}
bietet aber den Vorteil, da"s der zu pr"ufende Ausdruck nur einmal hingeschrieben
und berechnet werden mu"s, er ist also weniger fehleranf"allig und etwas
schneller als eine \tty{IF}-Kette, daf"ur nat"urlich auch nicht so flexibel.
Es ist m"oglich, bei den \tty{CASE}-Anweisungen mehrere, durch Kommata getrennte
Werte anzugeben, um den entsprechenden Block in mehreren F"allen assemblieren
zu lassen. Der \tty{ELSECASE}-Zweig dient wiederum als ,,Auffangstelle'' f"ur den
Fall, da"s keine der \tty{CASE}-Bedingungen greift. Fehlt er und fallen alle
Pr"ufungen negativ aus, so gibt \asname{} eine Warnung aus.
Auch wenn die Wertelisten der \tty{CASE}-Teile sich "uberlappen, so wird immer
nur \ii{ein} Zweig ausgef"uhrt, und zwar bei Mehrdeutigkeiten der erste.
\tty{SWITCH} dient nur der Einleitung des ganzen Konstruktes; zwischen ihm und
dem ersten \tty{CASE} darf beliebiger Code stehen (andere \tty{IF}s d"urfen aber nicht
offen bleiben!), im Sinne eines durchschaubaren Codes sollte davon aber
kein Gebrauch gemacht werden.
Ist \tty{SWITCH} auf dem gew"ahlten Target ein Maschinenbefehl,
so leitet man das Konstrukt stattdessen mit \tty{SELECT} ein, oder spricht
den Pseudobefehl explizit durch einen vorangestellten Punk an (\tty{.SWITCH}
anstelle von \tty{SWITCH}).
"Ahnlich wie bei {\tt IF...}-Konstrukten, mu"s es f"ur jedes {\tt SWITCH}
genau ein {\tt ENDCASE} geben. Analog zu {\tt ENDIF} wird bei {\tt ENDCASE}
im Listing die Zeilennummer des korrespondierenden {\tt SWITCH} angezeigt.
%%---------------------------------------------------------------------------
{\em G"ultigkeit: alle Prozessoren}
%%- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
\ttindex{PAGE}\ttindex{.PAGE}\ttindex{PAGESIZE}
Mit \tty{PAGE} kann man \asname{} die Dimensionen des Papiers, auf dem das
Listing ausgedruckt werden soll, mitteilen. Als erster Parameter
wird dabei die Anzahl von Zeilen angegeben, nach der \asname{} automatisch
einen Zeilenvorschub ausgeben soll. Zu ber"ucksichtigen ist allerdings,
da"s bei dieser Angabe die Kopfzeilen inklusive einer evtl. mit \tty{TITLE}
spezifizierten Zeile nicht mitgerechnet werden. Der Minimalwert f"ur
die Zeilenzahl ist 5, der Maximalwert 255. Eine Angabe von 0 f"uhrt dazu,
da"s \asname{} "uberhaupt keine automatischen Seitenvorsch"ube ausf"uhrt, sondern
nur noch solche, die explizit durch \tty{NEWPAGE}-Befehle oder implizit am
Ende des Listings (z.B. vor der Symboltabelle) von \asname{} ausgel"ost
wurden.
Die Angabe der Breite des Listings in Zeichen kann als optionaler
zweiter Parameter erfolgen und erf"ullt zwei Zwecke: Zum einen l"auft
der Zeilenz"ahler von \asname{} korrekt weiter, wenn eine Quell-Zeile "uber mehrere
Listing-Zeilen geht, zum anderen gibt es Drucker (wie z.B. Laserdrucker),
die beim "Uberschreiten des rechten Randes nicht automatisch in eine neue
Zeile umbrechen, sondern den Rest einfach ,,verschlucken''. Aus diesem
Grund f"uhrt \asname{} auch den Zeilenumbruch selbstst"andig durch, d.h. zu lange
Zeilen werden in Bruchst"ucke zerlegt, die eine L"ange kleiner oder
gleich der eingestellten L"ange haben. In Zusammenhang mit Druckern, die
einen automatischen Zeilenumbruch besitzen, kann das aber zu doppelten
Zeilenvorsch"uben f"uhren, wenn man als Breite exakt die Zeilenbreite des
Druckers angibt. Die L"osung in einem solchen Fall ist, als Zeilenbreite
ein Zeichen weniger anzugeben. Die eingestellte Zeilenbreite darf zwischen
5 und 255 Zeichen liegen; analog zur Seitenl"ange bedeutet ein Wert von 0,
da"s \asname{} keine Splittung der Listing-Zeilen vornehmen soll; eine
Ber"ucksichtigung von zu langen Zeilen im Listing beim Seitenumbruch kann
dann nat"urlich auch nicht mehr erfolgen.
Die Defaulteinstellung f"ur die Seitenl"ange ist 60 Zeilen, f"ur die
Zeilenbreite 0; letztere Wert wird auch angenommen, wenn \tty{PAGE} nur mit
einem Argument aufgerufen wird.
Falls \tty{PAGE} auf dem gew"ahlten Target bereits ein Maschinenbefehl ist,
benutzt man stattdessen \tty{PAGESIZE}. Alternativ ist es immer m"oglich,
durch Voranstellen eines Punktes (\tty{.PAGE} anstelle \tty{PAGE}) explizit
den Pseudobefehl anzusprechen.
\bb{ACHTUNG!} \asname{} hat keine M"oglichkeit, zu "uberpr"ufen, ob die
eingestellte Listing-L"ange und Breite mit der Wirklichkeit "ubereinstimmen!
%%- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
\ttindex{NEWPAGE}
\tty{NEWPAGE} kann dazu benutzt werden, einen Seitenvorschub zu erzwingen,
obwohl die Seite noch gar nicht voll ist. Dies kann z.B. sinnvoll
sein, um logisch voneinander getrennte Teile im Assemblerprogramm
auch seitenm"a"sig zu trennen. Der programminterne Zeilenz"ahler wird
zur"uck gesetzt, der Seitenz"ahler um Eins heraufgez"ahlt. Der optionale
Parameter steht in Zusammenhang mit einer hierarchischen Seitennumerierung,
die \asname{} bis zu einer Kapiteltiefe von 4 unterst"utzt. 0 bedeutet dabei
immer die tiefste Kapitelebene, der Maximalwert kann sich w"ahrend des
Laufes ver"andern, wenn das auch verwirrend wirken kann, wie folgendes
Beispiel zeigt:
\begin{quote}\begin{tabbing}
Seite 1, \> Angabe \tty{NEWPAGE 0} \> $\rightarrow$ Seite 2 \\
Seite 2, \> Angabe \tty{NEWPAGE 1} \> $\rightarrow$ Seite 2.1 \\
Seite 2.1, \> Angabe \tty{NEWPAGE 1} \> $\rightarrow$ Seite 3.1 \\
Seite 3.1, \> Angabe \tty{NEWPAGE 0} \> $\rightarrow$ Seite 3.2 \\
Seite 3.2, \> Angabe \tty{NEWPAGE 2} \> $\rightarrow$ Seite 4.1.1 \\
\end{tabbing}\end{quote}
Je nach momentan vorhandener Kapiteltiefe kann \tty{NEWPAGE $<$Nummer$>$}
also an verschiedenen Stellen eine Erh"ohung bedeuten. Ein automatischer
Seitenvorschub wegen Zeilen"uberlauf oder ein fehlender Parameter ist
gleichbedeutend mit \tty{NEWPAGE 0}. Am Ende des Listings wird vor Ausgabe
der Symboltabelle ein implizites \tty{NEWPAGE $<$bish. Maximum$>$} durchgef"uhrt,
um sozusagen ein neues Hauptkapitel zu beginnen.
%%- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
\ttindex{MACEXP}
\ttindex{MACEXP\_DFT}
\ttindex{MACEXP\_OVR}
Ist ein Makro einmal ausgestestet und 'fertig', m"ochte man es bei
Benutzung vielleicht gar nicht mehr im Listing sehen. Wie im
Abschnitt "uber Makros (\ref{SectMacros}) erl"autert, kann man bei der
Definition eines Makros "uber Zusatzargumente steuern, ob und wenn ja
welche Teile des Makro-Rumpfes im Listing expandiert werden. F"ur den
Fall, da"s eine ganze Reihe von Makros in Folge definiert werden,
mu"s man dies jedoch nicht f"ur jedes Makro einzeln festlegen. Der
Befehl \tty{MACEXP\_DFT} setzt f"ur alle im folgenden definerten Makros,
welche Teile ihres Rumpfes expandiert werden sollen:
\begin{itemize}
\item{\tty{ON} bzw. \tty{OFF} schalten die Expansion komplett
ein bzw. aus.}
\item{Mit den Argumenten \tty{IF} bzw. \tty{NOIF} werden Befehle
im Rumpf zur bedingten Assemblierung und derentwegen nicht
assemblierte Code-Teile aus- bzw. eingeblendet.}
\item{Makro-Definitionen (dazu z"ahlen auch \tty{REPT},
\tty{WHILE} und \tty{IRP(C)}) k"onnen "uber die Argumente
\tty{MACRO} bzw. \tty{NOMACRO} ein- und
ausgeblendet werden.}
\item{Mit den Argumenten \tty{REST} bzw. \tty{NOREST} k"onnen die
Zeilen ein- und ausgeblendet werden, die nicht in die ersten
beiden Klassen fallen.}
\end{itemize}
Default ist \tty{ON}, d.h. im folgenden definierte Makros werden
komplett expandiert, au"ser nat"urlich bei den einzelnen Makros wurde
dies durch Direktiven "ubersteuert. Weiterhin wirken angegebene Schalte
relativ zur aktuellen Einstellung: ist z.B. initial alles eingeschaltet,
sorgt ein
\begin{quote}{\tt
MACEXP\_DFT noif,nomacro
}\end{quote}
daf"ur, da"s nur noch das gelistet wird, was weder eine Makrodefinition
ist noch per bedingter Assemblierung ausgeschlossen wurde.
Mit diesem Befehl und den pro Makro setzbaren Direktiven l"a"st sich
f"ur jedes einzelne Makro genau festlegen, welche Teile bei einer
Expansion im Listing erscheinen sollen und welche nicht. Es kann
jedoch in der Praxis auch vorkommen, da"s man ein bestimmtes Makro an
einzelnen Stellen im Quellcode expandiert haben m"ochte, an anderen
jedoch nicht. Dies ist mit dem Befehl \tty{MACEXP\_OVR} m"oglich: er
akzeptiert die gleichen Argumente, diese wirken jedoch als Overrides
f"ur alle im folgenden {\em expandierten} Makros, im Gegensatz zu
\tty{MACEXP\_DFT}, das auf alle im folgenden {\em definierten} Makros
wirkt. Ist zum Beispiel f"ur ein Makro festgelegt worden, da"s weder
Makrodefinitionen noch per bedingte Assemblierung ausgeschlossene
Teile gelistet werden sollen, so schaltet ein
\begin{quote}{\tt
MACEXP\_OVR MACRO
}\end{quote}
f"ur folgende Expansionen das Listen von Makrodefinitionen wieder ein,
w"ahrend ein
\begin{quote}{\tt
MACEXP\_OVR ON
}\end{quote}
wieder alles ins Listing expandiert. \tty{MACEXP\_OVR} ohne
Argumente schaltet wiederum s"amtliche Overrides aus, Makros
verhalten sich bei der Expansion wieder so, wie zum Zeitpunkt ihrer
Definition festgelegt.
Beide Befehle wirken ebenfalls auf andere Makro-artige Konstrukte
(\tty{REPT, IRP, IRPC WHILE}), da diese aber einmalig ,,in-place''
expandiert werden, verschwimmt der funktionale Unterschied zwischen
den beiden Befehlen - im Zweifelsfalle hat aber der per
\tty{MACEXP\_OVR} gesetzte Override eine h"ohere Priorit"at.
Die momentane mit \tty{MACEXP\_DFT} gesetzte Einstellung l"a"st sich
aus dem Symbol \tty{MACEXP} auslesen. Anstelle von \tty{MACEXP\_DFT}
darf auch einfach \tty{MACEXP} geschrieben werden, davon sollte aber
in neuen Programmen kein Gebrauch mehr gemacht werden.
%%- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
\ttindex{LISTING}
Mit diesem Befehl kann das Listing komplett ein- und ausgeschaltet
werden. Nach einem
\begin{verbatim}
LISTING off
\end{verbatim}
wird \ii{"uberhaupt} nichts mehr im Listing ausgegeben. Diese Anweisung
macht Sinn f"ur erprobte Codeteile oder Include-Dateien, um den
Papierverbrauch nicht ins Unerme"sliche zu steigern. \bb{ACHTUNG!}
Wer sp"ater das Gegenst"uck vergi"st, bekommt auch keine Symboltabelle
mehr zu sehen! Zus"atzlich zu \tty{ON} und \tty{OFF} akzeptiert
\tty{LISTING} auch \tty{NOSKIPPED} und \tty{PURECODE} als Argument. Mit
der \tty{NOSKIPPED}-Einstellung werden aufgrund bedingter Assemblierung
nicht assemblierte Teile nicht im Listing aufgef"uhrt, w"ahrend
\tty{PURECODE} - wie der Name schon erahnen l"a"st - auch die
\tty{IF}-Konstrukte selber nicht mehr im Listing auff"uhrt. Diese
Einstellungen sind n"utzlich, wenn man Makros, die anhand von
Parametern verschiedene Aktionen ausf"uhren, benutzt, und im Listing
nur noch die jeweils benutzten Teile sehen m"ochte.
Die momentane Einstellung l"a"st sich aus dem Symbol \tty{LISTING}
(0=\tty{OFF}, 1=\tty{ON}, 2=\tty{NOSKIPPED}, 3=\tty{PURECODE}) auslesen.
%%- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
\ttindex{PRTINIT}\ttindex{PRTEXIT}
Bei der Listingausgabe auf Druckern ist es oftmals sinnvoll, den
Drucker in eine andere Betriebsart (z.B. Schmalschrift) umzuschalten
und am Ende des Listings diese Betriebsart wieder zu deaktivieren. Mit
diesen Befehlen kann die Ausgabe dieser Steuerfolgen automatisiert
werden, indem man mit
\begin{verbatim}
PRTINIT <String>
\end{verbatim}
die Zeichenfolge angibt, die vor Listingbeginn an das Ausgabeger"at
geschickt werden soll und mit
\begin{verbatim}
PRTEXIT <String>
\end{verbatim}
analog den Deinitialisierungsstring. In beiden F"allen mu"s
\tty{$<$String$>$} ein Stringausdruck sein. Die Syntaxregeln f"ur
Stringkonstanten erm"oglichen es, ohne Verrenkungen Steuerzeichen in den
String einzubauen.
Bei der Ausgabe dieser Strings unterscheidet der Assembler \bb{nicht},
wohin das Listing geschickt wird, d.h. Druckersteuerzeichen werden
r"ucksichtslos auch auf den Bildschirm geschickt!
Beispiel :
Bei Epson-Druckern ist es sinnvoll, f"ur die breiten Listings
in den Kompre"sdruck zu schalten. Die beiden Zeilen
\begin{verbatim}
PRTINIT "\15"
PRTEXIT "\18"
\end{verbatim}
sorgen daf"ur, da"s der Kompre"sdruck ein- und nach dem Druck wieder
ausgeschaltet wird.
%%- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
\ttindex{TITLE}
Normalerweise versieht der Assembler bereits jede Listingseite mit
einer Titelzeile, die Quelldatei, Datum und Uhrzeit enth"alt. Mit
diesem Befehl kann man den Seitenkopf um eine beliebige zus"atzliche
Zeile erweitern. Der anzugebende String ist dabei ein beliebiger
Stringausdruck.
Beispiel:
Bei dem bereits oben angesprochenenen Epson-Drucker soll eine Titelzeile
im Breitdruck ausgegeben werden, wozu vorher der Kompre"smodus
abgeschaltet werden mu"s:
\begin{verbatim}
TITLE "\18\14Breiter Titel\15"
\end{verbatim}
(Epson-Drucker schalten den Breitdruck automatisch am Zeilenende aus.)
%%- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
\ttindex{RADIX}
\ttindex{DECIMAL}
\ttindex{OCTAL}
\tty{RADIX} mit einem numerischen Argument zwischen 2 und 36 legt das
Default-Zahlensystem f"ur Integer-Konstanten fest, d.h. das Zahlensystem,
das angenommen wird, wenn man nichts ausdr"ucklich anderes angegeben hat.
Defaultm"a"sig ist dies 10, und bei der Ver"anderung dieses Wertes sind
einige Fallstricke zu beachten, die in Abschnitt \ref{SectIntConsts}
beschrieben sind.
Unabh"angig von der momentanen Einstellung ist das Argument von {\tt
RADIX} {\em immer dezimal}; weiterhin d"urfen keine symbolischen oder
Formelausdr"ucke verwendet werden, sondern nur einfache Zahlenkonstanten!
Auf dem IM61x0 stehen die Anweisungen \tty{DECIMAL} und \tty{OCTAL} zur
Verf"ugung, dies sind Kurzschreibweisen f"ur \tty{RADIX 10} beziehungsweise
\tty{RADIX 8}.
%%- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
\ttindex{OUTRADIX}
\tty{OUTRADIX} is gewisserma"sen das Gegenst"uck zu \tty{RADIX}: Mit ihm
kann man festlegen, in welchem Zahlensystem berechnete Integer-Ausdr"ucke
in Strings eingesetzt werden sollen, wenn man \verb!\{...}!-Konstrukte in
Stringkonstanten verwendet (siehe Abschnitt \ref{SectStringConsts}). Als
Argument sind wieder Werte zwischen 2 und 36 erlaubt; der Default ist 16.
%%---------------------------------------------------------------------------
{\em G"ultigkeit: alle Prozessoren}
Bei den lokalen Labels und den dazu eingef"uhrten Sektionen handelt es
sich um eine grundlegend neue Funktion, die mit Version 1.39 eingef"uhrt
wird. Da dieser Teil sozusagen ,,1.0'' ist, ist er sicherlich noch nicht
der Weisheit letzter Schlu"s. Anregungen und (konstruktive) Kritik sind
daher besonders erw"unscht. Insbesondere habe ich die Verwendung von
Sektionen hier so dargestellt, wie ich sie mir vorstelle. Es kann dadurch
passiert sein, da"s die Realit"at nicht ganz meinem Modell im Kopf entspricht.
F"ur den Fall von Diskrepanzen verspreche ich, da"s die Realit"at der
Dokumentation angepa"st wird, und nicht umgekehrt, wie es bei gr"o"seren
Firmen schon einmal vorgekommen sein soll...
\asname{} erzeugt keinen linkf"ahigen Code (und wird es wohl auch nicht in n"aherer
Zukunft tun \tty{:-(} ). Diese Tatsache zwingt dazu, ein Programm immer im ganzen
zu "ubersetzen. Dieser Technik gegen"uber h"atte eine Aufteilung in
Linker-Module einige Vorteile:
\begin{itemize}
\item{k"urzere "Ubersetzungszeiten, da lediglich die ge"anderten Module
neu "ubersetzt werden m"ussen;}
\item{die M"oglichkeit, durch Definition "offentlicher und privater
Symbole definierte Schnittstellen zwischen den Modulen festzulegen;}
\item{Durch die geringere L"ange der einzelnen Module reduziert sich die
Anzahl der Symbole im einzelnen Modul, so da"s k"urzere und trotzdem
eindeutige Symbolnamen benutzt werden k"onnen.}
\end{itemize}
Insbesondere der letzte Punkt hat mich pers"onlich immer etwas gest"ort:
War ein Label-Name einmal am Anfang eines 2000 Zeilen langen Programms
benutzt, so durfte er nirgendwo wieder verwendet werden --- auch nicht am
anderen Ende des Quelltextes, wo Routinen mit ganz anderem Kontext standen.
Ich war dadurch gezwungen, zusammengesetzte Namen der Form
\begin{verbatim}
<Unterprogrammname>_<Symbolname>
\end{verbatim}
zu verwenden, die dann L"angen zwischen 15 und 25 Zeichen hatten und das
Programm un"ubersichtlich machten.
Das im folgenden eingehender beschriebene Sektionen-Konzept sollte zumindest
den beiden letzten genannten Punkten abhelfen. Es ist vollst"andig optional:
Wollen Sie keine Sektionen verwenden, so lassen Sie es einfach bleiben
und arbeiten weiter wie unter den "alteren \asname{}-Versionen.
%%- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Eine \ii{Sektion} stellt einen durch spezielle Befehle eingerahmten
Teil des Assembler-Programms dar und hat einen vom Programmierer
festlegbaren, eindeutigen Namen:
\begin{verbatim}
...
<anderer Code>
...
SECTION <Sektionsname>
...
<Code in der Sektion>
...
ENDSECTION [Sektionsname]
...
<anderer Code>
...
\end{verbatim}
Der Name f"ur eine Sektion mu"s den Konventionen f"ur einen Symbolnamen
entsprechen; da \asname{} Sektions-und Symbolnamen in getrennten Tabellen speichert,
darf ein Name sowohl f"ur ein Symbol als auch eine Sektion verwendet werden.
Sektionsnamen m"ussen in dem Sinne eindeutig sein, da"s auf einer Ebene
nicht zwei Sektionen den gleichen Namen haben d"urfen (was es mit den
,,Ebenen'' auf sich hat, erl"autere ich im n"achsten Abschnitt). Das Argument
zu \tty{ENDSECTION} ist optional, es darf auch weggelassen werden; Falls
es weggelassen wird, zeigt \asname{} den Namen der Sektion an, der er das
\tty{ENDSECTION} zugeordnet hat. Code in einer Sektion wird von \asname{} genauso
behandelt wie au"serhalb, lediglich mit drei entscheidenden Unterschieden:
\begin{itemize}
\item{Innerhalb der Sektion definierte Symbole (z.B. Labels, \tty{EQU}s...) werden
mit einer von \asname{} intern vergebenen, der Sektion zugeordneten Nummer
versehen. Diese Symbole sind von Code au"serhalb der Sektion nicht
ansprechbar (das l"a"st sich nat"urlich durch Pseudobefehle variieren,
aber dazu sp"ater mehr).}
\item{Durch das zus"atzliche Attribut kann ein Symbolname sowohl au"serhalb
der Sektion als auch innerhalb definiert werden, das Attribut erlaubt
also, Symbolnamen mehrfach zu benutzen, ohne da"s \asname{} Protest anmeldet.}
\item{Falls ein Symbol sowohl au"serhalb als auch innerhalb definiert ist,
wird innerhalb der Sektion das ,,lokale'' verwendet, d.h. \asname{} sucht
in der Symboltabelle zuerst nach einem Symbol des gew"unschten Namens,
das auch gleichzeitig der Sektion zugeordnet wurde. Erst danach wird
nach einem globalen Symbol dieses Namens gefahndet.}
\end{itemize}
Mit diesem Mechanismus kann man z.B. den Code in Module aufteilen, wie man
es mit einem Linker getan h"atte. Eine feinere Aufteilung w"are dagegen,
alle Routinen in getrennte Sektionen zu verpacken. Je nach L"ange der
Routinen k"onnen die nur intern ben"otigten Symbole dann sehr kurze Namen
haben.
Defaultm"a"sig unterscheidet \asname{} Gro"s-und Kleinschreibung in Sektions-
namen nicht; schaltet man jedoch in den case-sensitiven Modus um, so
wird die Schreibweise genauso wie bei Symbolnamen ber"ucksichtigt.
Die bisher beschriebene Aufteilung w"urde in etwa der Sprache C entsprechen,
in der alle Funktionen auf gleicher Ebene nebeneinander stehen. Da mein
,,hochsprachliches'' Vorbild aber Pascal ist, bin ich noch einen Schritt
weiter gegangen:
%%- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
\subsection{Verschachtelung und Sichtbarkeitsregeln}
Es ist erlaubt, in einer Sektion weitere Sektionen zu definieren, analog
zu der M"oglichkeit in Pascal, in einer Prozedur/Funktion weitere
Prozeduren zu definieren. Dies zeigt folgendes Beispiel:
\begin{verbatim}
sym EQU 0
SECTION ModulA
SECTION ProcA1
sym EQU 5
ENDSECTION ProcA1
SECTION ProcA2
sym EQU 10
ENDSECTION ProcA2
ENDSECTION ModulA
SECTION ModulB
sym EQU 15
SECTION ProcB
ENDSECTION ProcB
ENDSECTION ModulB
\end{verbatim}
Bei der Suche nach einem Symbol sucht \asname{} zuerst ein Symbol, das der aktuellen
Sektion zugeordnet ist, und geht danach die ganze ,,Liste'' der Vatersektionen
durch, bis er bei den globalen Symbolen angekommen ist. Im Beispiel sehen
die Sektionen die in Tabelle \ref{TabSymErg} angegebenen Werte f"ur das Symbol
\tty{sym}.
\begin{table*}[htb]
\begin{center}\begin{tabular}{|l|l|l|}
Sektion & Wert & aus Sektion... \\
Global & 0 & Global \\
\tty{ModulA} & 0 & Global \\
\tty{ProcA1} & 5 & \tty{ProcA1} \\
\tty{ProcA2} & 10 & \tty{ProcA2} \\
\tty{ModulB} & 15 & \tty{ModulB} \\
\tty{ProcB} & 15 & \tty{ModulB} \\
\end{tabular}\end{center}
\caption{F"ur die einzelnen Sektionen g"ultigen Werte\label{TabSymErg}}
\end{table*}
Diese Regel kann man durchbrechen, indem man explizit an den Symbolnamen
die Sektion anh"angt, aus der man das Symbol holen will, und zwar in
eckigen Klammern am Ende des Symbolnamens:
\begin{verbatim}
move.l #sym[ModulB],d0
\end{verbatim}
Es d"urfen dabei nur Sektionsnamen verwendet werden, die eine Obersektion
zur aktuellen Sektion darstellen. Als Sonderwert sind die Namen
\tty{PARENT0..PARENT9} erlaubt, mit denen man die n-ten ,,Vatersektionen''
relativ zur momentanen Sektion ansprechen kann; \tty{PARENT0} entspricht
also der momentanen Sektion selber, \tty{PARENT1} der direkt "ubergeordneten
usw. Anstelle \tty{PARENT1} kann man auch kurz nur \tty{PARENT} schreiben.
L"a"st man dagegen den Platz zwischen den Klammern komplett frei, also
etwa so
\begin{verbatim}
move.l #sym[],d0 ,
\end{verbatim}
so erreicht man das globale Symbol. \bb{ACHTUNG!} Wenn man explizit ein
Symbol aus einer Sektion anspricht, so wird auch nur noch bei den
Symbolen dieser Sektion gesucht, der Sektionsbaum wird nicht mehr
bis nach oben durchgegangen!
Analog zu Pascal ist es erlaubt, da"s verschiedene Sektionen Untersektionen
gleichen Namens haben d"urfen, das Prinzip der Lokalit"at verhindert hier
Irritationen. M.E. sollte man davon aber trotzdem sparsamen Gebrauch machen,
da in Symbol-und Querverweisliste Symbole zwar mit der Sektion, in der sie
definiert wurden, gekennzeichnet werden, aber nicht mit der "uber dieser
Sektion evtl. liegenden ,,Sektionshierarchie'' (das h"atte einfach den Platz
in der Zeile gesprengt); Unterscheidungen sind dadurch nicht erkennbar.
Da ein \tty{SECTION}-Befehl von selber kein Label definiert, besteht hier
ein wichtiger Unterschied zu Pascal: Eine Pascal-Prozedur kann
ihre Unterprozeduren/funktionen automatisch ,,sehen'', unter \asname{} mu"s man
noch einen Einsprungpunkt extra definieren. Das kann man z.B. mit folgendem
Makro-P"archen tun:
\begin{verbatim}
proc MACRO name
SECTION name
name LABEL $
ENDM
endp MACRO name
ENDSECTION name
ENDM
\end{verbatim}
Diese Beispiel zeigt gleichzeitig, da"s die Lokalit"at von Labels in
Makros nicht von den Sektionen beeinflu"st wird, deshalb der Trick mit dem
\tty{LABEL}-Befehl.
Nat"urlich ist mit dieser Definition das Problen noch nicht ganz gel"ost,
bisher ist das Einsprung-Label ja noch lokal und von au"sen nicht zu
erreichen. Wer nun meint, man h"atte das Label einfach nur vor der
SECTION-Anweisung plazieren m"ussen, sei jetzt bitte ruhig, denn er
verdirbt mir den "Ubergang auf das n"achste Thema:
%%- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Die \tty{PUBLIC}-Anweisung erlaubt es, die Zugeh"origkeit eines Symbols
zu einer bestimmten Sektion zu ver"andern. Es ist m"oglich, mit einem
\tty{PUBLIC}-Befehl mehrere Symbole zu bearbeiten, ohne Beschr"ankung
der Allgemeinheit will ich aber ein Beispiel mit nur einer Variable verwenden:
Im einfachsten Falle erkl"art man ein Symbol als vollst"andig global, d.h.
es ist von allen Stellen des Programms ansprechbar:
\begin{verbatim}
PUBLIC <Name>
\end{verbatim}
Da ein Symbol bei seiner Definition endg"ultig in der Symboltabelle
einsortiert wird, mu"s diese Anweisung \bb{vor} der Definition des
Symbols erfolgen. Alle \tty{PUBLIC}s werden von \asname{} in einer Liste
vermerkt und bei ihrer Definition aus dieser Liste wieder entfernt. Bei
Beendigung einer Sektion gibt \asname{} Fehlermeldungen f"ur alle nicht
aufgel"osten ,,Vorw"artsreferenzen'' aus.
Angesichts des hierarchischen Sektionenkonzepts erscheint die Methode,
ein Symbol als vollst"andig global zu definieren, reichlich brachial.
Es geht aber auch etwas differenzierter, indem man zus"atzlich einen
Sektionsnamen angibt:
\begin{verbatim}
PUBLIC <Name>:<Sektion>
\end{verbatim}
Damit wird das Symbol der genannten Sektion zugeordnet und damit auch
allen ihren Untersektionen zug"anglich (es sei denn, diese definieren
wiederum ein Symbol gleichen Namens, das dann das ,,globalere''
"ubersteuert). Naturgem"a"s protestiert \asname{}, falls mehrere Untersektionen
ein Symbol gleichen Namens auf die gleiche Ebene exportieren wollen.
Als Spezialwert f"ur \tty{$<$Sektion$>$} sind die im vorigen Abschnitt
genannten \tty{PARENTx}-Namen zugelassen, um das Symbol genau n Ebenen hinaufzuexportieren.
Es sind als Sektionen nur der momentanen Sektion "ubergeordnete Sektionen
zugelassen, also keine, die im Baum aller Sektionen in einem anderen Zweig
stehen. Sollten dabei mehrere Sektionen den gleichen Namen haben (dies ist
legal), so wird die tiefste gew"ahlt.
Mit diesem Werkzeug kann das obige Prozedurmakro nun Sinn ergeben:
\begin{verbatim}
proc MACRO name
SECTION name
PUBLIC name:PARENT
name LABEL $
ENDM
\end{verbatim}
Diese Einstellung entspricht dem Modell von Pascal, in der eine
Unterprozedur auch nur von ihrem ,,Vater'' gesehen werden kann, jedoch
nicht vom ,,Gro"svater''.
Falls mehrere Untersektionen versuchen, ein Symbol gleichen Namens
in die gleiche Obersektion zu exportieren, meckert \asname{} "uber doppelt
definierte Symbole, was an sich ja korrekt ist. War das gewollt,
so mu"s man die Symbole in irgendeiner Weise ,,qualifizieren'', damit
sie voneinander unterschieden werden k"onnen. Dies ist mit der
\tty{GLOBAL}-Anweisung m"oglich. Die Syntax von \tty{GLOBAL} ist
der von \tty{PUBLIC} identisch, das Symbol bleibt aber lokal, anstatt
einer h"oheren Sektion zugeordnet zu werden. Stattdessen wird ein
weiteres Symbol gleichen Werts erzeugt, dem jedoch der Untersektionsname
mit einem Unterstrich vorangestellt wird, und nur dieses Symbol wird der
Sektionsangabe entsprechend "offentlich gemacht. Definieren z.B. zwei
Sektionen \tty{A} und \tty{B} ein Symbol \tty{SYM} und exportieren
es mit \tty{GLOBAL} zu ihrer Vatersektion, so werden dort die Symbole
unter den Namen \tty{A\_SYM} und \tty{B\_SYM} eingeordnet.
Falls zwischen Quell- und Zielsektion mehrere Stufen stehen sollten,
so wird entsprechend der komplette Namenszweig von der Ziel- bis zur
Quellsektion dem Symbolnamen vorangestellt.
%%- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
So sch"on das bisher besprochene Modell ist, ein bei Pascal nicht
auftauchendes Detail macht "Arger: die bei Assembler m"oglichen
Vorw"artsreferenzen. Bei Vorw"artsreferenzen kann es sein, da"s \asname{}
im ersten Pass auf ein Symbol einer h"oheren Sektion zugreift. Dies
ist an sich nicht weiter tragisch, solange im zweiten Pass das richtige
Symbol genommen wird, es k"onnen aber Unf"alle der folgenden Art passieren:
\begin{verbatim}
loop: .
<Code>
..
SECTION sub
.. ; ***
bra.s loop
..
loop: ..
ENDSECTION
..
jmp loop ; Hauptschleife
\end{verbatim}
\asname{} wird im ersten Pass das globale Label \tty{loop} verwenden, sofern
das Programmst"uck bei \tty{$<$Code$>$} hinreichend lang ist, wird er
sich "uber eine zu gro"se Sprungdistanz beklagen und den zweiten Pass erst
gar nicht versuchen. Um die Uneindeutigkeit zu vermeiden, kann man den
Symbolnamen mit einem expliziten Bezug versehen:
\begin{verbatim}
bra.s loop[sub]
\end{verbatim}
Falls ein lokales Symbol h"aufig referenziert wird, k"onnen die vielen
Klammern mit dem \tty{FORWARD}-Befehl eingespart werden. Das Symbol
wird damit explizit als lokal angek"undigt. \asname{} wird dann bei Zugriffen
auf dieses Symbol automatisch nur im lokalen Symbolbereich suchen.
In diesem Falle m"u"ste an der mit \tty{***} gekennzeichneten Stelle
daf"ur der Befehl
\begin{verbatim}
FORWARD loop
\end{verbatim}
stehen.
Damit \tty{FORWARD} Sinn macht, mu"s es nicht nur vor der Definition des
Symbols, sondern vor seiner ersten Benutzung in der Sektion gegeben werden.
Ein Symbol gleichzeitig privat und "offentlich zu definieren, ergibt keinen
Sinn und wird von \asname{} auch angemahnt.
%%- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Die mehrstufige Suche in der Symboltabelle und die Entscheidung, mit welchem
Attribut ein Symbol eingetragen werden soll, kosten naturgem"a"s etwas
Rechenzeit. Ein 1800 Zeilen langes 8086-Programm z.B. wurde nach der
Umstellung auf Sektionen statt in 33 in 34,5 Sekunden assembliert
(80386 SX, 16MHz, 3 Durchg"ange). Der Overhead h"alt sich also in Grenzen:
Ob man ihn in Kauf nehmen will, ist (wie am Anfang erw"ahnt) eine Frage des
Geschmacks; man kann \asname{} genauso gut ohne Sektionen verwenden.
%%---------------------------------------------------------------------------
%%- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
\label{ChapShareOrder} \ttindex{SHARED}
{\em G"ultigkeit: alle Prozessoren}
Mit diesem Befehl weist man den \asname{} an, die in der Parameterliste
angegebenen Symbole (egal ob Integer, Gleitkomma oder String) im
Sharefile mit ihren Werten abzulegen. Ob eine solche Datei "uberhaupt
und in welchem Format erzeugt wird, h"angt von den in
\ref{SectCallConvention} beschriebenen Kommandozeilenschaltern ab.
Findet \asname{} diesen Befehl und es wird keine Datei erzeugt, f"uhrt das zu
einer Warnung.
\bb{VORSICHT!} Ein eventuell der Befehlszeile anh"angender Kommentar
wird in die erste, ausgegebene Zeile mit "ubertragen (sofern die
Argumentliste von \tty{SHARED} leer ist, wird nur der Kommentar ausgegeben).
Falls die Share-Datei f"ur C oder Pascal erzeugt wird, sind einen
C/Pascal-Kommentar schlie"sende Zeichenfolgen (\verb!*/! bzw.
\verb!*)!) im Kommentar zu vermeiden. \asname{} pr"uft dies \ii{nicht}!
%%- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
\ttindex{INCLUDE}\label{SectInclude}
{\em G"ultigkeit: alle Prozessoren}
Dieser Befehl f"ugt die im Parameter angegebene Datei (die optional in
G"an\-se\-f"u"s\-chen eingeschlossen sein darf) so im Text ein, als ob sie dort
stehen w"urde. Dieser Befehl ist sinnvoll, um Quelldateien aufzuspalten,
die alleine nicht in den Speicher passen w"urden oder um sich ''Toolboxen''
zu erzeugen.
Falls der angegebene Dateiname keine Endung hat, wird er automatisch
um die Endung \tty{INC} erweitert.
Der Assembler versucht als erstes, die angegebene Datei in den Verzeichnis
zu finden, in dem sich auch die Quelldatei befindet, die das \tty{INCLUDE}-Statement
enth"alt - ein eventuell in der Dateiangabe enthaltener Pfad ist also relativ
zu deren Pfad, und nicht zu dem Verzeichnis, von dem aus man den Assembler
aufgerufen hat. Mit der Kommandozeilenoption
\begin{verbatim}
-i <Pfadliste>
\end{verbatim}
l"a"st sich eine Liste von Verzeichnissen angeben, in denen automatisch
zus"atzlich nach der Include-Datei gesucht werden soll. Wird die Datei
nicht gefunden, so ist dies ein \ii{fataler} Fehler, d.h. der Assembler
bricht sofort ab.
Aus Kompatibilit"atsgr"unden ist es erlaubt, den Namen in G"ansef"u"schen
zu schreiben,
\begin{verbatim}
INCLUDE stddef51
\end{verbatim}
und
\begin{verbatim}
INCLUDE "stddef51.inc"
\end{verbatim}
sind also "aquivalent. \bb{ACHTUNG!} Wegen dieser Wahlfreiheit ist
hier nur eine Stringkonstante, aber kein Stringausdruck zul"assig!
Sollte der Dateiname eine Pfadangabe enthalten, so wird die Suchliste
ignoriert.
%%- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
\ttindex{BINCLUDE}
{\em G"ultigkeit: alle Prozessoren}
\tty{BINCLUDE} dient dazu, in den von \asname{} erzeugten Code Bin"ardaten
einzubetten, die von einem anderen Programm erzeugt wurden (das kann
nat"urlich theoretisch auch von \asname{} selber erzeugter Code sein...).
\tty{BINCLUDE} hat drei Formen:
\begin{verbatim}
BINCLUDE <Datei>
\end{verbatim}
In dieser Form wird die Datei komplett eingebunden.
\begin{verbatim}
BINCLUDE <Datei>,<Offset>
\end{verbatim}
In dieser Form wird der Inhalt der Datei ab \verb!<Offset>! bis zum Ende
der Datei eingebunden.
\begin{verbatim}
BINCLUDE <Datei>,<Offset>,<Len>
\end{verbatim}
In dieser Form werden \verb!<Len>! Bytes ab Offset \verb!<Offset>! eingebunden.
Es gelten die gleichen Regeln bez"uglich Suchpfaden wie bei \tty{INCLUDE}.
%%- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
\ttindex{MESSAGE}\ttindex{WARNING}\ttindex{ERROR}\ttindex{FATAL}
{\em G"ultigkeit: alle Prozessoren}
Der Assembler pr"uft zwar die Quelltexte so streng wie m"oglich und
liefert differenzierte Fehlermeldungen, je nach Anwendung kann es
aber sinnvoll sein, unter bestimmten Bedingungen zus"atzliche
Fehlermeldungen auszul"osen, mit denen sich logische Fehler automatisch
pr"ufen lassen. Der Assembler unterscheidet drei Typen von Fehlermeldungen,
die "uber die drei Befehle auch dem Programmierer zug"anglich sind:
\begin{itemize}
\item{\tty{WARNING}: Fehler, die auf m"oglicherweise falschen oder
ineffizienten Code hinweisen. Die Assemblierung l"auft weiter,
eine Codedatei wird erzeugt.}
\item{\tty{ERROR}: echte Fehler im Programm. Die Assemblierung l"auft weiter,
um m"ogliche weitere Fehler in einem Durchgang entdecken und
korrigieren zu k"onnen. Eine Codedatei wird nicht erzeugt.}
\item{\tty{FATAL}: schwerwiegende Fehler, die einen sofortigen Abbruch des
Assemblers bedingen. Eine Codedatei kann m"oglicherweise entstehen,
ist aber unvollst"andig.}
\end{itemize}
Allen drei Befehlen ist das Format gemeinsam, in dem die Fehlermeldung
angegeben werden mu"s: Ein beliebiger String-Ausdruck, der sowohl eine einfache
Konstante als auch eine komplizierte Formel sein darf, die zu einem String
evaluiert. Dies schlie"st auch die in \ref{SectSymConv} beschriebene
Funktion ein, um Zahlenwerte mit auszugeben:
\begin{verbatim}
message "Startadresse ist \{start_address}"
\end{verbatim}
Diejenigen Anweisungen, die Warnungen oder Fehlermeldungen erzeugen, ergeben
nur in Zusammenhang mit bedingter Assemblierung Sinn. Ist f"ur ein Programm
z.B. nur ein begrenzter Adre"sraum vorhanden, so kann man den "Uberlauf
folgenderma"sen testen:
\begin{verbatim}
ROMSize equ 8000h ; 27256-EPROM
ProgStart: ..
<das eigentliche Programm>
..
ProgEnd:
if ProgEnd-ProgStart>ROMSize
error "\aDas Programm ist zu lang!"
endif
\end{verbatim}
Neben diesen fehlererzeugenden Befehlen gibt es noch den Befehl
\tty{MESSAGE}, der einfach nur eine Meldung im Listing und auf
der Konsole erzeugt (letzteres nur, wenn nicht im quiet-Modus
gearbeitet wird). Seine Benutzung ist den anderen drei Befehlen
gleich.
%%- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
\ttindex{READ}
{\em G"ultigkeit: alle Prozessoren}
\tty{READ} ist sozusagen das Gegenst"uck zu der vorigen Befehlsgruppe: mit
ihm ist es m"oglich, \ii{w"ahrend} der Assemblierung Werte von der
Tastatur einzulesen. Wozu das gut sein soll? Um das darzulegen, soll
hier ausnahmsweise einmal das Beispiel vor die genauere Erl"auterung
gezogen werden:
Ein Programm ben"otigt zum Datentransfer einen Puffer mit einer zur
"Ubersetzungszeit festzulegenden Gr"o"se. Um die Gr"o"se des Puffers
festzulegen, k"onnte man sie einmal mit \tty{EQU} in einem Symbol
ablegen, es geht aber auch interaktiv mit \tty{READ} :
\begin{verbatim}
IF MomPass=1
READ "Puffer (Bytes)",BufferSize
ENDIF
\end{verbatim}
Auf diese Weise k"onnen Programme sich w"ahrend der "Ubersetzung
interaktiv konfigurieren, man kann sein Programm z.B. jemandem geben,
der es mit seinen Parametern "ubersetzen kann, ohne im Quellcode
,,herumstochern'' zu m"ussen. Die im Beispiel gezeigte \tty{IF-}
Abfrage sollte "ubrigens immer verwendet werden, damit der Anwender
nur einmal mit der Abfrage bel"astigt wird.
\tty{READ} "ahnelt sehr stark dem \tty{SET-} Befehl, nur da"s der
dem Symbol zuzuweisende Wert nicht rechts vom Schl"usselwort steht,
sondern von der Tastatur eingelesen wird. Dies bedeutet z.B. auch,
da"s \asname{} anhand der Eingabe automatisch festlegt, ob es sich um eine
Integer- oder Gleitkommazahl oder einen String handelt und anstelle
einzelner Konstanten auch ganze Formelausdr"ucke eingegeben werden
k"onnen.
\tty{READ} darf entweder nur einen Parameter oder zwei Parameter
haben, denn die Meldung zur Eingabeaufforderung ist optional. Fehlt
sie, so gibt \asname{} eine aus dem Symbolnamen konstruierte Meldung aus.
%%- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
\ttindex{INTSYNTAX}
{\em G"ultigkeit: alle Prozessoren}
Mit diesem Befehl kann die Menge der Schreibweisen, die f"ur Integer-Konstanten
in verschiedenen Zahlensystemen zul"assig sind, ver"andert werden. Nach Auswahl
eines bestimmten Zieles gilt ein bestimmter Default-Satz (siehe Abschnitt
\ref{SectPseudoInst}), der um einzelne Schreibweisen erg"anzt oder bereinigt werden
kann. \tty{INTSYNTAX} akzeptiert eine beliebige Liste von Argumenten, von denen
jedes mit einem Plus- oder Minuszeichen beginnt, direkt gefolgt von der Kennung
der jeweiligen Schreibweise. So stellt man z.B. mit folgendem Befehl
\begin{verbatim}
intsyntax -0oct,+0hex
\end{verbatim}
ein, da"s eine f"uhrende Null keine Oktal-, sondern eine Hexadezimalzahl
kennzeichnet, was bei manchen Assemblern f"ur den SC/MP gebr"auchlich ist. Die
Kennungen f"ur die einzelnen Schreibweisen finden sich in Tabelle \ref{TabSystems}.
Den Kombinationsm"oglichkeiten sind keine Grenzen gesetzt, au"ser wenn sich zwei
Schreibweisen direkt widersprechen. Im obigen Beispiel w"are es z.B. nicht
erlaubt, gleichzeitig \tty{0oct} und \tty{0hex} einzuschalten.
%%- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
\ttindex{RELAXED}
{\em G"ultigkeit: alle Prozessoren}
Defaultm"a"sig ist einer Prozessorfamilie eine bestimmte Schreibweise
von Integer-Konstanten zugeordnet (die i.a. der Herstellervorgabe
entspricht, solange der nicht eine allzu abgefahrene Syntax benutzt...).
Nun hat aber jeder seine pers"onlichen Vorlieben f"ur die eine oder
andere Schreibweise und kann gut damit leben, da"s sich seine Programme
nicht mehr mit dem Standard-Assembler "ubersetzen lassen. Setzt man ein
\begin{verbatim}
RELAXED ON
\end{verbatim}
an den Programmanfang, so kann man fortan alle Schreibweisen beliebig
gemischt und durcheinander verwenden; bei jedem Ausdruck versucht \asname{}
automatisch zu ermitteln, welche Schreibweise verwendet wurde. Da"s
diese Automatik nicht immer das Ergebnis liefert, das man sich vorgestellt
hat, ist auch der Grund, weshalb diese Option explizit eingeschaltet
werden mu"s (und man sich davor h"uten sollte, sie einfach in einem
existierenden Programm dazuzusetzen): Ist nicht durch vor- oder
nachgestellte Zeichen zu erkennen, da"s es sich um Intel- oder
Motorola-Konstanten handelt, wird im C-Modus gearbeitet. Eventuell
vorangestellte, eigentlich "uberfl"ussige Nullen haben in diesem Modus
durchaus eine Bedeutung:
\begin{verbatim}
move.b #08,d0
\end{verbatim}
Diese Konstante w"urde als Oktalkonstante verstanden werden, und weil
Oktalzahlen nur Ziffern von 0..7 enthalten k"onnen, f"uhrt das zu einem
Fehler. Dabei h"atte man in diesem Fall noch Gl"uck gehabt, bei der
Zahl \tty{077} z.B. h"atte man ohne Meldung Probleme bekommen. Ohne
\tty{RELAXED}-Modus w"are in beiden F"allen klar gewesen, da"s es sich
um dezimale Konstanten handelt.
Die momentane Einstellung kann aus dem gleichnamigen Symbol ausgelesen
werden.
%%- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
\ttindex{COMPMODE}
{\em G"ultigkeit: verschiedene}
Auch wenn sich \asname{} bem"uht, sich m"oglichst genauso zu verhalten wie die
jeweiligen ''Original-Assembler'', so gibt es in der Praxis immer wieder
Details, wo ein hundertprozentiges Nachbilden des jeweiligen Original-
Verhaltens Optimierungen verhindern w"urde, die aus meiner Sicht valide
und n"utzlich sind. Mit einem
\begin{verbatim}
compmode on
\end{verbatim}
kann man in eine Betriebsart umschalten, die dem ''Original-Verhalten''
Vorrang vor optimalem Code gibt. Ob f"ur das jeweilige Target solche
F"alle vorliegen, ist im jeweiligen Unterkapitel mit dem prozessorspezifischen
Hinweisen ausgef"uhrt.
Im Default ist dieser Kompatibilit"ats-Modus ausgeschaltet, au"ser er
wurde durch die gleichnamige Kommandozeilen-Option eingeschaltet. Die
momentane Einstellung kann aus dem gleichnamigen Symbol ausgelesen
werden.
%%- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
\ttindex{END}
{\em G"ultigkeit: alle Prozessoren}
\tty{END} kennzeichnet das Ende des Assemblerprogrammes. Danach
noch in der Quelldatei stehende Zeilen werden ignoriert.
\bb{WICHTIG:} \tty{END} darf zwar aus einem Makro heraus aufgerufen
werden, der Stapel der bedingten Assemblierung wird aber nicht
automatisch abger"aumt. Das folgende Konstrukt f"uhrt daher zu
einer Fehlermeldung:
\begin{verbatim}
IF KeineLustMehr
END
ENDIF
\end{verbatim}
Optional darf \tty{END} auch einen Integer-Ausdruck als Argument haben,
der den Startpunkt des Programms vermerkt. Dieser wird von \asname{} in einem
speziellen Record der Datei vermerkt und kann z.B. von P2HEX
weiterverarbeitet werden.
\tty{END} war eigentlich schon immer in \asname{} definiert, nur war es
bei fr"uheren Versionen von \asname{} aus Kompatibilit"at zu anderen
Assemblern vorhanden und hatte keine Wirkung.
%%===========================================================================
\cleardoublepage
\chapter{Prozessorspezifische Hinweise}
Ich habe mich bem"uht, die einzelnen Codegeneratoren m"oglichst kompatibel
zu den Originalassemblern zu halten, jedoch nur soweit, wie es keinen
unvertretbaren Mehraufwand bedeutete. Wichtige Unterschiede, Details und
Fallstricke habe ich im folgenden aufgelistet.
%%---------------------------------------------------------------------------
,,Wo gibt es denn das zu kaufen, den HC11 in NMOS?'', fragt jetzt vielleicht
der eine oder andere. Gibt es nat"urlich nicht, aber ein H l"a"st sich nun
einmal nicht in einer Hexzahl darstellen ("altere Versionen von \asname{} h"atten
solche Namen deswegen nicht akzeptiert), und dann habe ich die Buchstaben
gleich ganz weggelassen...
\begin{quote}{\it
,,Jemand, der sagt, etwas sei unm"oglich,sollte wenigstens so kooperativ
sein, denjenigen, der es gerade tut, nicht am Arbeiten zu hindern.''
}\end{quote}
Ab und zu ist man gezwungen, seine Meinung zu revidieren. Vor einigen
Versionen hatte ich an dieser Stelle noch behauptet, ich k"onne es im Parser
von \asname{} nicht realisieren, da"s man die Argumente von \tty{BSET/BCLR} bzw.
\tty{BRSET/BRCLR} auch mit Leerzeichen trennen kann. Offensichtlich kann
selbiger aber mehr, als ich vermutet habe...nach der soundsovielten Anfrage
habe ich mich noch einmal drangesetzt, und jetzt scheint es zu laufen. Man
darf sowohl Leerzeichen als auch Kommas verwenden, aber nicht in allen
Varianten, um es nicht uneindeutig zu machen: Es gibt zu jeder
Befehlsvariante zwei M"oglichkeiten; eine, die nur Kommas verwendet, sowie
eine, wie sie von Motorola wohl definiert wurde (leider sind die Datenb"ucher
nicht immer so gut wie die zugeh"orige Hardware...):
\begin{verbatim}
Bxxx abs8 #mask entspricht Bxxx abs8,#mask
Bxxx disp8,X #mask entspricht Bxxx disp8,X,#mask
BRxxx abs8 #mask adr entspricht BRxxx abs8,#mask,adr
BRxxx disp8,X #mask adr entspricht BRxxx disp8,X,#mask,adr
\end{verbatim}
Dabei steht \tty{xxx} entweder f"ur \tty{SET} oder \tty{CLR} und \tty{\#mask}
f"ur die zu verwendende Bitmaske; der Lattenzaun ist dabei optional.
Anstelle des X-Registers darf nat"urlich auch Y verwendet werden.
Mit der K4-Version des HC11 hat Motorola ein Banking-Schema eingef"uhrt,
mit dem man zwar einerseits eine zu klein gewordene Architektur noch
einmal aufbohren kann, den Software- und Tool-Entwicklern aber nicht
unbedingt das Leben einfacher macht...wie stellt man so etwas vern"unftig
dar?
Die K4-Architektur {\em erweitert} den Adre"sraum des HC11 um 2x512 Kbyte,
so da"s jetzt insgesamt 64+1024=1088 Kbyte zur Verf"ugung stehen. \asname{} tut
so, als ob es sich dabei um einen Adre"sraum handeln w"urde, der
folgenderma"sen organisiert ist:
\begin{itemize}
\item{\$000000...\$00ffff: der alte HC11-Adre"sraum}
\item{\$010000...\$08ffff: Fenster 1}
\item{\$090000...\$10ffff: Fenster 2}
\end{itemize}
"Uber den {\tt ASSUME}-Befehl teilt man \asname{} mit, wie die Banking-Register
eingestellt sind und damit, wie und wo die erweiterten Bereiche
eingeblendet werden. Bei absoluten Adressierungen mit Adressen jenseits
\$10000 berechnet \asname{} dann automatisch, welche Adresse innerhalb der ersten
64K anzusprechen ist. Das kann nat"urlich wieder nur f"ur direkte
Adressierungsarten funktionieren, bei indizierten/indirekten
Adre"sausdr"ucken ist der Programmierer daf"ur verantwortlich, "uber die
momentan aktiven Banks den "Uberblick zu behalten!
Wer sich nicht ganz sicher ist, ob die momentane Einstellung korrekt ist,
kann den Pseudobefehl {\tt PRWINS} benutzen, der dann z.B.
\begin{verbatim}
MMSIZ e1 MMWBR 84 MM1CR 00 MM2CR 80
Window 1: 10000...12000 --> 4000...6000
Window 1: 90000...94000 --> 8000...c000
\end{verbatim}
ausgibt. Ein z.B. an Stelle \$10000 liegender Befehl
\begin{verbatim}
jmp *+3
\end{verbatim}
w"urde effektiv einen Sprung auf Adresse \$4003 ausl"osen.
%%---------------------------------------------------------------------------
Sicher hat es ein bi"schen den Anflug einer Schnapsidee, einen Prozessor,
der eher f"ur den Einsatz in Workstations konzipiert wurde, in \asname{}
einzubauen, der sich ja eher an Programmierer von Einplatinencomputern
wendet. Aber was heute noch das Hei"seste vom Hei"sen ist, ist es morgen
schon nicht mehr, und sowohl der Z80 als auch der 8088 haben ja inzwischen
die Mutation von der Personal Computer-CPU zum sog. ,,Mikrocontroller''
vollzogen. Mit dem Erscheinen von MPC505 und PPC403 hat sich die Vermutung
dann auch best"atigt, da"s IBM und Motorola diese Prozessorserie auf allen
Ebenen durchdr"ucken wollen.
Die Unterst"utzung ist momentan noch nicht vollst"andig: Als Pseudobefehle
zur Datenablage werden momentan provisorisch die Intel-Mnemonics
unterst"utzt und es fehlen die etwas ungew"ohnlicheren, in \cite{Mot601}
genannten RS6000-Befehle (die aber hoffentlich keiner vermi"st...). Das
wird aber nachgeholt, sobald Informationen verf"ugbar sind!
%%---------------------------------------------------------------------------
Der PALM-Prozessor von IBM war lange Zeit ,,Terra Incognita'', weil er
au"serhalb von IBM nie eingesetzt wurde. Des weiteren waren die damit
best"uckten IBM-Systeme 5100 bis 5120 recht exotisch und teuer, und
gerieten "uber den Erfolg des IBM PC schnell in Vergessenheit. Es ist
Christian Corti und seinem akribischen Reverse Engineering zu
verdanken, da"s dieses Target "uberhaupt implementiert werden konnte
Als Christian mit dem Reverse Engineering des PALM-Prozessors begann,
waren ihm die von IBM definierten Assembler-Mnemonics nicht bekannt, er
mu"ste sich seine eigenen ausdenken. Das geschah nat"urlich mit dem
Wissen im Hinterkopf "uber all die Architekturen, die nach 1973 bis
heute entwickelt wurden.
Vergleicht man seine Mnemonics mit den originalen von IBM (f"ur die
dann doch noch eine Dokumentation in \cite{IBMPalm} aufgetaucht
ist...), dann dr"angt sich ein Vergleich mit den Mnemonics f"ur den
Intel 8080/8085 auf der einen Seite, und den Zilog Z80 auf der anderen
Seite auf: Die einen packen zum Teil die Adressierungsart mit in den
Befehlsnamen, z.B. {\tt MVI} f"ur ,,Move Immediate'' oder {\tt LDHD}
f"ur ,,LoaD Halfword Direct''. Dies ist f"ur einen Assembler deutlich
einfacher zu parsen und in Maschinencode umzusetzen.
Die anderen fassen unter einem Mnemonic alle Maschinenbefehle
zusammen, die grob das gleiche tun, zum Beispiel {\tt LD} bzw.
{\tt MOVE} um Daten zu transferieren. Das macht die Nutzung f"ur
den Programmierer einfacher, sie sind mit den als Operanden
geschriebenen Adressierungsarten f"ur einen Assembler aber etwas
komplexer zu parsen.
Auf diese Weise haben beide Mnemonic-S"atze ihre Berechtigung: Die
einen, weil sie einfach das ,,Original'' sind und in allen
Herstellerdokumenten verwendet werden, und die anderen, weil sie
einfach moderner, zug"anglicher und praktischer sind. Ich habe mich
deshalb entschieden, {\em beide} in meinem Assembler zu unterst"utzen,
und gl"ucklicherweise war dies auch ohne Konflikte m"oglich. Das
schlie"st auch die ,,Makrobefehle'' {\tt CALL, RCALL, JMP, BRA, LWI}
und {\tt RET} ein. Und was ich selber noch dazu gedichtet habe:
\begin{itemize}
\item{{\tt AND} und {\tt OR} akzeptieren auch einen Immediate-Wert als zweites
Argument. Dies wird auf {\tt SET} bzw. {\tt CLR} abgebildet, wobei bei
{\tt AND} nat"urlich das Einerkomplement des Wertes eingesetzt wird.}
\item{{\tt MOVE} akzeptiert auch einen immediate-Wert als Quelle und erzeugt
dann den gleichen Code wie {\tt LWI}. Gleiches gilt f"ur {\tt MOVB} und
{\tt LBI}.}
\end{itemize}
Makrobefehle, die aus mehr als einem (Halb-)Wort bestehen, bringen
allerdings ein neues Problem mit sich: Der PALM-Prozessor kennt als
bedingten Sprung nur das "Uberspringen des folgenden Instruktionsworts.
Folgt auf so einen Sprung ein Makrobefehl, so w"urde dieser nur
teilweise "ubersprungen. Ich habe daher eine kleine State-Machine
vorgesehen, die solche Befehlsfolgen zu erkennen versucht und dann
warnt.
Die IBM-Systeme 5110 und 5120 verwenden nicht den heute "ublichen
ASCII-Zeichensatz, sondern den von IBM-Gro"srechnern bekannten
EBCDIC. Im Include-Verzeichnis befindet sich eine Datei, die man
zur Umsetzung von ASCII nach EDCDIC einbinden kann. WICHTIG:
EBCDIC ist in dieser Datei als eigene Codepage definiert, man
mu"s die Umsetzung also noch mit einem
\begin{verbatim}
codepage cp037
\end{verbatim}
aktivieren.
Noch ein Wort zur Integer-Syntax: Christian Corti hatte sich bei seiner
Implementierung f"ur die Motorola-Syntax entschieden, also
Hex-Konstanten mit vorangestelltem Dollar-Zeichen. Ich habe mich f"ur
die 'IBM-Syntax' entschieden, also Zahlenkonstanten in Hochkommas, und z.B.
ein vorangestelltes {\tt X} f"ur hexadezimal. Um die Programmbeispiele
auf Christians Seiten ohne "Anderungen zu "ubersetzen, f"uge man
folgenden Befehl zu Beginn ein:
\begin{verbatim}
intsyntax +$hex,-x'hex'
\end{verbatim}
%%---------------------------------------------------------------------------
Motorola, was ist nur in Dich gefahren! Wer bei Dir ist nur auf das
schmale Brett gekommen, die einzelnen parallelen Datentransfers
ausgerechnet durch Leerzeichen zu trennen! Wer immer nun seine Codes
etwas "ubersichtlicher formatieren will, z.B. so:
\begin{verbatim}
move x:var9 ,r0
move y:var10,r3 ,
\end{verbatim}
der ist gekniffen, weil das Leerzeichen als Trennung paralleler
Datentransfers erkannt wird!
Sei's drum; Motorola hat es so definiert, und ich kann es nicht
"andern. Als Trennung der Operationen sind statt Leerzeichen auch
Tabulatoren zugelassen, und die einzelnen Teile sind ja wieder ganz
normal mit Kommas getrennt.
In \cite{Mot56} steht, da"s bei den Befehlen \tty{MOVEC, MOVEM, ANDI} und
\tty{ORI} auch die allgemeineren Mnemonics \tty{MOVE, AND} und \tty{OR}
verwendet werden k"onnen. Bei \asname{} geht das (noch) nicht.
%%---------------------------------------------------------------------------
Bei der Assemblersyntax dieser Prozessoren hat Hitachi reichlich
bei Motorola abgekupfert (was so verkehrt ja nun auch nicht war...),
nur leider wollte die Firma unbedingt ihr eigenes Format f"ur
Hexadezimalzahlen einf"uhren, und dazu noch eines, das ein einzelne
Hochkommas verwendet, etwa in dieser Form:
\begin{verbatim}
mov.w #h'ff,r0
\end{verbatim}
Dieses Format wird von \asname{} im Default nicht unterst"utzt, es wird
stattdessen die ''Motorola-Syntax'' mit vorangestelltem Dollarzeichen
angeboten. Falls man doch unbedingt die 'Hitachi-Syntax' benutzen
will, z.B. um existierenden Code zu "ubersetzen, so mu"s der
RELAXED-Modus eingeschaltet werden. Bitte beachten, da"s diese Syntax
bisher wenig getestet wurde und ich keine Garantie geben kann, da"s sie
in allen F"allen funktioniert!
%%---------------------------------------------------------------------------
Der {\tt MOV}-Befehl des H8/500 bietet eine interessante und ungew"ohnliche
Optimierung: Hat der Zieloperand eine L"ange von 16 Bit, so ist es trotzdem
m"oglich, einen nur 8-bittigen (Immediate-)Quelloperanden zu verwenden. Bei
einer Anweisung der Form
\begin{verbatim}
mov.w #$ffff,@$1234
\end{verbatim}
ist es also m"oglich, den Immediate-Quellwert lediglich in einem Byte mit
dem Wert \$ff zu kodieren und ein Byte einzusparen. Der Prozessor f"uhrt
eine Vorzeichenerweiterung durch, so da"s aus \$ff das gew"unschte \$ffff
wird. \asname{} kennt diese Optimierung und benutzt sie auch, wenn dies nicht
durch einen expliziten \tty{:16}-Suffix am Immediate-Operanden verboten
wird.
Es hat sich in diesem Zusammenhang nur herausgestellt, da"s der Original-Assembler
von Hitachi diese Optimierung anders umsetzt: er scheint von einer Null- statt
einer Vorzeichen-Erweiterung auszugehen. Das bedeutet, nicht Argumente von
-128 bis +127 (\$ff80 bis \$007f) werden als ein Byte kodiert, sondern von 0 bis
255 (\$0000 bis \$00ff). Tests an echter Hardware haben ergeben, da"s
das Programmers Manual in dieser Hinsicht Recht hat: Es wird eine Vorzeichen-
Erweiterung durchgef"uhrt. Deshalb verwendet \asname{} im Default die k"urzere
Kodierung nur, wenn im Quellcode ein Wert von -128 bis +127 bzw. (\$ff80 bis
\$007f) benutzt wird. F"ur existierenden Code, der sich darauf verl"a"st,
da"s Werte von \$80 bis \$ff mit nur einem Byte kodiert werden, kann in einen
Kompatibilit"atsmodus geschaltet werden, entweder durch ein
\begin{verbatim}
compmode on
\end{verbatim}
im Quellcode oder den gleichnamigen Schalter auf der Kommandozeile.
Ansonsten gelten die gleichen Hinweise bez"uglich der Syntax hexadezimaler
Zahlen wie f"ur H8/300.
%%---------------------------------------------------------------------------
Leider hat Hitachi auch hier wieder das Extrawurst-Format f"ur
Hexadezimalzahlen verwendet, und wieder habe ich in \asname{} das nicht
nachvollzogen...bitte Motorola-Syntax benutzen!
Bei der Verwendung von Literalen und dem \tty{LTORG}-Befehl sind
einige Details zu beachten, wenn man nicht auf einmal mit eigenartigen
Fehlermeldungen konfrontiert werden will:
Literale existieren, weil der Prozessor nicht in der Lage ist, Konstanten
au"serhalb des Bereiches von -128 bis 127 mit immediate-Adressierung
zu laden. \asname{} (und der Hitachi-Assembler) verstecken diese Unzul"anglichkeit,
indem sie automatisch entsprechende Konstanten im Speicher ablegen, die
dann mittels PC-relativer Adressierung angesprochen werden. Die Frage, die
sich nun erhebt, ist die, wo diese Konstanten im Speicher abgelegt werden
sollen. \asname{} legt sie nicht sofort ab, sondern sammelt sie so lange
auf, bis im Programm eine \tty{LTORG}-Anweisung auftritt. Dort werden
alle Konstanten abgelegt, wobei deren Adressen mit ganz normalen
Labels versehen werden, die man auch in der Symboltabelle sehen kann.
Ein Label hat die Form
\begin{verbatim}
LITERAL_s_xxxx_n .
\end{verbatim}
Dabei repr"asentiert \tty{s} den Typ des Literals. Unterschieden werden
Literale, die 16-Bit-Konstanten (\tty{s=W}), 32-Bit-Konstanten (\tty{s=L})
oder Vorw"artsreferenzen, bei denen \asname{} die Operandengr"o"se nicht
im voraus erkennen kann (\tty{s=F}), enthalten. F"ur \tty{W} oder \tty{L}
bedeutet \tty{xxxx} den hexadezimal geschriebenen Wert der Konstante, bei
Vorw"artsreferenzen, bei denen man den Literalwert ja noch nicht kennt,
bezeichnet \tty{xxxx} eine einfache Durchnumerierung. \tty{n} kennzeichnet
das wievielte Auftreten dieses Literals in dieser Sektion. Literale machen
ganz normal die Lokalisierung durch Sektionen mit, es ist daher zwingend
erforderlich, in einer Sektion entstandene Literale mit \tty{LTORG} auch
dort abzulegen!
Die Durchnumerierung mit \tty{n} ist erforderlich, weil ein Literal in
einer Sektion mehrfach auftreten kann. Dies ist einmal bedingt dadurch,
da"s die PC-relative Adressierung nur positive Displacements erlaubt,
einmal mit \tty{LTORG} abgelegte Literale also im folgenden Code nicht
mitbenutzt werden k"onnen, andererseits auch, weil die Reichweite der
Displacements beschr"ankt ist (512 bzw. 1024 Byte).
Ein automatisches \tty{LTORG} am Ende des Programms oder beim Umschalten
zu einer anderen CPU erfolgt nicht; findet \asname{} in einer solchen Situation
noch abzulegende Literale, so wird eine Fehlermeldung ausgegeben.
Da bei der PC-relativen Adressierung der zur Adressierung herangezogene
PC-Wert der Instruktionsadresse+4 entspricht, ist es nicht m"oglich, ein
Literal zu benutzen, welches direkt hinter dem betroffenen Befehl abgelegt
wird, also z.B. so:
\begin{verbatim}
mov #$1234,r6
ltorg
\end{verbatim}
Da der Prozessor dann aber sowieso versuchen w"urde, Daten als Code
auszuf"uhren, sollte diese Situation in realen Programmen nicht auftreten.
Wesentlich realer ist aber ein anderer Fallstrick: Wird hinter einem
verz"ogerten Sprung PC-relativ zugegriffen, so ist der Programmz"ahler
bereits auf die Sprungzieladresse gesetzt, und das Displacement wird
relativ zum Sprungziel+2 berechnet. Im folgenden Beispiel kann daher
das Literal nicht erreicht werden:
\begin{verbatim}
bra Target
mov #$12345678,r4 ; wird noch ausgefuehrt
.
.
ltorg ; hier liegt das Literal
.
.
Target: mov r4,r7 ; hier geht es weiter
\end{verbatim}
Da Target+2 hinter dem Literal liegt, w"urde sich ein negatives
Displacement ergeben. Besonders haarig wird es, wenn mit den
Befehlen \tty{JMP, JSR, BRAF} oder \tty{BSRF} verzweigt wird: Da \asname{} die
Zieladresse hier nicht ermitteln kann (sie ergibt sich erst zur
Laufzeit aus dem Registerinhalt), nimmt \asname{} hier eine Adresse an,
die nach M"oglichkeit nie pa"st, so da"s PC-relative Adressierung g"anzlich
unm"oglich wird.
Es ist nicht direkt m"oglich, aus der Zahl und Gr"o"se der Literale
auf den belegten Speicher zu schlie"sen. U.u. mu"s \asname{} ein F"ullwort
einbauen, um einen Langwort-Wert auf eine durch 4 teilbare Adresse
auszurichten, andererseits kann er m"oglicherweise Teile eines
32-bittigen Literals f"ur 16-Bit-Literale mitbenutzten. Mehrfach
auftretende Literale erzeugen nat"urlich nur einen Eintrag. Solche
Optimierungen werden f"ur Vorw"artsreferenzen allerdings ganz
unterdr"uckt, da \asname{} den Wert dieser Literale noch nicht kennt.
Da Literale die PC-relative Adressierung ausnutzen, die nur beim
\tty{MOV}-Befehl erlaubt sind, beschr"anken sich Literale ebenfalls auf
die Verwendung in \tty{MOV}. Etwas trickreich ist hier die Art und Weise,
in der \asname{} die Operandengr"o"se auswertet. Eine Angabe von Byte oder
Wort bedeutet, da"s \asname{} einen m"oglichst kurzen \tty{MOV}-Befehl erzeugt,
der den angegebenen Wert in den unteren 8 oder 16 Bit erzeugt, d.h.
die oberen 24 oder 16 Bit werden als don't care behandelt. Gibt
man dagegen Langwort oder gar nichts an, so sagt dies aus, da"s
das komplette 32-Bit-Register den angegebenen Wert enthalten soll.
Das hat z.B. den Effekt, da"s in folgendem Beispiel
\begin{verbatim}
mov.b #$c0,r0
mov.w #$c0,r0
mov.l #$c0,r0
\end{verbatim}
der erste Befehl echte immediate-Adressierung erzeugt, der zweite und
dritte jedoch ein Wort-Literal benutzen: Da das Bit 7 in der Zahl gesetzt
ist, erzeugt der Byte-Befehl effektiv \$FFFFFFC0 im Register, was nach
der Konvention nicht das w"are, was man im zweiten und dritten Fall haben
m"ochte. Im dritten Fall reicht auch ein Wort-Literal, weil das gel"oschte
Bit 15 des Operanden vom Prozessor in Bit 16..31 fortgesetzt wird.
Wie man sieht, ist dieses ganze Literal-Konzept reichlich kompliziert;
einfacher ging's aber wirklich nicht. Es liegt leider in der Natur
der Sache, da"s man manchmal Fehlermeldungen "uber nicht gefundene
Literale bekommt, die eigentlich logisch nicht auftreten k"onnten, weil
\asname{} die Literale ja komplett in eigener Regie verwaltet. Treten aber bei
der Assemblierung Fehler erst im zweiten Pass auf, so verschieben sich
z.B. hinter der Fehlerstelle liegende Labels gegen"uber dem ersten Pass,
weil \asname{} f"ur die jetzt als fehlerhaft erkannten Befehle keinen Code mehr
erzeugt. Da aber Literalnamen u.a. aus den Werten von Symbolen erzeugt
werden, werden als Folgefehler davon eventuell andere Literalnamen
nachgefragt, als im ersten Pass abgelegt wurden und \asname{} beschwert sich
"uber nicht gefundene Symbole...sollten also neben anderen Fehlern solche
Literal-Fehler auftreten, beseitigen Sie erst die anderen Fehler, bevor
Sie mich und alle Literale verfluchen...
Wer aus der Motorola-Ecke kommt und PC-relative Adressierung explizit
benutzen will (z.B. um Variablen lageunabh"angig zu erreichen), sollte
wissen, da"s beim Ausschreiben der Adressierung nach Programmierhandbuch,
also z.B. so:
\begin{verbatim}
mov.l @(Var,PC),r8
\end{verbatim}
{\it keine} implizite Umrechnung der Adresse auf ein Displacement erfolgt,
d.h. der Operand wird so eingesetzt, wie er ist (und w"urde in diesen
Beispiel wohl mit hoher Wahrscheinlichkeit eine Fehlermeldung
hervorrufen...). Will man beim SH7x00 PC-relativ adressieren, so tut man
das einfach mit ,,absoluter'' Adressierung, die auf Maschinenebene ja
gar nicht existiert:
\begin{verbatim}
mov.l Var,r8
\end{verbatim}
Hier wird das Displacement korrekt berechnet (es gelten nat"urlich die
gleichen Einschr"ankungen f"ur das Displacement wie bei Literalen).
%%---------------------------------------------------------------------------
Beim Befehlssatz dieser 4-Bit-Prozessoren f"uhlte ich mich
spontan an den 8080/8085 erinnert - sehr viele Menemonics, die
Adressierungsart (z.B. indirekt oder direkt) ist in den Befehl
einkodiert, die Befehle sind zum Teil nur schwer zu merken.
Nat"urlich unterst"utzt \asname{} diese Syntax, wie Hitachi sie
seinerzeit definiert hat, ich habe aber zus"atzlich f"ur die
meisten Befehle eine - finde ich - sch"onere und besser lesbare
Variante implementiert, so wie Zilog es seinerzeit mit den Z80
gemacht hat. Zum Beispiel k"onnen alle Maschineninstruktionen,
die in irgendeiner Form Daten transferieren, egal ob die
Operanden Register, Konstanten oder Speicherstellen sind, "uber den
\asname{}-spezifischen \tty{LD}-Befehl angesprochen werden. "Ahnliche
'Meta-Befehle' gibt es f"ur arithmetische und logische Befehle.
Eine vollst"andige Liste aller Meta-Befehle und ihrer Operanden
findet sich in den Tabellen \ref{TabHMCS400Meta} und
\ref{TabHMCS400MetaOps}, ihre praktische Verwendung kann man sich
in der Datei \tty{t\_hmcs4x.asm} ansehen.
\begin{table*}
\begin{center}\begin{tabular}{|l|l|}
Meta-Instruktion & Ersetzt \\
\tty{LD} {\em src, dest} & \tty{LAI, LBI, LMID, LMIIY,} \\
& \tty{LAB, LBA, LAY, LASPX, LASPY, LAMR,} \\
& \tty{LWI, LXI, LYI, LXA, LYA, LAM, LAMD} \\
& \tty{LBM, LMA, LMAD, LMAIY, LMADY} \\
\tty{XCH} {\em src, dest} & \tty{XMRA, XSPX, XSPY, XMA, XMAD, XMB} \\
\tty{ADD} {\em src, dest} & \tty{AYY, AI, AM, AMD} \\
\tty{ADC} {\em src, dest} & \tty{AMC, AMCD} \\
\tty{SUB} {\em src, dest} & \tty{SYY} \\
\tty{SBC} {\em src, dest} & \tty{SMC, SMCD} \\
\tty{OR} {\em src, dest} & \tty{OR, ORM, ORMD} \\
\tty{AND} {\em src, dest} & \tty{ANM, ANMD} \\
\tty{EOR} {\em src, dest} & \tty{EORM, EORMD} \\
\tty{CP} {\em cond, src, dest} & \tty{INEM, INEMD, ANEM, ANEMD, BNEM,} \\
& \tty{YNEI, ILEM, ILEMD, ALEM, ALEMD,} \\
& \tty{BLEM, ALEI} \\
\tty{BSET} {\em bit} & \tty{SEC, SEM, SEMD} \\
\tty{BCLR} {\em bit} & \tty{REC, REM, REMD} \\
\tty{BTST} {\em bit} & \tty{TC, TM, TMD} \\
\end{tabular}\end{center}
\end{table*}
\begin{table*}
\begin{center}\begin{tabular}{|l|l|}
Operand & Typen \\
{\em src, dest} & \tty{A, B, X, Y, W, SPX, SPY} (Register) \\
& \tty{M} (Speicher adressiert durch X/Y/W) \\
& \tty{M+} (dito, mit Autoinkrement) \\
& \tty{M-} (dito, mit Autodekrement) \\
& \tty{\#val} (2/4 bit immediate) \\
& \tty{addr10} (Speicherzelle direkt) \\
& \tty{MRn} (Memory-Register 0..15) \\
{\em cond} & \tty{NE} (ungleich) \\
& \tty{LE} (kleiner oder gleich) \\
{\em bit} & \tty{CA} (Carry) \\
& {\em bitpos},\tty{M} \\
& {\em bitpos},\tty{addr10} \\
{\em bitpos} & \tty{0..3} \\
\end{tabular}\end{center}
\caption{Operandentypen f"ur Meta-Befehle HMCS400}
\label{TabHMCS400MetaOps}
\end{table*}
%%---------------------------------------------------------------------------
Der Befehlssatz des H16-Kerns verdient mit Recht den Namen ,,CISC'': komplexe
Adressierungsarten, sehr variable Instruktionsl"angen, und f"ur viele
Befehle mit g"angigen Operanden gibt es Kurzschreibweisen. So gibt
es f"ur diverse Befehle mehrere ,,Formate'', je nachdem welchen Typ Quell-
und Zieloperand haben. Die generelle Regel ist, da"s \asname{} immer
das k"urzestm"ogliche Format benutzt, es sei denn, es wurde explizit
angegeben:
\begin{verbatim}
mov.l r4,r7 ; benutzt R-Format
mov.l #4,r7 ; benutzt RQ-Format
mov.l #4,@r7 ; benutzt Q-Format
mov.l @r4,@r7 ; benutzt G-Format
mov:q.l #4,r7 ; Q- statt RQ-Format erzwungen
mov:g.l #4,r7 ; G- statt RQ-Format erzwungen
\end{verbatim}
F"ur Immediate-Argumente wird die ,,nat"urliche'' Operandenl"ange
benutzt, also z.B. 2 Bytes f"ur 16 Bits. K"urzere oder l"angere
Argumente lassen sich durch eine angeh"angte Operandengr"o"se
(.b, .w, .l oder :8, :16, :32) erzwingen. Bei Displacements oder
absoluten Adressen gilt jedoch, da"s ohne explizite L"angenangabe
immer die k"urzestm"ogliche Schreibweise benutzt wird. Das schlie"st
ein, da"s bei absoluten Adressen die oberen acht Adre"sbits vom
Prozessor nicht herausgegeben werden: eine Adresse \$ffff80 kann also
mit einem Byte (\$80) kodiert werden.
Des weiteren kennt \asname{} das ''Akkumulator-Bit'', d.h. bei Instruktionen
mit zwei beliebigen Operanden kann der zweite Operand weggelassen
werden, falls das Ziel Register Null ist. Dieses Verhalten kann
nicht "ubersteuert werden.
Des weiteren werden folgende Optimierungen durchgef"uhrt:
\begin{itemize}
\item{\tty{MOV R0,<ea>} wird zu \tty{MOVF <ea>} optimiert, sofern
\tty{<ea>} kein PC-relativer Ausdruck ist und sich die L"ange
des Displacements "andern w"urde. Diese Optimierung kann durch
eine explizite Formatangabe unterdr"uckt werden.}
\item{\tty{SUB} existiert nicht im Q-Format, kann aber durch ein
\tty{ADD:Q} mit negiertem immediate-Argument ersetzt werden,
falls das Argument zu \tty{SUB} im Bereich -127...+128 liegt.
Auch diese Optimierung kann durch eine explizite Formatangabe
unterdr"uckt werden.}
\end{itemize}
%%---------------------------------------------------------------------------
"Ahnlich wie beim HMCS400 sind die Adressierungsarten zu einem
gro"sen Teil in die Mnemonics hineinkodiert, und ich habe mich
auch hier daf"ur entschieden, f"ur h"aufig genutzte Befehle eine
alternative, modernere und besser lesbare Notation
bereitzustellen.
Eine vollst"andige Liste aller Meta-Befehle und ihrer Operanden
findet sich in den Tabellen \ref{TabOLMS40Meta} und
\ref{TabOLMS40MetaOps}, ihre praktische Verwendung kann man sich
in der Datei \tty{t\_olms4.asm} ansehen.
\begin{table*}
\begin{center}\begin{tabular}{|l|l|}
Meta-Instruktion & Ersetzt \\
\tty{LD} {\em dest, src} & \tty{LAI, LLI, LHI, L,} \\
& \tty{LAL, LLA, LAW, LAX, LAY, LAZ,} \\
& \tty{LWA, LXA, LYA, LPA, LTI, RTH, RTL} \\
\tty{DEC} {\em dest} & \tty{DCA, DCL, DCM, DCW, DCX, DCY, DCZ, DCH} \\
\tty{INC} {\em dest} & \tty{INA, INL, INM, INW, INX, INY, INZ} \\
\tty{BSET} {\em bit} & \tty{SPB, SMB, SC} \\
\tty{BCLR} {\em bit} & \tty{RPB, RMB, RC} \\
\tty{BTST} {\em bit} & \tty{TAB, TMB, Tc} \\
\end{tabular}\end{center}
\end{table*}
\begin{table*}
\begin{center}\begin{tabular}{|l|l|}
Operand & Typen \\
{\em src, dest} & \tty{A, W, X, Y, Z, DPL, DPH} (Register) \\
& \tty{T, TL, TH} (Timer, obere/untere H"alfte) \\
& \tty{(DP), M} (Speicher adressiert durch DPH/DPL) \\
& \tty{\#val} (4/8 bit immediate) \\
& \tty{PP} (Port-Pointer) \\
{\em bit} & \tty{C} (Carry) \\
& \tty{(PP)},{\em bitpos} \\
& \tty{(DP)},{\em bitpos} \\
& \tty{(A)},{\em bitpos} \\
{\em bitpos} & \tty{0..3} \\
\end{tabular}\end{center}
\caption{Operandentypen f"ur Meta-Befehle OLMS-40}
\end{table*}
%%---------------------------------------------------------------------------
Der Datenspeicher dieser 4-Bit-Controller besteht aus bis zu 128
Nibbles. F"ur die daf"ur ben"otigten sieben Adre"sbits war
jedoch nur in den wenigsten Instruktionen Platz, so da"s einmal
wieder Banking zur Adressierung herhalten mu"s. Die meisten
Befehle, die Speicher adressieren, enthalten nur die untersten
vier Bits der RAM-Adresse, und sofern nicht die untersten 16
Nibbles angesprochen werden sollen, liefert das P-Register die
notwendigen obere Adre"sbits. Dessen aktuellen Wert teilt man
dem Assembler "uber ein
\begin{verbatim}
assume p:<Wert>
\end{verbatim}
mit, z.B. direkt nach einem \tty{PAGE}-Befehl.
Mit \tty{PAGE} ist auch ein anderes Thema angeschnitten: sowohl
\tty{PAGE} als auch \tty{SWITCH} sind auf diesen Controllern
Maschinenbefehle, d.h. haben nicht ihre von anderen Targets
"ubliche Funktion. Der Pseudobefehl, um ein \tty{SWITCH/CASE}-
Konstrukt einzuleiten, lautet im OLMS-50-Modus \tty{SELECT}, und
die Seitengr"o"se des Listings legt man mit \tty{PAGESIZE} fest.
%%---------------------------------------------------------------------------
Der Programmspeicher dieser Mikrokontroller ist in Seiten zu
128 Worten eingeteilt. Diese Einteilung existiert eigentlich nur
deswegen, weil es Sprungbefehle gibt, deren Ziel innerhalb der
gleichen Seite liegen darf, und andererseits ,,lange'' Exemplare,
die den ganzen Adre"sbereich erreichen k"onnen. Die Standard-Syntax
von Mitsubishi verlangt eigentlich, da"s Seite und Offset als getrennte
Argument geschrieben werden m"ussen. Da das aber reichlich unpraktisch
ist (ansonsten hat man als Programmierer keine Veranlassung, sich um
Seiten zu k"ummern, mit der Ausnahme von indirekten Spr"ungen), erlaubt
es \asname{} auch wahlweise, die Zieladresse linear zu schreiben, also z.B.
\begin{verbatim}
bl $1234
\end{verbatim}
anstelle
\begin{verbatim}
bl $24,$34 .
\end{verbatim}
%%---------------------------------------------------------------------------
Da die undokumentierten Befehle des 6502 sich naturgem"a"s in keinem
Datenbuch finden, sollen sie an dieser Stelle kurz aufgelistet werden.
Die Verwendung erfolgt naturgem"a"s auf eigene Gefahr, da es keine
Gew"ahr gibt, da"s alle Maskenversionen alle Varianten unterst"utzen!
Bei den CMOS-Nachfolgern des 6502 funktionieren sie sowieso nicht
mehr, da diese die entsprechenden Bitkombinationen mit offiziellen Befehlen
belegen...
%%TEMP
\clearpage
Es bedeuten:
\begin{tabbing}
\& \> bin"ares UND \\
| \> bin"ares ODER \\
\verb!^! \> bin"ares EXOR \\
$<<$ \> logischer Linksshift \\
$>>$ \> logischer Rechtsshift \\
$<<<$ \> Linksrotation \\
$>>>$ \> Rechtsrotation \\
$\leftarrow$ \> Zuweisung \\
(..) \> Inhalt von .. \\
{..} \> Bits .. \\
A \> Akkumulator \\
X,Y \> Indexregister X,Y \\
S \> Stapelzeiger \\
An \> Akkumulatorbit n \\
M \> Operand \\
C \> Carry \\
PCH \> obere H"alfte Programmz"ahler \\
\end{tabbing}
\begin{tabbing}
Adressierungsmodi \= : \= \kill \\
Anweisung \> : \> \tty{JAM, KIL} oder \tty{CRS} \\
Funktion \> : \> keine, Prozessor wird angehalten \\
Adressierungsmodi \> : \> implizit \\
\end{tabbing}
\begin{tabbing}
Adressierungsmodi \= : \= \kill \\
Anweisung \> : \> \tty{SLO} \\
Funktion \> : \> $M\leftarrow((M)<<1)|(A)$ \\
Adressierungsmodi \> : \> absolut lang/kurz, X-indiziert lang/kurz, \\
\> \> Y-indiziert lang, X/Y-indirekt \\
\end{tabbing}
\begin{tabbing}
Adressierungsmodi \= : \= \kill \\
Anweisung \> : \> \tty{ANC} \\
Funktion \> : \> $A\leftarrow(A)\&(M), C\leftarrow A7$ \\
Adressierungsmodi \> : \> immediate \\
\end{tabbing}
\begin{tabbing}
Adressierungsmodi \= : \= \kill \\
Anweisung \> : \> \tty{RLA} \\
Funktion \> : \> $M\leftarrow((M)<<1)\&(A)$ \\
Adressierungsmodi \> : \> absolut lang/kurz, X-indiziert lang/kurz, \\
\> \> Y-indiziert lang, X/Y-indirekt \\
\end{tabbing}
\begin{tabbing}
Adressierungsmodi \= : \= \kill \\
Anweisung \> : \> \tty{SRE} \\
Funktion \> : \> $M\leftarrow((M)>>1)$\verb!^!$(A)$ \\
Adressierungsmodi \> : \> absolut lang/kurz, X-indiziert lang/kurz, \\
\> \> Y-indiziert lang, X/Y-indirekt \\
\end{tabbing}
\begin{tabbing}
Adressierungsmodi \= : \= \kill \\
Anweisung \> : \> \tty{ASR} \\
Funktion \> : \> $A\leftarrow((A)\&(M))>>1$ \\
Adressierungsmodi \> : \> immediate \\
\end{tabbing}
\begin{tabbing}
Adressierungsmodi \= : \= \kill \\
Anweisung \> : \> \tty{RRA} \\
Funktion \> : \> $M\leftarrow((M)>>>1)+(A)+(C)$ \\
Adressierungsmodi \> : \> absolut lang/kurz, X-indiziert lang/kurz, \\
\> \> Y-indiziert lang, X/Y-indirekt \\
\end{tabbing}
\begin{tabbing}
Adressierungsmodi \= : \= \kill \\
Anweisung \> : \> \tty{ARR} \\
Funktion \> : \> $A\leftarrow((A)\&(M))>>>1$ \\
Adressierungsmodi \> : \> immediate \\
\end{tabbing}
\begin{tabbing}
Adressierungsmodi \= : \= \kill \\
Anweisung \> : \> \tty{SAX} \\
Funktion \> : \> $M\leftarrow(A)\&(X)$ \\
Adressierungsmodi \> : \> absolut lang/kurz, Y-indiziert kurz, \\
\> \> Y-indirekt \\
\end{tabbing}
\begin{tabbing}
Adressierungsmodi \= : \= \kill \\
Anweisung \> : \> \tty{ANE} \\
Funktion \> : \> $M\leftarrow((A)\&\$ee)|((X)\&(M))$ \\
Adressierungsmodi \> : \> immediate \\
\end{tabbing}
\begin{tabbing}
Adressierungsmodi \= : \= \kill \\
Anweisung \> : \> \tty{SHA} \\
Funktion \> : \> $M\leftarrow(A)\&(X)\&(PCH+1)$ \\
Adressierungsmodi \> : \> X/Y-indiziert lang \\
\end{tabbing}
\begin{tabbing}
Adressierungsmodi \= : \= \kill \\
Anweisung \> : \> \tty{SHS} \\
Funktion \> : \> $X\leftarrow(A)\&(X), S\leftarrow(X), M\leftarrow(X)\&(PCH+1)$ \\
Adressierungsmodi \> : \> Y-indiziert lang \\
\end{tabbing}
\begin{tabbing}
Adressierungsmodi \= : \= \kill \\
Anweisung \> : \> \tty{SHY} \\
Funktion \> : \> $M\leftarrow(Y)\&(PCH+1)$ \\
Adressierungsmodi \> : \> Y-indiziert lang \\
\end{tabbing}
\begin{tabbing}
Adressierungsmodi \= : \= \kill \\
Anweisung \> : \> \tty{SHX} \\
Funktion \> : \> $M\leftarrow(X)\&(PCH+1)$ \\
Adressierungsmodi \> : \> X-indiziert lang \\
\end{tabbing}
\begin{tabbing}
Adressierungsmodi \= : \= \kill \\
Anweisung \> : \> \tty{LAX} \\
Funktion \> : \> $A,X\leftarrow(M)$ \\
Adressierungsmodi \> : \> absolut lang/kurz, Y-indiziert lang/kurz, \\
\> \> X/Y-indirekt \\
\end{tabbing}
\begin{tabbing}
Adressierungsmodi \= : \= \kill \\
Anweisung \> : \> \tty{LXA} \\
Funktion \> : \> $X{04}\leftarrow(X){04} \& (M){04},$ \\
\> \> $A{04}\leftarrow(A){04} \& (M){04}$ \\
Adressierungsmodi \> : \> immediate \\
\end{tabbing}
\begin{tabbing}
Adressierungsmodi \= : \= \kill \\
Anweisung \> : \> \tty{LAE} \\
Funktion \> : \> $X,S,A\leftarrow((S)\&(M))$ \\
Adressierungsmodi \> : \> Y-indiziert lang \\
\end{tabbing}
\begin{tabbing}
Adressierungsmodi \= : \= \kill \\
Anweisung \> : \> \tty{DCP} \\
Funktion \> : \> $M \leftarrow(M)-1, Flags\leftarrow((A)-(M))$ \\
Adressierungsmodi \> : \> absolut lang/kurz, X-indiziert lang/kurz, \\
\> \> Y-indiziert lang, X/Y-indirekt \\
\end{tabbing}
\begin{tabbing}
Adressierungsmodi \= : \= \kill \\
Anweisung \> : \> \tty{SBX} \\
Funktion \> : \> $X\leftarrow((X)\&(A))-(M)$ \\
Adressierungsmodi \> : \> immediate \\
\end{tabbing}
\begin{tabbing}
Adressierungsmodi \= : \= \kill \\
Anweisung \> : \> \tty{ISB} \\
Funktion \> : \> $M\leftarrow(M)+1, A\leftarrow(A)-(M)-(C)$ \\
Adressierungsmodi \> : \> absolut lang/kurz, X-indiziert lang/kurz, \\
\> \> Y-indiziert lang, X/Y-indirekt \\
\end{tabbing}
%%---------------------------------------------------------------------------
Die Mikrokontroller dieser Reihe haben ein sehr nettes, verstecktes
Feature: Setzt man mit dem Befehl \tty{SET} das Bit 5 des
Statusregisters, so wird bei allen arithmetischen Operationen (und
Ladebefehlen) der Akkumulator durch die durch das X-Register adressierte
Speicherzelle ersetzt. Dieses Feature syntaxm"a"sig sauber zu integrieren,
ist bisher nicht geschehen, d.h. es kann bisher nur im ,,Handbetrieb''
(\tty{SET}...Befehle mit Akkuadressierung...\tty{CLT}) genutzt werden.
Nicht alle MELPS-740-Prozessoren implementieren alle Befehle. An dieser
Stelle mu"s der Programmierer aufpassen, da"s er nur die Befehle benutzt,
die auch wirklich vorhanden sind, da \asname{} die Prozessoren dieser Familie
nicht n"aher unterscheidet. Die Besonderheiten der
Special-Page-Adressierung werden bei der Erkl"arung von \tty{ASSUME} n"aher
erl"autert.
%%---------------------------------------------------------------------------
Offensichtlich haben diese beiden Prozessorfamilien ausgehend vom
6502 ("uber ihre 8-bittigen Vorg"anger) etwas disjunkte Entwicklungswege
hinter sich. Kurz aufgelistet, ergeben sich folgende Unterschiede:
\begin{itemize}
\item{der 65816 hat keinen B-Akkumulator.}
\item{beim 65816 fehlen Multiplikations- sowie Divisionsbefehle.}
\item{Die Befehle \tty{SEB}, \tty{CLB}, \tty{BBC}, \tty{BBS},
\tty{CLM}, \tty{SEM}, \tty{PSH}, \tty{PUL} und \tty{LDM}
fehlen beim 65816. An deren Stelle in der Code-Tabelle finden
sich \tty{TSB}, \tty{TRB}, \tty{BIT}, \tty{CLD}, \tty{SED},
\tty{XBA}, \tty{XCE} und \tty{STZ}.}
\end{itemize}
Identische Funktion, jedoch andere Namen haben folgende Befehle:
\begin{center}\begin{tabular}{|c|c||c|c|}
65816 & MELPS-7700 & 65816 & MELPS-7700 \\
\tty{REP} & \tty{CLP} & \tty{PHK} & \tty{PHG} \\
\tty{TCS} & \tty{TAS} & \tty{TSC} & \tty{TSA} \\
\tty{TCD} & \tty{TAD} & \tty{TDC} & \tty{TDA} \\
\tty{PHB} & \tty{PHT} & \tty{PLB} & \tty{PLT} \\
\tty{WAI} & \tty{WIT} & & \\
\end{tabular}\end{center}
Besonders t"uckisch sind die Befehle \tty{PHB}, \tty{PLB} und \tty{TSB}:
diese Befehle haben jeweils eine v"ollig andere Funktion und Kodierung!
Leider tun diese Prozessoren mit ihrem Speicher etwas, was f"ur mich
auf der nach oben offenen Perversit"atsskala noch vor der
Intel-m"a"sigen Segmentierung rangiert: sie banken ihn!
Nunja, dies ist wohl der Preis f"ur die 6502-Aufw"artskompatibilit"at;
wie dem auch sei, damit \asname{} den gew"unschten Code erzeugen kann, mu"s
man ihn "uber den \tty{ASSUME}-Befehl "uber den Inhalt einiger
Register in Kenntnis setzen:
Das M-Flag bestimmt, ob die Akkumulatoren A und B 8 Bit (1) oder 16 Bit
(0) breit sein sollen. Analog entscheidet das Flag X "uber die Breite
der Indexregister X und Y. \asname{} ben"otigt die Information "uber die
Registerbreite bei unmittelbarer Adressierung (\tty{\#<Konstante>}), ob das
Argument 8 oder 16 Bit breit sein soll.
Der Speicher ist in 256 B"anke zu 64 Kbyte geteilt. Da alle Register
im Prozessor nur maximal 16 Bit breit sind, kommen die obersten 8
Adre"sbits aus 2 speziellen Bank-Registern: DT liefert die oberen 8
Bits bei Datenzugriffen, PG erweitert den 16-bittigen Programmz"ahler
auf 24 Bit. Die vom 6502 her bekannte ,,Zero-Page'' ist mittels
des 16 Bit breiten Registers DPR frei innerhalb der ersten Bank
verschiebbar. Trifft \asname{} nun im Code auf eine Adresse (egal ob in
einem absoluten, indizierten oder indirekten Ausdruck), so versucht
er der Reihe nach folgende Adressierungsvarianten:
\begin{enumerate}
\item{Liegt die Adresse im Bereich von DPR...DPR+\$ff? Falls ja,
Verwendung von direkter Adressierung mit 8-Bit-Adresse.}
\item{Liegt die Adresse innerhalb der durch DT (bzw. PG f"ur
Sprungbefehle) festgelegten Seite? Falls ja, Verwendung von
absoluter Adressierung mit 16-Bit-Adresse.}
\item{Falls nichts anderes hilft, Verwendung von langer Adressierung
mit 24-Bit-Adresse.}
\end{enumerate}
Aus dieser Aufz"ahlung folgt, da"s das Wissen "uber die momentanen
Werte von DT,PG und DPR f"ur die Funktion von \asname{} essentiell ist;
sind die Angaben fehlerhaft, adressiert das Programm ,,in die W"uste''.
Diese Aufz"ahlung geht "ubrigens davon aus, da"s alle drei
Adre"sl"angen verf"ugbar sind; sollte dies einmal nicht der Fall sein,
so wird die Entscheidungskette entsprechen k"urzer.
Die oben geschilderte, automatische Festlegung der Adre"sl"ange l"a"st
sich auch durch die Verwendung von Pr"afixen "ubersteuern. Stellt
man der Adresse ein $<$, $>$ oder $>>$ ohne trennendes Leerzeichen voran,
so wird eine Adresse mit 1, 2 oder 3 Bytes benutzt, unabh"angig davon,
ob dies die optimale L"ange ist. Benutzt man eine f"ur diesen Befehl
nicht erlaubte oder f"ur die Adresse zu kurze L"ange, gibt es eine
Fehlermeldung.
Um die Portierung von 6502-Programmen zu erleichtern, verwendet \asname{} f"ur
Hexadezimalkonstanten die Motorola-Syntax und nicht die von Mitsubishi
"ubrigens f"ur die 740er favorisierte Intel/IEEE-Schreibweise.
Ich halte erstere auch f"ur die bessere Schreibweise, und die Entwickler
des 65816 werden dies vermutlich "ahnlich gesehen haben (da man mittels
der \tty{RELAXED}-Anweisung auch Intel-Notation benutzen kann, wird durch
diese Entscheidung auch niemand festgelegt). Ein f"ur die
Portierung "ahnlich wichtiges Detail ist, da"s der Akkumulator A als
Ziel von Operationen auch weggelassen werden darf, anstelle von
\tty{LDA A,\#0} darf also z.B. auch einfach \tty{LDA \#0} geschrieben
werden.
Ein echtes Bonbon in dem Befehlssatz sind dagegen die Blocktransferbefehle
\tty{MVN} und \tty{MVP}. Etwas eigenartig ist nur die Adre"sangabe:
Bit 0--15 im Indexregister, Bit 16--23 im Befehl. Bei \asname{} gibt man als
Argument f"ur beide Speicherbl"ocke einfach die vollen Adressen an, \asname{}
fischt sich dann die passenden Bits automatisch heraus. Dies ist ein
feiner, aber wichtiger Unterschied zum Mitsubishi-Assembler, bei dem
man die oberen 8 Bit selber herausziehen mu"s. Richtig bequem
wird es aber erst mit einem Makro im folgendem Stil:
\begin{verbatim}
mvpos macro src,dest,len
if MomCPU=$7700
lda #len
elseif
lda #(len-1)
endif
ldx #(src&$ffff)
ldy #(dest&$ffff)
mvp dest,src
endm
\end{verbatim}
Vorsicht, Falle: Steht im Akkumulator die Zahl $n$, so transferiert
der Mitsubishi $n$ Bytes, der 65816 jedoch $n+1$ Bytes!
Sehr nett sind auch die Befehle \tty{PSH} und \tty{PUL}, mit deren Hilfe es
m"oglich ist, mit einem Befehl einen frei w"ahlbaren Satz von Registern
auf dem Stack zu sichern oder von ihm zu laden. Nach dem
Mitsubishi-Datenbuch\cite{Mit16} mu"s die Angabe der Bitmasken immediate
erfolgen, der Programmierer soll also entweder alle
Register$\leftrightarrow$Bitstellen-Zuordnungen im Kopf behalten oder
sich passende Symbole definieren. Hier habe ich die Syntax eigenm"achtig
erweitert, um die Sache etwas angenehmer zu machen: Es darf eine Liste
angegeben werden, die sowohl immediate-Ausdr"ucke als auch Registernamen
enthalten darf. Damit sind z.B. die Anweisungen
\begin{verbatim}
psh #$0f
\end{verbatim}
und
\begin{verbatim}
psh a,b,#$0c
\end{verbatim}
und
\begin{verbatim}
psh a,b,x,y
\end{verbatim}
"aquivalent. Da die immediate-Version weiterhin erlaubt ist, bleibt
\asname{} hier ,,aufw"artskompatibel'' zu den Mitsubishi-Assemblern.
Nicht ganz habe ich beim Mitsubishi-Assembler die Behandlung des
\tty{PER}-Befehles verstanden: Mit diesem Befehl kann man eine
16-Bit-Variable auf den Stack legen, deren Adresse relativ zum
Programmz"ahler angegeben wird. Es ist aus der Sicht des Programmierers
also eine absolute Adressierung einer Speicherzelle. Nichtsdestotrotz
verlangt Mitsubishi eine immediate-Adressierung, und das Argument wird so
in den Code eingesetzt, wie es im Quelltext steht. Die Differenz mu"s
man selber ausrechnen, was mit der Einf"uhrung von symbolischen Assemblern
ja abgeschafft werden sollte...da ich aber auch ein bi"schen ,,kompatibel''
denken mu"s, enth"alt \asname{} eine Kompromi"sl"osung: W"ahlt man
immediate-Adressierung (also mit Gartenzaun), so verh"alt sich \asname{} wie das
Original von Mitsubishi. L"a"st man ihn jedoch weg, so berechnet \asname{} die
Differenz vom Argument zum momentanen Programmz"ahler und setzt diese
ein.
"Ahnlich sieht es beim \tty{PEI}-Befehl aus, der den Inhalt einer
16-Bit-Variablen auf der Zeropage auf den Stack legt: Obwohl der Operand
eine Adresse ist, wird wieder immediate-Adressierung verlangt. Hier
l"a"st \asname{} schlicht beide Versionen zu (d.h. mit oder ohne Gartenzaun).
%%---------------------------------------------------------------------------
Die M16-Familie ist eine Familie "au"serst komplexer CISC-Prozessoren
mit einem entsprechend komplizierten Befehlssatz. Zu den Eigenschaften
dieses Befehlssatzes geh"ort es unter anderem, da"s bei Operationen
mit zwei Operanden beide Operanden verschiedene L"angen haben d"urfen.
Die bei Motorola "ubliche und von Mitsubishi "ubernommene Methode, die
Operandengr"o"se als Attribut an den Befehl anzuh"angen, mu"ste daher
erweitert werden: Es ist erlaubt, auch an die Operanden selber Attribute
anzuh"angen. So wird im folgenden Beispiel
\begin{verbatim}
mov r0.b,r6.w
\end{verbatim}
Register 0 8-bittig gelesen, auf 32 Bit vorzeichenerweitert und das
Ergebnis in Register 6 kopiert. Da man in 9 von 10 F"allen aber von
diesen M"oglichkeiten doch keinen Gebrauch macht, kann man weiterhin
die Operandengr"o"se an den Befehl selber schreiben, z.B. so:
\begin{verbatim}
mov.w r0,r6
\end{verbatim}
Beide Varianten d"urfen auch gemischt verwendet werden, eine
Gr"o"senangabe am Operanden "ubersteuert dann den ,,Default'' am Befehl.
Eine Ausnahme stellen Befehle mit zwei Operanden dar. Bei diesen ist
der Default f"ur den Quelloperanden die Gr"o"se des Zieloperanden. In
folgendem Beispiel
\begin{verbatim}
mov.h r0,r6.w
\end{verbatim}
wird also auf Register 0 32-bittig zugegriffen, die Gr"o"senangabe
am Befehl wird "uberhaupt nicht mehr benutzt. Finden sich "uberhaupt
keine Angaben zur Operandengr"o"se, so wird Wort(w) verwendet. Merke:
im Gegensatz zu den 68000ern bedeutet dies 32 und nicht 16 Bit!
Reichlich kompliziert sind auch die verketteten Adressierungsmodi;
dadurch, da"s \asname{} die Verteilung auf Kettenelemente automatisch
vornimmt, bleibt die Sache aber einigerma"sen "ubersichtlich. Die
einzige Eingriffsm"oglichkeit, die bei \asname{} gegeben ist (der Originalassembler
von Mitsubishi/Green Hills kann da noch etwas mehr), ist die explizite
Festlegung von Displacement-L"angen mittels der Anh"angsel \tty{:4},
\tty{:16} und \tty{:32}.
%%---------------------------------------------------------------------------
Der CP-3F wurde Anfang der 70er-Jahre entwickelt, wo auch die Entwicklungssysteme
deutlich weniger leistungsf"ahig waren und bei der Assembler-Syntax auch
auf die leichte Umsetzbarkeit im Maschinensprache geachtet wurde. So
gruppieren sich die Original-Mnemonics in wenige Gruppen: Befehle mit
3/4- oder 8-Bit-immediate-Argument, solche mit einem Registeroperanden,
Spr"unge und Befehle ganz ohne Argumente. Das l"ast sich mit relativ wenig
Aufwand in Maschinencode "ubersetzen, der Lesbarkeit des Quellcodes
ist das aber eher abtr"aglich - "ahnlich wie beim Intel 8080. Ich habe mich
deshalb entschlossen, f"ur die meisten Befehle eine alternative Schreibweise
anzubieten, die verst"andlicher ausdr"uckt, was der jeweilige Befehl
tut:
\begin{longtable}{|l|l|l|}
Original & Alternativ & Funktion \\
\endhead
\input{../doc_COM/cp3finst.tex}
\caption{Alternative Befehlsschreibweisen f"ur CP-3F}
\end{longtable}
%%---------------------------------------------------------------------------
John Weinrich sei dank, habe ich nun auch die offiziellen Datenbl"atter
von Intel "uber diese 'Urv"ater' aller Mikroprozessoren, und die
Unklarheiten "uber die Syntax von Registerpaaren (f"ur 8-Bit-Operationen)
sind f"urs erste ausger"aumt. Die Syntax lautet \tty{RnRm}, wobei \tty{n}
bzw. \tty{m} gerade Integers im Bereich 0 bis E bzw. 1 bis F sind. Dabei
gilt immer \tty{m = n + 1}.
%%---------------------------------------------------------------------------
Der maximale Adre"sraum dieser Prozessoren betr"agt 4 KByte, bzw. 8 KByte
bei einigen Philips-Varianten. Dieser Raum ist jedoch nicht linear organisiert
(wie k"onnte das bei Intel auch anders sein...), sondern in 2 B"anke zu 2
Kbyte geteilt. Ein Wechsel zwischen diesen beiden B"anken ist nur durch die
Befehle \tty{CALL} und \tty{JMP} erlaubt, indem vor dem Sprung das h"ochste
Adre"sbit mit den Befehlen \tty{SEL MB0} bis \tty{SEL MB3} vorgegeben wird.
Man kann dem Assembler mit einem
\begin{verbatim}
ASSUME MB:<0..3>
\end{verbatim}
mitteilen, welche Speicherbank gerade f"ur Sprungziele gew"ahlt ist; wird auf
eine Adresse gesprungen, die au"serhalb dieser Bank liegt, wird eine Warnung
ausgegeben.
Wenn der Sonderwert {\tt NOTHING} angegeben wird (dies ist auch der Default),
so greift eine in den Befehlen \tty{JMP} und \tty{CALL} eingebaute Automatik ,
die den Wechsel zwischen den B"anken vereinfacht. Sie f"ugt automatisch einen
{\tt SEL MBx} Befehl ein, falls die Adresse des Sprungbefehles und das
Sprungziel in unterschiedlichen B"anken liegen. Die explizite Benutzung der
\tty{SEL MBx}-Befehle ist dann nicht mehr notwendig (obwohl sie m"oglich
bleibt) und kann die Automatik auch durcheinanderbringen, wie in dem folgenden
Beispiel:
\begin{verbatim}
000: SEL MB1
JMP 200h
\end{verbatim}
\asname{} nimmt an, da"s das MB-Flag auf 0 steht und f"ugt keinen
\tty{SEL MB0}-Befehl vor dem Sprung ein, mit der Folge, da"s der
Prozessor zur Adresse A00h springt.
Weiterhin ist zu beachten, da"s ein Sprungbefehl durch diesen Mechanismus
unter Umst"anden ein Byte l"anger wird.
%%---------------------------------------------------------------------------
Dem Assembler liegen die Dateien STDDEF51.INC bzw. 80C50X.INC bei, in
denen alle Bits und SFRs der Prozessoren 8051, 8052 und 80515 bzw. 80C501,
502 und 504 verzeichnet sind. Je nach Einstellung des Prozessortyps mit
dem \tty{CPU}-Befehl wird dabei die korrekte Untermenge eingebunden, die
richtige Reihenfolge f"ur den Anfang eines Programms ist daher
\begin{verbatim}
CPU <Prozessortyp>
INCLUDE stddef51.inc ,
\end{verbatim}
sonst f"uhren die MCS-51-Pseudobefehle in der Include-Datei zu
Fehlermeldungen.
Da der 8051 keinen Befehl kennt, um die Register 0..7 auf den Stack zu
legen, mu"s mit deren absoluten Adressen gearbeitet werden. Diese
h"angen aber von der momentan aktiven Registerbank ab. Um diesem Mi"sstand
etwas abzuhelfen, ist in den Include-Dateien das Makro \tty{USING} definiert,
dem als Parameter die Symbole \tty{Bank0..Bank3} gegeben werden k"onnen.
Das Makro belegt daraufhin die Symbole \tty{AR0..AR7} mit den passenden
absoluten Adressen der Register. Dieses Makro sollte nach jeder
Bankumschaltung benutzt werden. Es erzeugt selber \ii{keinen} Code zur
Umschaltung!
Das Makro f"uhrt in der Variablen \tty{RegUsage} gleichzeitig Buch "uber
alle jemals benutzten Registerb"anke; Bit 0 entspricht Bank 0, Bit 1 der
Bank 1 usw. . Der Inhalt kann am Ende der Quelldatei z.B. mit folgendem
Codest"uck ausgegeben werden:
\begin{verbatim}
irp BANK,Bank0,Bank1,Bank2,Bank3
if (RegUsage&(2^BANK))<>0
message "Bank \{BANK} benutzt"
endif
endm
\end{verbatim}
Mit der Mehrpass-F"ahigkeit ab Version 1.38 wurde es m"oglich, zus"atzlich
die Befehle \tty{JMP} und \tty{CALL} einzuf"uhren. Bei der Kodierung
von Spr"ungen mit diesen Befehlen w"ahlt \asname{} je nach Adre"slage automatisch
die optimale Variante, d.h. \tty{SJMP/AJMP/LJMP} f"ur \tty{JMP} und
\tty{ACALL/LCALL} f"ur \tty{CALL}. Es ist nat"urlich weiterhin m"oglich,
die Varianten direkt zu verwenden, um eine bestimmte Kodierung zu erzwingen.
%%---------------------------------------------------------------------------
Intel hat sich beim 80C251 ja bem"uht, den "Ubergang f"ur den Programmierer
auf die neue Familie so weich wie m"oglich zu gestalten, was darin gipfelt,
da"s alte Anwendungen ohne Neu"ubersetzung auf dem neuen Prozessor ablaufen
k"onnen. Sobald man jedoch den erweiterten Befehlssatz der 80C251 nutzen
will, gilt es, einige Details zu beachten, die sich als versteckte
Fu"sangeln auftun.
An vorderster Stelle steht dabei die Tatsache, da"s der 80C251 keinen
getrennten Bitadre"sraum mehr hat. Es sind nunmehr alle SFRs unabh"angig
von ihrer Adre"slage sowie die ersten 128 Speicherstellen des internen
RAMs bitadressierbar. M"oglich wird dies dadurch, da"s die Bitadressierung
nicht mehr "uber einen zus"atzlichen virtuellen Adre"sraum, der andere
Adre"sr"aume "uberdeckt, erfolgt, sondern so wie bei anderen Prozessoren
auch durch eine zweidimensionale Adressierung, die aus der Speicherstelle,
die das Bit beinhaltet sowie der Bitstelle im Byte besteht. Dies bedeutet
zum einen, da"s bei einer Bitangabe wie z.B. PSW.7 \asname{} die Zerlegung der
Teile links und rechts vom Punkt selber vornimmt. Es ist also nicht mehr
n"otig, mittels eines \tty{SFRB}-Befehls wie noch beim 8051 explizit 8
Bitsymbole zu erzeugen. Dies bedeutet zum anderen, da"s es den
\tty{SFRB}-Befehl "uberhaupt nicht mehr gibt. Wird er in zu portierenden
8051-Programmen benutzt, kann er durch einen einfachen \tty{SFR}-Befehl
ersetzt werden.
Weiterhin hat Intel in den unterschiedlichen Adre"sr"aumen des 8051
geh"orig aufger"aumt: Der Bereich des internen RAMs (\tty{DATA} bzw.
\tty{IDATA}), der \tty{XDATA}-Bereich und er bisherige \tty{CODE}-Bereich
wurden in einem einzigen, 16 Mbyte gro"sen \tty{CODE}-Bereich vereinigt.
Das interne RAM beginnt bei Adresse 0, das interne ROM beginnt bei
Adresse ff0000h, dorthin mu"s also auch der Code mittels \tty{ORG}
hinverlagert werden. Ausgelagert wurden dagegen die \tty{SFRs} in einen
eigenen Adre"sraum (der bei \asname{} als \tty{IO}-Segment definiert ist). In
diesem neuen Adre"sraum haben sie aber die gleichen Adressen wie beim 8051.
Der \tty{SFR}-Befehl kennt diesen Unterschied und legt mit ihm erzeugte
Symbole je nach Zielprozessor automatisch ins \tty{DATA}- bzw.
\tty{IO}-Segment. Da es keinen Bit-Adre"sraum mehr gibt, funktioniert der
\tty{BIT}-Befehl v"ollig anders: anstelle einer linearen Adresse von 0 bis
255 beinhalten Bit-Symbole jetzt in Bit 0..7 die Adresse, in Bit 24..26
die Bitstelle. Damit ist es jetzt leider nicht mehr so einfach m"oglich,
Felder von Flags mit symbolischen Namen anzulegen: Wo man beim 8051 noch
z.B.
\begin{verbatim}
segment bitdata
bit1 db ?
bit2 db ?
\end{verbatim}
oder
\begin{verbatim}
defbit macro name
name bit cnt
cnt set cnt+1
endm
\end{verbatim}
schreiben konnte, hilft jetzt nur noch die zweite Variante weiter, z.B.
so:
\begin{verbatim}
adr set 20h ; Startadresse Flags im internen RAM
bpos set 0
defbit macro name
name bit adr.bpos
bpos set bpos+1
if bpos=8
bpos set 0
adr set adr+1
endif
endm
\end{verbatim}
Ein weiteres, kleines Detail: Da Intel als Kennzeichnung f"ur den Carry
nun CY statt C bevorzugt, sollte man ein eventuell benutztes Symbol
umbenennen. \asname{} versteht aber auch weiterhin die alte Variante in den
Befehlen \tty{CLR, CPL, SETB, MOV, ANL,} und \tty{ORL}. Gleiches gilt
sinngem"a"s f"ur die dazugekommenen Register \tty{R8..R15, WR0..WR30,
DR0..DR28, DR56, DR60, DPX} und \tty{SPX}.
Intel m"ochte es gerne, da"s man absolute Adressen in der Form \tty{XX:YYYY}
schreibt, wobei \tty{XX} eine 64K-Bank im Adre"sraum angibt bzw. mit einem
\tty{S} Adressen im IO-Raum kennzeichnet. Wie man sich schon denken kann,
halte ich davon nicht allzu viel, weshalb man an allen Stellen Adressen
genauso gut linear angeben kann; lediglich um das S f"ur die Kennzeichnung
von I/O-Adressen kommt man nicht herum, z.B. hier:
\begin{verbatim}
Carry bit s:0d0h.7
\end{verbatim}
Ohne den Pr"afix w"urde \asname{} die absolute Adresse in das Code-Segment
legen, und dort sind ja nur die ersten 128 Byte bitadressierbar...
Wie auch schon beim 8051 gibt es die generischen Befehle \tty{JMP} und
\tty{CALL}, die je nach Adre"slage automatisch die k"urzeste Variante
einsetzen. W"ahrend \tty{JMP} aber die Variante mit 24 Bit mitber"ucksichtigt,
tut \tty{CALL} dies aus gutem Grund nicht: Der \tty{ECALL}-Befehl legt
n"amlich im Gegensatz zu \tty{ACALL} und \tty{LCALL} 3 Bytes auf den
Stack, und man h"atte sonst einen \tty{CALL}-Befehl, bei dem man nicht
mehr genau wei"s, was er tut. Bei \tty{JMP} tritt diese Problem nicht auf.
Aus einer Sache bin ich nicht ganz schlau geworden: Der 80251 kann
auch immediate-Operanden auf den Stack legen, und zwar sowohl einzelne
Bytes als auch ganze W"orter. F"ur beide Varianten ist aber der gleiche
Befehl \tty{PUSH} vorgesehen -- und woher soll bitte ein Assembler bei
einer Anweisung wie
\begin{verbatim}
push #10
\end{verbatim}
wissen, ob ein Byte oder ein Wort mit dem Wert 10 auf den Stack gelegt
werden soll? Daher gilt im Augenblick die Regelung, da"s \tty{PUSH}
grunds"atzlich ein Byte ablegt; wer ein Wort ablegen will, schreibt
einfach \tty{PUSHW} anstelle \tty{PUSH}.
Noch ein gut gemeinter Ratschlag: Wer den erweiterten Befehlssatz des
80C251 nutzt, sollte den Prozessor auch tunlichst im Source-Modus
betreiben, sonst werden alle neuen Anweisungen ein Byte l"anger! Um
die origin"aren 8051-Anweisungen, die daf"ur im Source-Modus l"anger
werden, ist es nicht besonders schade: Sie werden entweder von \asname{}
automatisch durch neue, leistungsf"ahigere ersetzt oder sind be-
treffen veraltete Adressierungsarten (indirekte Adressierung mit
8-Bit-Registern).
%%---------------------------------------------------------------------------
Wie schon weiter vorne erw"ahnt, ist es m"oglich, durch ein
\begin{verbatim}
Z80SYNTAX <OFF|ON|EXCLUSIVE>
\end{verbatim}
f"ur die allermeisten 8080/8085-Befehle m"oglich, sie auch wahlweise
oder ausschlie"slich im 'Z80-Stil' zu schreiben, d.h. mit weniger
Mnemonics, daf"ur aber mit deutlich aussagekr"aftigeren Operanden.
F"ur die folgenden Befehle ist die Z80-Syntax im nicht-exklusiven Modus
nicht m"oglich, da sie mit existierenden 8080-Mnemonics kollidieren:
\begin{itemize}
\item{\tty{CP} ist in der 'Intel-Syntax' der Befehl f"ur 'Call on
Positive', in der Zilog-Syntax jedoch der Befehl f"ur
'Compare'. Verwendet man \tty{CP} mit einem absoluten
Zahlenwert als Argument, so ist f"ur den Assembler nicht zu
erkennen, ob das ein Sprung zu einer absoluten Adresse sein
soll oder ein Vergleich mit einem immediate-Wert. Der
Assembler wird in so einem Fall einen Sprung kodieren, da
die Intel-Syntax bei Mehrdeutigkeiten Vorrang hat. M"ochte
man den Vergleich haben, so kann man den Akkumulator als
Zieloperanden explizit hinschreiben, also z.B. \tty{CP A,12h}
anstatt \tty{CP 12h}.}
\item{\tty{JP} ist in der Intel-Syntax der Befehl f"ur 'Jump on
Positive', in der Zilog-Syntax jedoch der allgemeine
Sprung-Befehl. F"ur bedingte Spr"unge in Zilog-Syntax (\tty{JP
cond,addr}) ist die Sache wegen der zwei Argumente eindeutig,
bei nur einem Argument wird der Assembler aber den bedingten
Sprung kodieren. Wer einen unbedingten Sprung zu einer
absoluten Adresse haben m"ochte, mu"s weiterhin die
Intel-Variante (\tty{JMP addr}) verwenden.}
\end{itemize}
Der 8085 unterst"utzt mit \tty{RIM} und \tty{SIM} zwei Befehle, die
im Z80-Befehlssatz nicht existieren. Diese k"onnen ''Z80-artig'' als
\tty{LD A,IM} bzw. \tty{LD IM,A} geschrieben werden.
%%---------------------------------------------------------------------------
"Ahnlich wie beim Z80 oder 6502, sind auch beim 8085 die undokumentierten
Befehle nicht n"aher von Intel spezifiziert worden, weshalb es nicht
undenkbar ist, da"s andere Assembler andere Mnemonics daf"ur verwenden.
Deshalb sollen auch diese Befehle und ihre Funktion hier kurz aufgelistet
werden. Und auch hier wieder ist die Verwendung dieser Befehle auf
eigenes Risiko - schon der an sich zum 8085 aufw"artskompatible Z80
benutzt diese Opcodes f"ur v"ollig andere Funktionen...
\begin{tabbing}
Argumente \= : \= \kill \\
Anweisung \> : \> \tty{DSUB [reg]} \\
Z80-Syntax \> : \> \tty{SUB HL,reg} \\
Funktion \> : \> HL $\leftarrow$ HL - reg \\
Flags \> : \> CY, S, X5, AC, Z, V, P \\
Argumente \> : \> \tty{reg} = B f"ur BC (optional f"ur nicht-Z80-Syntax) \\
\end{tabbing}
\begin{tabbing}
Argumente \= : \= \kill \\
Anweisung \> : \> \tty{ARHL} \\
Z80-Syntax \> : \> \tty{SRA HL} \\
Funktion \> : \> HL,CY $\leftarrow$ HL $>>$ 1 (arithmetisch) \\
Flags \> : \> CY \\
Argumente \> : \> keine bzw. fix f"ur Z80-Syntax \\
\end{tabbing}
\begin{tabbing}
Argumente \= : \= \kill \\
Anweisung \> : \> \tty{RDEL} \\
Z80-Syntax \> : \> \tty{RLC DE} \\
Funktion \> : \> CY,DE $\leftarrow$ DE $<<$ 1 \\
Flags \> : \> CY, V \\
Argumente \> : \> keine bzw. fix f"ur Z80-Syntax \\
\end{tabbing}
\begin{tabbing}
Argumente \= : \= \kill \\
Anweisung \> : \> \tty{LDHI d8} \\
Z80-Syntax \> : \> \tty{ADD DE,HL,d8} \\
Funktion \> : \> DE $\leftarrow$ HL + {\tt d8} \\
Flags \> : \> keine \\
Argumente \> : \> {\tt d8} = 8-Bit-Konstante, Register fix f"ur Z80-Syntax \\
\end{tabbing}
\begin{tabbing}
Argumente \= : \= \kill \\
Anweisung \> : \> \tty{LDSI d8} \\
Z80-Syntax \> : \> \tty{ADD DE,SP,d8} \\
Funktion \> : \> DE $\leftarrow$ SP + {\tt d8} \\
Flags \> : \> keine \\
Argumente \> : \> {\tt d8} = 8-Bit-Konstante, Register fix f"ur Z80-Syntax \\
\end{tabbing}
\begin{tabbing}
Argumente \= : \= \kill \\
Anweisung \> : \> \tty{RSTflag} \\
Z80-Syntax \> : \> \tty{RST flag} \\
Funktion \> : \> Restart zu 40h wenn {\tt flag}=1 \\
Flags \> : \> keine \\
Argumente \> : \> {\tt flag} = V f"ur Overflow-Bit \\
\end{tabbing}
\begin{tabbing}
Argumente \= : \= \kill \\
Anweisung \> : \> \tty{SHLX [reg]} \\
Z80-Syntax \> : \> \tty{LD (reg),HL} \\
Funktion \> : \> [reg] $\leftarrow$ HL \\
Flags \> : \> keine \\
Argumente \> : \> \tty{reg} = D/DE f"ur DE (optional f"ur nicht-Z80-Syntax) \\
\end{tabbing}
\begin{tabbing}
Argumente \= : \= \kill \\
Anweisung \> : \> \tty{LHLX [reg]} \\
Z80-Syntax \> : \> \tty{LD HL,(reg)} \\
Funktion \> : \> HL $\leftarrow$[reg] \\
Flags \> : \> keine \\
Argumente \> : \> \tty{reg} = D/DE f"ur DE (optional f"ur nicht-Z80-Syntax) \\
\end{tabbing}
\begin{tabbing}
Argumente \= : \= \kill \\
Anweisung \> : \> \tty{JNX5 adr} \\
Z80-Syntax \> : \> \tty{JP NX5, adr} \\
Funktion \> : \> springe zu {\tt adr} wenn X5=0 \\
Flags \> : \> keine \\
Argumente \> : \> {\tt adr} = absolute 16-Bit-Adresse \\
\end{tabbing}
\begin{tabbing}
Argumente \= : \= \kill \\
Anweisung \> : \> \tty{JX5 adr} \\
Funktion \> : \> springe zu {\tt adr} wenn X5=1 \\
Flags \> : \> keine \\
Argumente \> : \> {\tt adr} = absolute 16-Bit-Adresse \\
\end{tabbing}
Mit X5 ist dabei das ansonsten unbenutzte Bit 5 im PSW-Register gemeint.
%%---------------------------------------------------------------------------
Eigentlich hatte ich mir geschworen, die Segmentseuche der 8086er aus diesem
Assembler herauszuhalten. Da aber nun eine Nachfrage kam und Studenten
flexiblere Menschen als die Entwickler dieses Prozessors sind, findet sich
ab sofort auch eine rudiment"are Unterst"utzung dieser Prozessoren in \asname{}.
Unter ,,rudiment"ar'' verstehe ich dabei nicht, da"s der Befehlssatz nicht
vollst"andig abgedeckt wird, sondern da"s ich nicht den ganzen Wust an
Pseudoanweisungen integriert habe, die sich bei MASM, TASM \& Co. finden.
\asname{} ist auch nicht in erster Linie geschrieben worden, um PC-Programme zu
entwickeln (Gott bewahre, das hie"se wirklich, das Rad neu zu erfinden),
sondern zur Programmentwicklung f"ur Einplatinenrechner, die eben unter
anderem auch mit 8086ern best"uckt sein k"onnen.
F"ur Unentwegte, die mit \asname{} doch DOS-Programme schreiben wollen, eine kleine
Liste dessen, was zu beachten ist:
\begin{itemize}
\item{Es k"onnen nur COM-Programme erzeugt werden.}
\item{Verwenden Sie nur das \tty{CODE}-Segment, und legen Sie auch alle
Variablen darin ab.}
\item{Alle Segmentregister werden von DOS auf das Codesegment
vorinitialisiert. Ein \tty{ASSUME DS:CODE, SS:CODE} am
Programmanfang ist daher notwendig.}
\item{DOS l"adt den Code ab Adresse 100h. Ein \tty{ORG} auf diese
Adresse ist daher zwingend.}
\item{Die Umwandlung in eine Bin"ardatei erfolgt mit P2BIN (s.u.), wobei als
als Adre"sbereich \tty{\$-\$} anzugeben ist.}
\end{itemize}
Allgemein unterst"utzt \asname{} f"ur diese Prozessoren nur ein Small-Programmiermodell, d.h.
\ii{ein} Codesegment mit maximal 64 KByte und ein ebenfalls h"ochstens 64
KByte gro"ses Datensegment mit (f"ur COM-Dateien uninitialisierten) Daten.
Zwischen diesen beiden Segmenten kann mit dem \tty{SEGMENT}-Befehl hin-und hergeschaltet werden.
Aus dieser Tatsache folgert, da"s Spr"unge immer intrasegment"ar sind,
sofern sie sich auf Adressen im Codesegment beziehen. Falls weite Spr"unge
doch einmal erforderlich sein sollten, k"onnen sie mit \tty{CALLF} und
\tty{JMPF} und einer Speicheradresse oder einen Segment:Offset-Wert als
Argument erreicht werden.
Ein weiteres gro"ses Problem dieser Prozessoren ist deren Assemblersyntax,
deren genaue Bedeutung nur aus dem Zusammenhang erkennbar ist. So kann im
folgenden Beispiel je nach Symboltyp sowohl unmittelbare als auch absolute
Adressierung gemeint sein:
\begin{verbatim}
mov ax,wert
\end{verbatim}
Bei \asname{} ist immer unmittelbare Adressierung gemeint, wenn um den Operanden
keine eckigen Klammern stehen. Soll z.B. die Adresse oder der Inhalt einer
Variablen geladen werden, so ergeben sich die in Tabelle \ref{TabMASM}
aufgelisteten Unterschiede.
\begin{table*}
\begin{center}\begin{tabular}{|l|l|l|}
Assembler & Adresse & Inhalt \\
MASM & \tty{mov ax,offset vari} & \tty{mov ax,vari} \\
& \tty{lea ax,vari} & \tty{mov ax,[vari]} \\
& \tty{lea ax,[vari]} & \\
& & \\
\asname{} & \tty{mov ax,vari} & \tty{mov ax,[vari]} \\
& \tty{lea ax,[vari]} & \\
& & \\
\end{tabular}\end{center}
\caption{Unterschiede in der Adressierungssyntax \asname{}$\leftrightarrow$MASM\label{TabMASM}}
\normalsize
\end{table*}
Der Assembler pr"uft bei Symbolen, ob sie im Datensegment liegen und
versucht, automatisch einen passenden Segmentpr"afix einzuf"ugen, z.B.
falls ohne CS-Pr"afix auf Symbole im Code zugegriffen wird. Dieser
Mechanismus kann jedoch nur funktionieren, falls der \tty{ASSUME}-Befehl
(siehe dort) korrekt angewendet wurde.
Die Intel-Syntax verlangt eine Abspeicherung, ob an einem Symbol Bytes oder
W"orter abgelegt wurden. \asname{} nimmt diese Typisierung nur vor, falls in der
gleichen Zeile wie das Label ein \tty{DB} oder \tty{DW} steht. F"ur alle anderen F"alle
mu"s mit den Operatoren \tty{WORD PTR, BYTE PTR} usw. explizit angegeben werden,
um was f"ur eine Operandengr"o"se es sich handelt. Solange ein Register an der
Operation beteiligt ist, kann auf diese Kennzeichnung verzichtet werden, da
durch den Registernamen die Operandengr"o"se eindeutig bestimmt ist.
Der Koprozessor in 8086-Systemen wird "ublicherweise durch den TEST-Eingang
des Prozessors synchronisiert, indem selbiger mit dem BUSY-Ausgang des
Koprozessors verbunden wird. \asname{} unterst"utzt dieses Handshaking, indem
vor jedem 8087-Befehl automatisch ein \tty{WAIT}-Befehl eingef"ugt wird. Ist
dies aus irgendwelchen Gr"unden unerw"unscht (z.B. w"ahrend der
Initialisierung), so mu"s im Opcode hinter dem \tty{F} ein \tty{N} eingef"ugt
werden; aus
\begin{verbatim}
FINIT
FSTSW [vari]
\end{verbatim}
wird so z.B.
\begin{verbatim}
FNINIT
FNSTSW [vari]
\end{verbatim}
Diese Variante ist bei \ii{allen} Koprozessorbefehlen erlaubt.
%%---------------------------------------------------------------------------
Die Prozessoren dieser Reihe sind auf eine einfache Manipulation von
Bitgruppen auf Peripherieadressen optimiert worden. Um mit solchen
Bitgruppen auch symbolisch umgehen zu k"onnen, existieren die Befehle
\tty{LIV} und \tty{RIV}, mit denen einer solchen Bitgruppe ein
symbolischer Name zugewiesen wird. Diese Befehle arbeiten "ahnlich
wie \tty{EQU}, ben"otigen aber drei Parameter:
\begin{enumerate}
\item{die Adresse der peripheren Speicherzelle, in der sich die
Bitgruppe befindet (0..255);}
\item{die Bitnummer des ersten Bits in der Gruppe (0..7);}
\item{die L"ange der Gruppe in Bits (1..8).}
\end{enumerate}
\bb{ACHTUNG!} Der 8X30x unterst"utzt keine Bitgruppen, die "uber mehrere
Speicherstellen hinausreichen, so da"s je nach Startposition der
Wertebereich f"ur die L"ange eingeschr"ankt sein kann. \asname{} nimmt hier
\bb{keine} Pr"ufung vor, man bekommt lediglich zur Laufzeit merkw"urdige
Ergebnisse!
Im Maschinencode dr"ucken sich L"ange und Position durch ein 3-Bit-Feld
im Instruktionswort sowie ein passende Registernummer (\tty{LIVx} bzw.
\tty{RIVx}) aus. Bei der Verwendung eines symbolischen Objektes wird \asname{}
diese Felder automatisch richtig besetzen, es ist aber auch erlaubt,
die L"ange als dritten Operanden explizit anzugeben, wenn man nicht
mit symbolischen Busobjekten arbeitet. Trifft \asname{} auf eine L"angenangabe
trotz eines symbolischen Operanden, so vergleicht er beide L"angen
und gibt eine Fehlermeldung bei Ungleichheit aus (das gleiche passiert
"ubrigens auch, wenn man bei einem \tty{MOVE}-Befehl zwei symbolische
Operanden mit unterschiedlicher L"ange benutzt - die Instruktion hat
einfach nur ein L"angenfeld...).
Neben den eigentlichen Maschinenbefehlen des 8X30x implementiert \asname{}
noch "ahnlich wie das ,,Vorbild'' MCCAP einige Pseudoinstruktionen, die
als eingebaute Makros ausgef"uhrt sind:
\begin{itemize}
\item{\tty{NOP} ist eine Kurzschreibweise f"ur \tty{MOVE AUX,AUX}}
\item{\tty{HALT} ist eine Kurzschreibweise f"ur {\tt JMP \verb!*!}}
\item{\tty{XML ii} ist eine Kurzschreibweise f"ur \tty{XMIT ii,R12} (nur
8X305)}
\item{\tty{XMR ii} ist eine Kurzschreibweise f"ur \tty{XMIT ii,R13} (nur
8X305)}
\item{\tty{SEL $<$busobj$>$} ist eine Kurzschreibweise f"ur
\tty{XMIT $<$adr$>$,IVL/IVR}, f"uhrt also die notwendige Vorselektion
durch, um \tty{$<$busobj$>$} ansprechen zu k"onnen.}
\end{itemize}
Die bei MCCAP ebenfalls noch vorhandenen \tty{CALL-} und
\tty{RTN-}Instruktionen sind mangels ausreichender Dokumentation momentan
nicht implementiert. Das gleiche gilt f"ur einen Satz an
Pseudoinstruktionen zur Datenablage. Kommt Zeit, kommt Rat...
%%---------------------------------------------------------------------------
"Ahnlich wie sein Vorg"anger MCS/51, jedoch im Unterschied zu seinem
,,Konkurrenten'' MCS/251 besitzt der Philips XA einen getrennten Bitadre"sraum,
d.h. alle mit Bitbefehlen manipulierbaren Bits haben eine
bestimmte, eindimensionale Adresse, die in den Maschinenbefehlen auch
so abgelegt wird. Die naheliegende M"oglichkeit, diesen dritten
Adre"sraum (neben Code und Daten) auch so in \asname{} anzubieten, habe ich
nicht nutzen k"onnen, und zwar aus dem Grund, da"s ein Teil der Bitadressen
im Gegensatz zum MCS/51 nicht mehr eindeutig ist: Bits mit
den Adressen 256 bis 511 bezeichnen Bits der Speicherzellen 20h..3fh
aus dem aktuellen Datensegment. Dies bedeutet aber, da"s diese Adressen
je nach Situation unterschiedliche Bits ansprechen k"onnen - ein definieren
von Bits mit Hilfe von \tty{DC}-Befehlen, was durch ein extra Segment
m"oglich geworden w"are, w"urde also nicht "uberm"a"sig viel Sinn ergeben.
Zur Definition einzelner, symbolisch ansprechbarer Bits steht aber
nach wie vor der \tty{BIT}-Befehl zur Verf"ugung, mit dem beliebige Bitadressen
(Register, RAM, SFR) definiert werden k"onnen. F"ur Bitadressen im
internen RAM wird auch die 64K-Bank-Adresse gespeichert, so da"s \asname{}
Zugriffe "uberpr"ufen kann, sofern das DS-Register korrekt mit \tty{ASSUME}
vorbesetzt wurde.
Nichts drehen kann man dagegen an den Bem"uhungen von \asname{}, potentielle
Sprungziele (also Zeilen im Code mit Label) auf gerade Adressen
auszurichten. Dies macht \asname{} genauso wie andere XA-Assembler auch durch
Einf"ugen von \tty{NOP}s vor dem fraglichen Befehl.
%%---------------------------------------------------------------------------
Im Gegensatz zum AVR-Assembler verwendet \asname{} defaultm"a"sig das Intel-Format
zur Darstellung von Hexadezimalkonstanten und nicht die C-Syntax. OK, nicht
vorher in den (freien) AVR-Assembler hineingeschaut, aber als ich mit dem
AVR-Teil anfing, gab es zum AVR noch nicht wesentlich mehr als ein
vorl"aufiges Datenbuch mit Prozessortypen, die dann doch nie kamen...mit
einem \tty{RELAXED ON} schafft man dieses Problem aus der Welt.
Optional kann \asname{} f"ur die AVRs (es geht auch f"ur andere CPU's, nur
macht es dort keinen Sinn...) sogenannte ,,Objekt-Dateien'' erzeugen.
Das sind Dateien, die sowohl Code als auch Quellzeileninformationen
enthalten und z.B. eine schrittweise Abarbeitung auf Quellcodeebene
mit dem von Atmel gelieferten Simulator WAVRSIM erlauben. Leider
scheint dieser mit Quelldateispezifikationen, die l"anger als ca. 20
Zeichen sind, seine liebe Not zu haben: Namen werden abgeschnitten
oder um wirre Sonderzeichen erg"anzt, wenn die Maximall"ange "uberschritten
wird. \asname{} speichert deshalb in den Objekt-Dateien Dateinamen ohne
Pfadangabe, so da"s es eventuell Probleme geben k"onnte, wenn
Dateien (z.B. Includes) nicht im Arbeitsverzeichnis liegen.
Eine kleine Besonderheit sind Befehle, die Atmel bereits in der
Architektur vorgesehen hat, aber noch in keinem Mitglied der Familie
implementiert wurden. Dabei handelt es sich um die Befehle {\tt MUL, JMP}
und {\tt CALL}. Besonders bei letzteren fragt man sich vielleicht, wie man
denn nun den 4 KWorte gro"sen Adre"sraum des AT90S8515 erreichen kann,
wenn die 'n"achstbesten' Befehle {\tt RJMP} und {\tt RCALL} doch nur 2
KWorte weit springen kann. Der Kunstgriff lautet 'Abschneiden der oberen
Adre"sbits' und ist n"aher bei der {\tt WRAPMODE}-Anweisung beschrieben.
F"ur alle AVR-CPUs ist das CPU-Argument {\tt CODESEGSIZE} definiert.
Mit einem
\begin{verbatim}
cpu atmega8:codesegsize=0
\end{verbatim}
weist man den Assembler an, das Code-Segment (also das interne Flash-ROM)
nicht als in 16-Bit-Worten, sondern in 8-Bit-Bytes organisiert zu betrachten.
Dies ist die Sichtweise, wie man sie beim {\tt LPM}-Befehl hat und wie sie
einige andere (nicht-Atmel) Assembler grunds"atzlich verfolgen. Sie hat den
Vorteil, da"s man Adressen im {\tt CODE}-Segment f"ur Datenzugriffe nicht selber
mit zwei multiplizieren mu"s, andererseits mu"s aber darauf geachtet werden,
da"s Instruktionen niemals auf einer ungeraden Adresse liegen d"urfen - sie
w"urden dann ja quasi halb auf einem und halb auf dem n"achsten 16-Bit-Wort
im Flash-ROM liegen. {\tt PADDING} ist deshalb im Default aktiviert, es bleibt
aber m"oglich, mit {\tt DB} oder {\tt DATA} Byte-Felder zu definieren, ohne
da"s zwischen den Anweisungen Padding-Bytes eingestreut werden. Bei relativen
oder absoluten Spr"ungen werden die Adressen im ''Byte-Modus'' automatisch
durch zwei geteilt. Default ist die vom Atmel-Assembler vorgegebene Organisation
in unteilbare 16-Bit-Worte. Diese kann auch explizit mit dem Argument
\verb!codesegsize=1! gew"ahlt werden.
%%---------------------------------------------------------------------------
Da es von Zilog naturgem"a"s keine Syntaxvorgaben f"ur die undokumentierten
Befehle gibt und wohl auch nicht jeder den kompletten Satz kennt,
ist es vielleicht sinnvoll, diese Befehle hier kurz aufzuz"ahlen:
Wie auch beim Z380 ist es m"oglich, die Byte-H"alften von IX und IY
einzeln anzusprechen. Im einzelnen sind dies folgende Varianten:
\begin{verbatim}
INC Rx LD R,Rx LD Rx,n
DEC Rx LD Rx,R LD Rx,Ry
ADD/ADC/SUB/SBC/AND/XOR/OR/CP A,Rx
\end{verbatim}
Dabei stehen \tty{Rx} bzw. \tty{Ry} f"ur \tty{IXL, IXU, IYL} oder
\tty{IYU}. Zu beachten ist jedoch, da"s in der \tty{LD Rx,Ry}-Variante
beide Register aus dem gleichen Indexregister stammen m"ussen.
Die Kodierung von Schiebebefehlen besitzt noch eine undefinierte
Bitkombination, die als \tty{SL1}-, \tty{SLI}-, \tty{SLIA}- oder
\tty{SLS}-Befehl zug"anglich ist. Er funktioniert wie \tty{SLA},
es wird jedoch eine Eins und nicht eine Null in Bit 0 eingeschoben.
\bb{ACHTUNG}: In Internet findet man f"ur diesen Befehl auch den
Namen \tty{SLL}, ich habe mich aber entschieden, dies nicht zu
implementieren. \tty{SLL} steht f"ur ,,Shift Logically Left'' und
die von diesem Befehl ausgef"uhrte Operation ist kein logischer
Linksshift - wenn \tty{SLL} "uberhaupt definiert werden sollte, dann
als Alias zu \tty{SLA}. Wer f"ur existierenden Code \tty{SLL} mit
der Funktion von \tty{SL1/SLI} braucht, definiere sich daf"ur ein
Makro.
Dieser undokumentierte Schiebebefehl kann, wie alle anderen
Schiebebefehle auch, noch in zwei weiteren Varianten benutzt
werden:
\begin{verbatim}
SLIA R,(XY+d)
SLIA (XY+d),R
\end{verbatim}
Dabei steht \tty{R} f"ur ein beliebiges 8-Bit-Register (aber nicht eine
Indexregisterh"alfte...), und \tty{(XY+d)} f"ur eine normale
indexregister-relative Adressierung. Das Ergebnis dieser Operation
ist, da"s das Schiebeergebnis zus"atzlich ins Register geladen wird.
Dies funktioniert auch bei den \tty{RES-} und \tty{SET-}Befehlen:
\begin{verbatim}
SET/RES R,n,(XY+d)
SET/RES n,(XY+d),R
\end{verbatim}
Des weiteren gibt es noch zwei versteckte I/O-Befehle:
\begin{verbatim}
IN (C) bzw. TSTI
OUT (C),0
\end{verbatim}
Deren Funktionsweise sollte klar sein. \bb{ACHTUNG!} Es gibt keine
Garantie daf"ur, da"s alle Z80-Masken alle diese Befehle beherrschen,
und die Z80-Nachfolger l"osen zuverl"assig Traps aus. Anwendung
daher auf eigene Gefahr...
%%---------------------------------------------------------------------------
Das im originalen Gameboy verbaute SoC namens LR35092 wurde von Sharp
entwickelt, und der darin verbaute Prozessorkern ist (vermutlich) der gleiche
wie in den SM83-Mikrokontrollern. Dieser ist vom Befehlssatz auf dem
,,halben Weg'' zwischen 8080 und Z80, allerdings auch mit seinen
eigenen Auslassungen und Erweiterungen. F"ur die neuen Befehle hat
Sharp nat"urlich eine Assembler-Syntax definiert, in der
,,Gameboy-Szene'' haben sich aber auch einige alternative
Schreibweisen eingeb"urgert. Ich habe mich bem"uht, diese (so weit
bekannt) zu ber"ucksichtigen:
\begin{center}\begin{tabular}{|l|l|l|}
Sharp & alternativ & Funktion \\
LD A,(HLD) & LD A,(HL-) & A $\longleftarrow$ (HL), \\
& LDD A,(HL) & HL $\longleftarrow$ HL-1 \\
LD A,(HLI) & LD A,(HL+) & A $\longleftarrow$ (HL), \\
& LDI A,(HL) & HL $\longleftarrow$ HL+1 \\
LD (HLD),A & LD (HL-),A & (HL) $\longleftarrow$ A, \\
& LDD (HL),A & HL $\longleftarrow$ HL-1 \\
LD (HLI),A & LD (HL+),A & (HL) $\longleftarrow$ A, \\
& LDI (HL),A & HL $\longleftarrow$ HL+1 \\
LD A,(C) & LD A,(FF00+C) & A $\longleftarrow$ (0ff00h+C) \\
& LDH A,(C) & \\
LD (C),A & LD (FF00+C),A & (0ff00h+C) $\longleftarrow$ A \\
& LDH (C),A & \\
LD (FF00+n),A & LDH (n),A & (0ff00h+n) $\longleftarrow$ A \\
LD A,(FF00+n) & LDH A,(n) & A $\longleftarrow$ (0ff00h+n) \\
LDHL SP,d & LD HL,SP+d & HL $\longleftarrow$ SP + d \\
LDX A,(nn) & LD A,(nn) & A $\longleftarrow$ (nn) $^{1}$ \\
LDX (nn),A & LD (nn),A & (nn) $\longleftarrow$ A $^{1}$ \\
\multicolumn{3}{|l|}{$^{1}$ erzwingt 16-Bit-Adressierung. } \\
\end{tabular}\end{center}
%%---------------------------------------------------------------------------
Da dieser Prozessor als Enkel des wohl immer noch beliebtesten
8-Bit-Prozessors konzipiert wurde, war es bei der Entwicklung
unabdingbar, da"s dieser bestehende Z80-Programme ohne "Anderung
ausf"uhren kann (nat"urlich geringf"ugig schneller, etwa um den
Faktor 10...). Die erweiterten F"ahigkeiten k"onnen daher nach
einem Reset mit zwei Flags zugeschaltet werden, die XM (eXtended
Mode, d.h. 32- statt 16-Bit-Adre"sraum) und LW (long word mode,
d.h. 32- statt 16- Bit-Operanden) hei"sen. Deren Stand mu"s man
\asname{} "uber die Befehle \tty{EXTMODE} und \tty{LWORDMODE} mitteilen, damit
Adressen und Konstantenwerte gegen die korrekten Obergrenzen
gepr"uft werden. Die Umschaltung zwischen 32- und 16-Bit-Befehlen
bewirkt nat"urlich nur bei solchen Befehlen etwas, die auch in
einer 32-Bit-Version existieren; beim Z380 sind das momentan
leider nur Lade- und Speicherbefehle, die ganze Arithmetik kann
nur 16-bittig ausgef"uhrt werden. Hier sollte Zilog wohl noch
einmal etwas nachbessern, sonst kann man den Z380 selbst beim
besten Willen nur als ,,16-Bit-Prozessor mit 32-Bit-Erweiterungen''
bezeichnen...
Kompliziert wird die Sache dadurch, da"s die mit LW eingestellte
Operandengr"o"se f"ur einzelne Befehle mit den Pr"afixen \tty{DDIR W}
und \tty{DDIR LW} "ubersteuert werden kann. \asname{} merkt sich das
Auftreten solcher Befehle und schaltet dann f"ur den n"achsten
Prozessorbefehl automatisch mit um. Andere \tty{DDIR}-Varianten
als \tty{W} und \tty{LW} sollte man "ubrigens nie explizit
verwenden, da \asname{} bei zu langen Operanden diese automatisch
einsetzt, und das k"onnte zu Verwirrungen f"uhren. Die Automatik
geht "ubrigens so weit, da"s in der Befehlsfolge
\begin{verbatim}
DDIR LW
LD BC,12345678h
\end{verbatim}
automatisch der erforderliche \tty{IW}-Pr"afix mit in die
vorangehende Anweisung hineingezogen wird, effektiv wird also
der Code
\begin{verbatim}
DDIR LW,IW
LD BC,12345678h
\end{verbatim}
erzeugt. Der im ersten Schritt erzeugte Code f"ur \tty{DDIR LW}
wird verworfen, was an einem \tty{R} im Listing zu erkennen
ist.
%%---------------------------------------------------------------------------
Der Prozessorkern der Z8-Mikrokontroller beinhaltet keine eigenen
Register. Stattdessen kann ein 16er-Block des internen Adre"sraums
aus RAM und I/O-Registern als 'Arbeitsregister' benutzt werden, die
mit 4-Bit-Adressen angesprochen werden k"onnen. Welcher 16er-Block
als Arbeitsregister benutzt werden soll, wird mit den RP-Registern
festgelegt: Bits 4 bis 7 von RP definieren beim klassischen Z8 den
'Offset', der auf die 4-Bit-Arbeitsregisteradresse addiert wird,
um eine 8-Bit-Adresse zu erhalten. Beim Super8-Kern existieren
zwei RP-Register (RP0 und RP1), die es erlauben, obere und untere
H"alfte der Arbeitsregister an getrennte Stellen zu legen.
"Ublicherweise werden die Arbeitsregister in der Assemblersyntax als
Register R0...R15 angesprochen, man kann diese Arbeitsregister aber
auch als eine Methode zur effizienteren (k"urzeren) Adressierung eines
16er-Bocks im internen RAM betrachten.
Mit dem \tty{ASSUME}-Befehl teilt man \asname{} den aktuellen Wert von RP mit. \asname{}
ist dann in der Lage, bei einer Adresse aus dem internen RAM
automatisch zu entscheiden, ob dieser Operand mit einer 4-Bit Adresse
angesprochen werden kann oder eine 8-Bit-Adresse verwendet werden
mu"s. Man kann diese Funktion auch dazu benutzen, Arbeitsregistern
symbolische Namen zu verpassen:
\begin{verbatim}
op1 equ 040h
op2 equ 041h
srp #040h
assume rp:040h
ld op1,op2 ; entspricht ld r0,r1
\end{verbatim}
Es ist auch auf dem Super8 m"oglich, RP als Argument von \tty{ASSUME}
anzugeben, obwohl dieser kein RP-Register hat (nur RP0 und RP1). In
diesem Fall werden die angenommen Werte von RP0 und RP1 auf $wert$ bzw.
$wert+8$ gesetzt, analog zum \tty{SRP} Maschinenbefehl auf dem Super8-
Kern.
Im Gegensatz zum Original Zilog-Assembler ist es nicht erforderlich,
eine 'Arbeitsregisteradressierung' explizit durch ein vorangestelltes
Ausrufezeichen anzufordern, wobei \asname{} diese Syntax nichtsdestotrotz
versteht - ein vorangestelltes Ausrufezeichen erzwingt quasi
4-Bit-Adressierung, auch wenn die Adresse eigentlich nicht im durch
RP festgelegten 16-Bit-Fenster liegt (dann wird eine Warnung
ausgegeben). Umgekehrt ist es durch ein vorangestelltes $>$-Zeichen
m"oglich, eine Adressierung mit 8 Bit zu erzwingen, auch wenn die
Adresse eigentlich im aktuellen 16er-Fenster liegt.
Beim eZ8 wird das Spielchen quasi eine Stufe weiter getrieben: der
interne Daten-Adre"sbereich ist jetzt 12 statt 8 Bit gro"s. Um
kompatibel zum alten Z8-Kern zu sein, hat Zilog die zus"atzlichen
Banking-Bits in den {\em unteren} vier Bits von RP untergebracht -
ein RP-Wert von 12h definiert also das 16er-Adre"sfenster von 210h
bis 21fh.
Die unteren vier Bits von RP definieren beim eZ8 gleichzeitig das
256er-Fenster, das man mit 8-Bit-Adressen erreichen kann - hier gilt
ein analoger Mechanismus, der daf"ur sorgt, da"s \asname{} automatisch 12-
oder 8-Bit-Adressen verwendet. 'Lange' 12-Bit-Adressen kann man mit
zwei vorangestellten $>$-Zeichen erzwingen.
%%---------------------------------------------------------------------------
Der Z8001/8003 kann in zwei verschiedenen Modi betrieben werden:
\begin{itemize}
\item{{\em Nicht segmentiert}: Der Speicheradre"sraum ist auf 64 KByte
beschr"ankt, alle Adressen sind 'einfache' lineare 16-Bit-
Adressen. Adre"sregister sind einfache 16-Bit-Register (Rn),
und absolute Adressen in Befehlen sind ein 16-Bit-Wort lang.}
\item{{\em Segmentiert}: Der Speicher ist in bis zu 128 Segmente von
jeweils maximal 64 KByte aufgeteilt. Adressen bestehen aus
einem 7-bittigen Segment und einem 16-bittigen Offset. Adre"sregister
sind immer Registerpaare (RRn). Absolute Adressen in Befehlen
sind zwei 16-Bit-Worte lang, au"ser der Offset is kleiner 256.}
\end{itemize}
Die Betriebsart (segmentiert oder nicht segmentiert) hat also einen
Einflu"s auf den erzeugten Code und wird implizit "uber den verwendeten
Prozessortyp umgeschaltet. Ist das Ziel also z.B. ein Z8001 im nicht
segmentierten Modus, so w"ahlt man einfach Z8002 als Ziel.
Eine 'echte' Unterst"utzung eines segmentierten Speichermodells bietet
\asname{} indes f"ur den Z8000 genauso wenig wie f"ur den 8086. Im segmentierten
Modus wird die Segmentnummer einfach als die oberen sieben Adre"sbits
eines gedacht linearen 8MB-Adre"sraums behandelt. Dies ist eigentlich
nicht im Sinne des Erfinders, aber es entspricht der Art und Weise, wie
der Z8001 in Systemen ohne MMU effektiv betrieben wurde.
Generell implementiert \asname{} die Assembler-Syntax der Z8000-Maschinenbefehle
so, wie es von Zilog in der Dokumentation vorgesehen ist. Es existieren
jedoch Assembler, die Erweiterungen bzw. Variationen unterst"utzen. \asname{}
implementiert davon folgendes:
Zus"atzlich zu den von Zilog definierten Bedingungen sind folgende alternative
Namen definiert:
\begin{center}\begin{tabular}{|l|l|l|}
Alternativ & Zilog & Bedeutung \\
ZR & Z & Z = 1 \\
CY & C & C = 1 \\
LLE & ULE & (C OR Z) = 1 \\
LGE & UGE & C = 0 \\
LGT & UGT & ((C = 0) AND (Z = 0)) = 1 \\
LLT & ULT & C = 1 \\
\end{tabular}\end{center}
Als Argument f"ur die Befehle \tty{SETFLG}, \tty{COMFLG} und \tty{RESFLG} werden
auch die folgenden alternativen Namen akzeptiert:
\begin{center}\begin{tabular}{|l|l|l|}
Alternativ & Zilog & Bedeutung \\
ZR & Z & Zero-Flag \\
CY & C & Carry-Flag \\
\end{tabular}\end{center}
Anstelle \verb!@Rn! darf auch \verb!Rn^! geschrieben werden, falls beim \tty{CPU}-
Statement die Option \tty{AMDSyntax=1} gesetzt wurde. Wird eine I/O-Adresse
indirekt adressiert, so reicht es mit dieser Option auch aus, {\em nur} \verb!Rn!
zu schreiben.
\subsection{Direkte versus unmittelbare Adressierung}
Bei der von Zilog vorgegebenen Assembler-Syntax mu"s unmittelbare Adressierung
durch ein vorangestelltes Doppelkreuz kenntlich gemacht werden. Wurde dem
\tty{CPU}-Statement jedoch die Option \tty{AMDSyntax=1} mitgegeben, wird anhand
des Arguments (Label oder Konstante) entschieden, ob direkte oder unmittelbare
Adressierung verwendet werden soll. Unmittelbare Adressierung kann erzwungen
werden, indem dem Argument ein Circumflex vorangestellt wird, z.B. um die
Adresse eines Labels in ein Register zu laden.
%%---------------------------------------------------------------------------
Diese Prozessoren k"onnen in zwei Betriebsarten laufen, einmal im
\ii{Minimum}-Modus, der weitgehende Z80- und TLCS-90-Quellcodekompatibilit"at
bietet, und zum anderen im \ii{Maximum}-Modus, in dem der Prozessor
erst seine wahren Qualit"aten entfaltet. Die Hauptunterschiede zwischen
den beiden Betriebsarten sind:
\begin{itemize}
\item{Breite der Register WA,BC,DE und HL: 16 oder 32 Bit;}
\item{Anzahl der Registerbanks: 8 oder 4;}
\item{Programmadre"sraum: 64 Kbyte oder 16 Mbyte;}
\item{Breite von R"ucksprungadressen: 16 oder 32 Bit.}
\end{itemize}
Damit \asname{} gegen die richtigen Grenzen pr"ufen kann, mu"s man ihm zu Anfang
mit dem Befehl \tty{MAXMODE} (siehe dort) mitteilen, in welcher Betriebsart
der Code ausgef"uhrt werden wird; Voreinstellung ist der Minimum-Modus.
Je nach Betriebsart m"ussen demzufolge auch die 16- oder 32-Bit-Versionen
der Bankregister zur Adressierung verwendet werden, d.h. WA, BC, DE und HL
im Minimum-Modus sowie XWA, XBC, XDE und XHL im Maximum-Modus. Die Register
XIX..XIZ und XSP sind \bb{immer} 32 Bit breit und m"ussen zur Adressierung
auch immer in dieser Form verwendet werden; hier mu"s bestehender Z80-Code
also auf jeden Fall angepa"st werden (neben der Tatsache, da"s es gar keinen
I/O-Adre"sraum mehr gibt und alle I/O-Register memory-mapped sind...).
Absolute Adressen sowie Displacements k"onnen in unterschiedlichen L"angen
kodiert werden. \asname{} wird ohne explizite Angaben immer versuchen, die
k"urzestm"ogliche Schreibweise zu verwenden; dies schlie"st ein, da"s ein
Displacement von Null "uberhaupt nicht im Code erscheint und aus einen
\verb!(XIX+0)! einfach ein \verb!(XIX)! wird. Ist eine bestimmte L"ange
erw"unscht, so kann sie durch Anh"angen eines passenden Suffixes (:8, :16,
:24) an das Displacement bzw. die Adresse erreicht werden.
Die von Toshiba gew"ahlte Syntax f"ur Registernamen ist in der Hinsicht
etwas ungl"ucklich, als da"s zur Anwahl der vorherigen Registerbank ein
Hochkomma (') benutzt wird.
Dieses Zeichen wird von den prozessorunabh"angigen Teilen von \asname{} bereits zur
Kennzeichnung von Zeichenkonstanten benutzt. Im Befehl
\begin{verbatim}
ld wa',wa
\end{verbatim}
erkennt \asname{} z.B. nicht das Komma zur Parametertrennung.
Dieses Problem kann man aber umgehen,
indem man ein umgekehrtes Hochkomma (`) verwendet, z.B.
\begin{verbatim}
ld wa`,wa
\end{verbatim}
Toshiba liefert f"ur die TLCS-900-Reihe selber einen Assembler (TAS900), der
sich in einigen Punkten von \asname{} unterscheidet:
\begin{itemize}
\item{TAS900 unterscheidet Symbolnamen nur auf den ersten 32 Zeichen.
\asname{} dagegen speichert Symbolnamen immer in der vollen L"ange (bis
255 Zeichen) und unterscheidet auch auf dieser L"ange.}
\item{Unter TAS900 k"onnen Integerkonstanten sowohl in C-Notation (mit
vorangestellter 0 f"ur oktal bzw. 0x f"ur hexadezimal) als auch in
normaler Intel-Notation geschrieben werden. \asname{} unterst"utzt in der
Default-Einstellung \bb{nur} die Intel-Notation. Mit dem
\tty{RELAXED}-Befehl bekommt man (unter anderem) auch die C-Notation.}
\item{\asname{} macht keinen Unterschied zwischen Gro"s- und Kleinschreibung,
TAS900 hingegen unterscheidet Gro"s-und Kleinbuchstaben in
Symbolnamen. Dieses Verhalten erh"alt man bei \asname{} erst, wenn man
die \tty{-u}-Kommandozeilenoption benutzt.}
\end{itemize}
\asname{} ist bei vielen Befehlen in der Syntaxpr"ufung weniger streng als TAS900,
bei einigen weicht er (sehr) geringf"ugig ab. Diese Erweiterungen bzw.
"Anderungen dienen teilweise der leichteren Portierung von bestehendem
Z80-Code, teilweise einer Schreiberleichterung und teilweise einer besseren
Orthogonalit"at der Assemblersyntax:
\begin{itemize}
\item{Bei den Befehlen \tty{LDA, JP} und \tty{CALL} verlangt TAS, da"s
Adre"sausdr"ucke wie \tty{XIX+5} nicht geklammert sein d"urfen, wie
es sonst "ublich ist. \asname{} verlangt im Sinne der Orthogonalit"at f"ur
\tty{LDA} dagegen immer eine Klammerung, bei \tty{JP} und \tty{CALL}
ist sie dagegen f"ur einfache, absolute Adressen optional.}
\item{Bei den bedingten Befehlen \tty{JP, CALL, JR} und \tty{SCC} stellt
\asname{} es dem Programmierer frei, die Default-Bedingung \tty{T} (= true) als
ersten Parameter anzugeben oder nicht. TAS900 hingegen erlaubt es
nur, die Default-Bedingung implizit zu benutzen (also z.B.
\tty{jp (xix+5)} anstelle von \tty{jp t,(xix+5)}).}
\item{\asname{} erlaubt beim \tty{EX}-Befehl auch Operandenkombinationen, die
zwar nicht direkt im User's Manual\cite{Tosh900} genannt werden,
aber durch Vertauschung auf eine genannte zur"uck gef"uhrt werden
k"onnen. Kombinationen wie \tty{EX f`,f} oder \tty{EX wa,(xhl)}
werden damit m"oglich. TAS900 hingegen l"a"st nur die ,,reine Lehre''
zu.}
\item{\asname{} erlaubt, bei den Befehlen \tty{INC} und \tty{DEC} die Angabe
des Inkrements oder Dekrements wegzulassen, wenn dies 1 ist. Unter
TAS900 dagegen mu"s auch eine 1 hingeschrieben werden.}
\item{"Ahnlich verh"alt es sich bei allen Schiebebefehlen: Ist der zu
verschiebende Operand ein Register, so verlangt TAS900, da"s auch
eine Schiebeamplitude von 1 ausgeschrieben werden mu"s; ist dagegen
eine Speicherstelle der Operand, so ist die Schiebezahl
(hardwarebedingt) immer 1 und darf auch nicht hingeschrieben werden.
Unter \asname{} dagegen ist die Schiebezahl 1 immer optional und auch f"ur
alle Operandentypen zul"assig.}
\end{itemize}
Der Makroprozessor wird TAS900 als externes Programm vorgeschaltet und
besteht aus zwei Komponenten: einem C-artigen Pr"aprozessor und einer
speziellen Makrosprache (MPL), die an h"ohere Programmiersprachen
erinnert. Der Makroprozessor von \asname{} dagegen orientiert sich an
,,klassischen'' Makroassemblern wie dem M80 oder MASM (beides Programme
von Microsoft). Er ist fester Bestandteil des Programms.
TAS900 erzeugt relokatiblen Code, so da"s sich mehrere, getrennt assemblierte
Teile zu einem Programm zusammenbinden lassen. \asname{} hingegen erzeugt direkt
absoluten Maschinencode, der nicht linkbar ist. An eine Erweiterung ist
(vorl"aufig) nicht gedacht.
Bedingt durch den fehlenden Linker fehlen in \asname{} eine ganze Reihe von f"ur
relokatiblen Code erforderlichen Pseudoanweisungen, die TAS900 implementiert.
In gleicher Weise wie bei TAS900 sind folgende Anweisungen vorhanden:
\begin{quote}{\tt
EQU, DB, DW, ORG, ALIGN, END, TITLE, SAVE, RESTORE,
}\end{quote}
wobei die beiden letzteren einen erweiterten Funktionsumfang haben.
Einige weitere TAS900-Pseudobefehle lassen sich durch "aquivalente \asname{}-Befehle
ersetzen (siehe Tabelle \ref{TabTAS900}).
Von Toshiba existieren zwei Versionen des Prozessorkerns, wobei die
L-Variante eine ,,Sparversion'' darstellt. Zwischen TLCS-900 und TLCS-900L
macht \asname{} folgende Unterschiede:
\begin{itemize}
\item{Die Befehle \tty{MAX} und \tty{NORMAL} sind f"ur die L-Version
nicht erlaubt, der \tty{MIN}-Befehl ist f"ur die Vollversion
gesperrt.}
\item{Die L-Version kennt den Normal-Stapelzeiger \tty{XNSP/NSP} nicht,
daf"ur das Steuerregister \tty{INTNEST}.}
\end{itemize}
Die Befehle \tty{SUPMODE} und \tty{MAXMODE} werden nicht beeinflu"st,
ebenso nicht deren ini\-tiale Einstellung OFF. Die Tatsache, da"s die
L-Version im Maximum-Modus startet und keinen Normal-Modus kennt, mu"s
also vom Programmierer ber"ucksichtigt werden. \asname{} zeigt sich jedoch
insofern kulant gegen"uber der L-Variante, als da"s Warnungen wegen
privilegierter Anweisungen im L-Modus unterdr"uckt werden.
\begin{table*}[htbp]
\begin{center}\begin{tabular}{|l|l|l|}
TAS900 & \asname{} & Bedeutung/Funktion \\
\tty{DL} $<Daten>$ & \tty{DD} $<Daten>$ & Speicher in Langworten belegen \\
\tty{DSB} $<Zahl>$ & \tty{DB} $<Zahl>$ \tty{DUP} (?) & Speicher byteweise reservieren \\
\tty{DSW} $<Zahl>$ & \tty{DW} $<Zahl>$ \tty{DUP} (?) & Speicher wortweise reservieren \\
\tty{DSD} $<Zahl>$ & \tty{DD} $<Zahl>$ \tty{DUP} (?) & Speicher langwortweise reservieren \\
\tty{\$MIN[IMUM]} & \tty{MAXMODE OFF} & folgender Code im Minimum-Modus \\
\tty{\$MAX[IMUM]} & \tty{MAXMODE ON} & folgender Code im Maximum-Modus \\
\tty{\$SYS[TEM]} & \tty{SUPMODE ON} & folgender Code im System-Modus \\
\tty{\$NOR[MAL]} & \tty{SUPMODE OFF} & folgender Code im User-Modus \\
\tty{\$NOLIST} & \tty{LISTING OFF} & Assemblerlisting ausschalten \\
\tty{\$LIST} & \tty{LISTING ON} & Assemblerlisting einschalten \\
\tty{\$EJECT} & \tty{NEWPAGE} & neue Seite im Listing beginnen \\
\end{tabular}\end{center}
\caption{"aquivalente Befehle TAS900$\leftrightarrow$\asname{}\label{TabTAS900}}
\end{table*}
%%---------------------------------------------------------------------------
Vielleicht fragt sich der eine oder andere, ob bei mir die Reihenfolge
durcheinander gekommen ist, es gab ja von Toshiba zuerst den 90er als
,,aufgebohrten Z80'' und danach den 900er als 16-Bit-Version. Nun, ich
bin einfach "uber den 900er zum 90er gekommen (Danke, Oliver!). Die
beiden Familien sind sich sehr artverwandt, nicht nur was ihre Syntax
angeht, sondern auch ihre Architektur. Die Hinweise f"ur den 90er sind
daher eine Untermenge derer f"ur den 900er: Da Schieben, Inkrementieren
und Dekrementieren hier nur um eins m"oglich sind, braucht und darf diese
Eins auch nicht als erstes Argument hingeschrieben werden. Bei den
Befehlen \tty{LDA, JP} und \tty{CALL} m"ochte Toshiba wieder die
Klammern um Speicheroperanden weglassen, bei \asname{} m"ussen sie aber aus
Gr"unden der Orthogonalit"at gesetzt werden (der tiefere Grund ist
nat"urlich, da"s ich mir damit eine Sonderabfrage im Parser gespart habe,
aber das sagt man nicht so laut).
Die TLCS-90er besitzen bereits prinzipiell einen Adre"sraum von 1
Mbyte, dieser Raum erschlie"st sich aber nur bei Datenzugriffen "uber
die Indexregister. \asname{} verzichtet daher auf eine Ber"ucksichtigung
der Bankregister und begrenzt den Adre"sraum f"ur Code auf 64 Kbyte.
Da der Bereich jenseits aber sowieso nur "uber indirekte Adressierung
erreichbar ist, sollte dies keine allzu gro"se Einschr"ankung darstellen.
%%---------------------------------------------------------------------------
Schon wieder Toshiba...diese Firma ist im Augenblick wirklich sehr
produktiv! Speziell dieser Spro"s der Familie (Toshibas Mikrokontroller
sind sich ja alle in Bin"arkodierung und Programmiermodell recht "ahnlich)
scheint auf den 8051-Markt abzuzielen: Die Methode, Bitstellen durch einen
Punkt getrennt an den Adre"sausdruck anzuh"angen, hatte ja beim 8051 ihren
Ursprung, f"uhrt jetzt aber auch genau zu den Problemen, die ich beim 8051
geahnt hatte: Der Punkt ist jetzt einerseits legales Zeichen in Symbolnamen,
andererseits aber auch Teil der Adre"ssyntax, d.h. \asname{} mu"s Adresse und
Bitstelle trennen und einzeln weiterverarbeiten. Diesen Interessenkonflikt
habe ich vorerst so gel"ost, da"s der Ausdruck von \bb{hinten} an nach
Punkten durchsucht wird und so der letzte Punkt als Trenner gilt, eventuelle
weitere Punkte werden dem Symbolnamen zugerechnet. Es gilt weiterhin die
flehentliche Bitte, im eigenen Interesse auf Punkte in Symbolnamen zu
verzichten, sie f"uhren nur zu Verwirrungen:
\begin{verbatim}
LD CF,A.7 ; Akku Bit 7 nach Carry
LD C,A.7 ; Konstante A.7 nach Register C
\end{verbatim}
%%---------------------------------------------------------------------------
Mit dieser 4-Bit-Prozessorfamilie d"urfte wohl das unter Ende dessen
erreicht sein, was \asname{} unterst"utzen kann. Neben dem \tty{ASSUME}-Befehl
f"ur das Datenbankregister (siehe dort) ist eigentlich nur ein Detail
erw"ahnenswert: im Daten- und I/O-Segment werden keine Bytes, sondern
Nibbles reserviert (eben 4-Bitter...). Die Sache funktioniert "ahnlich
wie das Bitdatensegment beim 8051, wo ein \tty{DB} ja nur einzelne Bit
reserviert, nur da"s es hier eben Nibbles sind.
Toshiba hat f"ur diese Prozessorfamilie einen ,,erweiterten Befehlssatz''
in Makroform definiert, um das Arbeiten mit diesem doch recht
beschr"ankten Befehlssatz zu erleichtern. Im Fall von \asname{} ist er in der
Datei STDDEF47.INC definiert. Einige Befehle, deren makrom"a"sige
Realisierung nicht m"oglich war, sind allerdings ,,eingebaut'' und stehen
daher auch ohne die Include-Datei zur Verf"ugung:
\begin{itemize}
\item{der \tty{B}-Befehl, der die jeweils optimale Version des
Sprungbefehls (\tty{BSS, BS oder BSL}) automatisch w"ahlt;}
\item{\tty{LD} in der Variante HL mit immediate;}
\item{\tty{ROLC} und \tty{RORC} mit einer Schiebeamplitude $>$1.}
\end{itemize}
%%---------------------------------------------------------------------------
Hier ist es zum ersten Mal passiert, da"s ich einen Prozessor in \asname{}
implementiert habe, der zu diesem Zeitpunkt noch gar nicht auf dem
Markt war. Toshiba hatte sich nach meinen Informationen leider
zwischenzeitlich auch dazu entschieden, diesen Prozessor ,,auf Eis''
zu legen, also auch kein Silizium geben. Das hatte nat"urlich zur Folge,
da"s dieser Teil
\begin{description}
\item[1.]{ein ,,Paper-Design'' ist, d.h. noch nicht praktisch getestet
wurde und}
\item[2.]{Die Unterlagen, die ich zum 9000er hatte \cite{Tosh9000},
noch vorl"aufig waren, also noch nicht bis ins letzte Klarheit
lieferten.}
\end{description}
und dieses Target foratn in einen Dornr"oschenschlaf fiel...
...Schnitt, 20 Jahre sp"ater: auf einmal melden sich Leute bei
mir, da"s Toshiba wohl doch TLCS-9000-Chips an Kunden verkauft
hat, und fragen nach den Unterlagen, weil sie Reverse-Engineering
betreiben. Vielleicht bekommen wir ja auf diesem Wege noch das
eine oder andere unklare Detail best"atigt oder gekl"art. Fehler in
diesem Teil sind also weiterhin noch m"oglich und werden nat"urlich
bereinigt. Zumindest die Handvoll Beispiele in \cite{Tosh9000} werden
aber richtig "ubersetzt.
Displacements im Maschinenbefehl selber k"onnen nur eine bestimmte
maximale L"ange (z.B. 13 oder 9 Bit) haben. Ist das Displacement
l"anger, mu"s dem Befehl ein Pr"afix mit den ''oberen Bits''
vorangestellt werden. \asname{} wird solche Pr"afixe automatisch nach
Bedarf einsetzen, man kann jedoch auch mit einem dem Displacement
vorangestellten \verb!'>'! das Setzen eines Pr"afix erzwingen,
z.B. so:
\begin{verbatim}
ld:g.b (0h),0 ; kein Praefix
ld:g.b (400000h),0 ; Praefix automatisch erzeugt
ld:g.b (>0h),0 ; Praefix erzwungen
\end{verbatim}
%%---------------------------------------------------------------------------
Toshiba hat seinerzeit f"ur diesen Prozessor einen (DOS-basierten)
Assembler namens ASM31T geliefert. Dieser Assembler unterst"utzt
eine Reihe von Syntax-Elementen, die sich auf \asname{} nicht ohne
"Anderungen abbilden lie"sen, die die Kompatibilit"at
zu existierenden Quelldateien f"ur andere Targets gef"ahrdert
h"atten. An folgenden Stellen werden m"oglicherweise "Anderungen
erforderlich sein, um f"ur den ASM31T geschriebene Programme mit
\asname{} "ubersetzen zu k"onnen:
\begin{itemize}
\item{ASM31T unterst"utzt C-artige Kommentare (\verb!/* ... */!),
die auch "uber mehrere Zeilen gehen d"urfen. Diese werden
von \asname{} nicht unterst"utzt und m"ussen in mit einem
Semikolon eingeleitete Kommentare umgesetzt werden.}
\item{Wie ASM31T unterst"utzt \asname{} f"ur den TC9331 Kommentare in
runden Klammern (\verb!( ... )!), aber nur innerhalb
eines Befehlsarguments. Enth"alt ein solcher Kommentar ein
Komma, wird dieses Komma als Argument-Trenner behandelt und
der Kommentar nicht beim Parsing der Argumente
"ubersprungen.}
\item{ASM31T erlaubt Symbol- und Label-Namen, die einen
Bindestrich enthalten. Das ist bei \asname{} nicht zugelassen,
der Bindestrich ist hier der Subtraktionsoperator und in
einem Ausdruck wie \verb!end-start! w"are sonst nicht klar,
ob ein einzelnes Symbol oder die Differenz von zwei
Symbolen gemeint ist.}
\item{ASM31T verlangt zwingend ein \tty{END}-Statement am Ende
des Programms; bei \asname{} ist dies optional.}
\end{itemize}
Des weiteren fehlen \asname{} im Moment die F"ahigkeiten, auf
miteinander kollidierende Nutzungen von Funktionseinheiten in
einem Befehl hinzuweisen. Die Dokumentation von Toshiba ist an
diesem Punkt leider etwas schwer verst"andlich.
%%---------------------------------------------------------------------------
Wie schon beim \tty{ASSUME}-Befehl beschrieben, kann \asname{} mit der Kenntnis
"uber den Inhalt des RBP-Registers feststellen, ob im User-Modus
auf gesperrte Register zugegriffen wird. Diese F"ahigkeit
beschr"ankt sich nat"urlich auf direkte Zugriffe (also nicht, wenn
die Register IPA...IPC benutzt werden), und sie hat noch einen
weiteren Haken: da lokale Register (also solche mit Nummern$>$127)
relativ zum Stackpointer adressiert werden, die Bits in RBP sich
aber immer auf absolute Nummern beziehen, wird die Pr"ufung f"ur
lokale Register NICHT durchgef"uhrt. Eine Erweiterung auf lokale
Register w"urde bedingen, da"s \asname{} zu jedem Zeitpunkt den absoluten
Wert von SP kennt, und das w"urde sp"atestens bei rekursiven
Unterprogrammen scheitern...
%%---------------------------------------------------------------------------
Wie in der Erkl"arung des \tty{ASSUME}-Befehls schon erl"autert, versucht
\asname{}, dem Programmierer die Tatsache, da"s der Prozessor mehr physikalischen
als logischen Speicher hat, soweit als m"oglich zu verbergen. Beachten
Sie aber, da"s die DPP-Register \bb{nur} Datenzugriffe betreffen und auch dort
nur absolute Adressierung, also weder indirekte noch indizierte Zugriffe,
da \asname{} ja nicht wissen kann, wie die berechnete Adresse zur Laufzeit
aussehen wird...Bei Codezugriffen arbeitet die Paging-Einheit leider nicht,
man mu"s also explizit mit langen oder kurzen \tty{CALL}s, \tty{JMP}s oder
\tty{RET}s arbeiten. Zumindest bei den ,,universellen'' Befehlen \tty{CALL}
und \tty{JMP} w"ahlt \asname{} automatisch die k"urzeste Form, aber sp"atestens
beim \tty{RET} sollte man wissen, woher der Aufruf kam. Prinzipiell
verlangen \tty{JMPS} und \tty{CALLS} dabei, da"s man Segment und Adresse
getrennt angibt, \asname{} ist jedoch so geschrieben, da"s er eine Adresse selber
zerlegen kann, z.B.
\begin{verbatim}
jmps 12345h
\end{verbatim}
anstelle von
\begin{verbatim}
jmps 1,2345h
\end{verbatim}
Leider sind nicht alle Effekte der chipinternen Instruktions-Pipeline
versteckt: Werden CP (Registerbankadresse), SP (Stack) oder eines der
Paging-Register ver"andert, so steht der neue Wert noch nicht f"ur den
n"achsten Befehl zur Verf"ugung. \asname{} versucht, solche Situationen zu
erkennen und gibt im Falle eines Falles eine Warnung aus. Aber auch
diese Mimik greift nur bei direkten Zugriffen.
Mit \tty{BIT} definierte Bits werden intern in einem 13-Bit-Wort abgelegt,
wobei die Bitadresse in Bit 4..11 liegt und die Bitnummer in den unteren
vier Bits. Diese Anordnung erlaubt es, das n"achsth"ohere bzw.
n"achstniedrigere Bit durch Inkrementieren bzw. Dekrementieren anzusprechen.
Bei expliziten Bitangaben mit Punkt funktioniert das aber nicht "uber
Wortgrenzen hinaus. So erzeugt folgender Ausdruck eine
Wertebereichs"uberschreitung:
\begin{verbatim}
bclr r5.15+1
\end{verbatim}
Hier mu"s ein \tty{BIT} her:
\begin{verbatim}
msb bit r5.15
.
.
.
bclr msb+1
\end{verbatim}
F"ur den 80C167/165/163 ist der SFR-Bereich verdoppelt worden; da"s ein Bit im
zweiten Teil liegt, wird durch ein gesetztes Bit 12 vermerkt. Leider
hatte Siemens bei der Definition des 80C166 nicht vorausgesehen, da"s
256 SFRs (davon 128 bitadressierbar) f"ur Nachfolgechips nicht reichen
w"urden. So w"are es unm"oglich, den zweiten SFR-Bereich von F000H..F1DFH
mit kurzen Adressen oder Bitbefehlen zu erreichen, h"atten die Entwickler
nicht einen Umschaltbefehl eingebaut:
\begin{verbatim}
EXTR #n
\end{verbatim}
Dieser Befehl bewirkt, da"s f"ur die n"achsten \tty{n} Befehle (0$<$\tty{n}$<$5)
anstelle des normalen der erweiterte SFR-Bereich angesprochen werden kann.
\asname{} erzeugt bei diesm Befehl nicht nur den passenden Code, sondern setzt
intern ein Flag, da"s f"ur die n"achsten \tty{n} Befehle nur Zugriffe auf den
erweiterten SFR-Bereich zul"a"st. Da d"urfen nat"urlich keine Spr"unge
dabei sein... Bits aus beiden Bereichen lassen sich nat"urlich jederzeit
definieren, ebenso sind komplette Register aus beiden SFR-Bereichen
jederzeit mit absoluter Adressierung erreichbar. Nur die kurze bzw.
Bitadressierung geht immer nur abwechselnd, Zuwiderhandlungen werden
mit einer Fehlermeldung geahndet.
"Ahnlich sieht es mit den Pr"afixen f"ur absolute bzw. indirekte
Adressierung aus: Da aber sowohl Argument des Pr"afixes als auch der
Adre"sausdruck nicht immer zur "Ubersetzungszeit bestimmbar sind, sind
die Pr"ufungsm"oglichkeiten durch \asname{} sehr eingeschr"ankt, weshalb er es
auch bei Warnungen bel"a"st...im einzelnen sieht das folgenderma"sen aus:
\begin{itemize}
\item{feste Vorgabe einer 64K-Bank mittels \tty{EXTS} oder \tty{EXTSR}:
Im Adre"sausdruck werden direkt die unteren 16 Bit der Zieladresse
eingesetzt. Haben sowohl Pr"afix als auch Befehl einen konstanten
Operanden, so wird "uberpr"uft, ob Pr"afixargument und Bit 16..23 der
Zieladresse identisch sind.}
\item{feste Vorgabe einer 16K-Seite mittels \tty{EXTP} oder \tty{EXTPR}:
Im Adre"sausdruck werden direkt die unteren 14 Bit der Zieladresse
eingesetzt. Bit 14 und 15 bleiben konstant 0, da sie in diesem Modus
nicht vom Prozessor ausgewertet werden. Haben sowohl Pr"afix als
auch Befehl einen konstanten Operanden, so wird "uberpr"uft, ob
Pr"afixargument und Bit 14..23 der Zieladresse identisch sind.}
\end{itemize}
Damit das etwas klarer wird, ein Beispiel (die DPP-Register haben
die Reset-Vorbelegung) :
\begin{verbatim}
extp #7,#1 ; Bereich von 112K..128K
mov r0,1cdefh ; ergibt Adresse 0defh im Code
mov r0,1cdefh ; -->Warnung
exts #1,#1 ; Bereich von 64K..128K
mov r0,1cdefh ; ergibt Adresse 0cdefh im Code
mov r0,1cdefh ; -->Warnung
\end{verbatim}
%%---------------------------------------------------------------------------
"Ahnlich wie die MCS-48-Familie teilen auch die PICs ihren
Programmspeicher in mehrere B"anke auf, da im Opcode nicht gen"ugend Platz
f"ur die vollst"andige Adresse war. \asname{} verwendet f"ur die Befehle \tty{CALL}
und \tty{GOTO} die gleiche Automatik, d.h. setzt die PA-Bits im
Statuswort entsprechend Start- und Zieladresse. Im Gegensatz zu den 48ern
ist dieses Verfahren hier aber noch deutlich problematischer:
\begin{enumerate}
\item{Die Befehle sind nicht mehr nur ein Wort, sondern bis zu drei Worten
lang, k"onnen also nicht mehr in jedem Fall mit einem bedingten Sprung
"ubergangen werden.}
\item{Es ist m"oglich, da"s der Programmz"ahler beim normalen
Programmfortgang eine Seitengrenze "uberschreitet. Die vom Assembler
angenommene Belegung der PA-Bits stimmt dann nicht mehr mit der
Realit"at "uberein.}
\end{enumerate}
Bei den Befehlen, die das Register W mit einem anderen Register
verkn"upfen, mu"s normalerweise als zweiter Parameter angegeben werden, ob
das Ergebnis in W oder im Register abgelegt werden soll. Bei diesem
Assembler ist es erlaubt, den zweiten Parameter wegzulassen. Welches Ziel
dann angenommen werden soll, h"angt vom Typ des Befehls ab: bei un"aren
Operationen wird defaultm"a"sig das Ergebnis zur"uck ins Register gelegt.
Diese Befehle sind:
\begin{quote}
{\tt COMF, DECF, DECFSZ, INCF, INCFSZ, RLF, RRF} und {\tt SWAPF}
\end{quote}
Die anderen Befehle betrachten W defaultm"a"sig als Akkumulator, zu dem ein
Register verkn"upft wird:
\begin{quote}
{\tt ADDWF, ANDWF, IORWF, MOVF, SUBWF} und {\tt XORWF}
\end{quote}
Die von Microchip vorgegebene Schreibweise f"ur Literale ist ziemlich
abstrus und erinnert an die auf IBM 360/370-Systemen "ubliche Schreibweise
(Gr"u"se aus Neandertal...). Um nicht noch einen Zweig in den Parser
einf"ugen zu m"ussen, sind bei \asname{} Konstanten in
Motorola-Syntax zu schreiben (wahlweise auch Intel oder C im \tty{RELAXED}-Modus).
Dem Assembler liegt die Include-Datei STDDEF16.INC bei, in der die Adressen
der Hardware-Register und Statusbits verewigt sind. Daneben enth"alt sie
eine Liste von ,,Befehlen'', die der Microchip-Assembler als Makro
implementiert. Bei der Benutzung dieser Befehlsmakros ist gro"se Vorsicht
angebracht, da sie mehrere Worte lang sind und sich somit nicht "uberspringen
lassen!!
%%---------------------------------------------------------------------------
F"ur diese Prozessoren gelten im wesentlichen die gleichen Hinweise wie
f"ur ihre kleinen Br"uder, mit zwei Ausnahmen: Die zugeh"orige Include-Datei
enth"alt nur Registerdefinitionen, und die Probleme bei Sprungbefehlen
sind deutlich kleiner. Aus der Reihe f"allt nur \tty{LCALL}, der einen
16-Bit-Sprung erlaubt. Dieser wird mit folgendem ,,Makro'' "ubersetzt:
\begin{verbatim}
MOVLW <Adr15..8>
MOWF 3
LCALL <Adr0..7>
\end{verbatim}
%%---------------------------------------------------------------------------
Durch die beschr"ankte L"ange des Instruktionswortes ist es nicht
m"oglich, darin eine vollst"andige Programmspeicher-Adresse (11 Bit)
oder Datenspeicher-Adresse (8 Bit) unterzubringen. Der Prozessor
erg"anzt die gek"urzten Adressen um die PA-Bits aus dem
STATUS-Register bzw. oberen Bits aus dem FSR-Register. "Uber
\tty{ASSUME}-Befehle teilt man dem Assembler deren aktuellen Inhalt
mit. Falls auf Adressen zugegriffen wird, die mit den vermerkten
Werten nicht zugreifbar sind, erfolgt eine Warnung.
%%---------------------------------------------------------------------------
Diese Prozessoren k"onnen das Code-ROM seitenweise in den Datenbereich
einblenden. Weil ich nicht die ganze Mimik des \tty{ASSUME}-Befehles
hier wiederk"auen m"ochte, verweise ich auf das entsprechende Kapitel
(\ref{ST6Assume}), in dem steht, wie man mit diesem Befehl einigerma"sen
unfallfrei Konstanten aus dem ROM lesen kann.
Bei n"aherer Betrachtung des Befehlssatzes fallen einige eingebaute
,,Makros'' auf. Die Befehle, die mir aufgefallen sind (es gibt aber
vielleicht noch mehr...), sind in Tabelle \ref{TabHid62} aufgelistet.
\begin{table*}[htbp]
\begin{center}\begin{tabular}{|l|l|}
Befehl & in Wirklichkeit \\
\tty{CLR A} & \tty{SUB A,A} \\
\tty{SLA A} & \tty{ADD A,A} \\
\tty{CLR adr} & \tty{LDI adr,0} \\
\tty{NOP} & \tty{JRZ PC+1} \\
\end{tabular}\end{center}
\caption{versteckte Makros im ST6225-Befehlssatz\label{TabHid62}}
\end{table*}
Insbesondere der letztere Fall verbl"ufft doch etwas...
Leider fehlen aber einige Anweisungen wirklich. So gibt es z.B. zwar einen
\tty{AND}-Befehl, aber kein \tty{OR}...von \tty{XOR} gar nicht zu
reden. In der Datei STDDEF62.INC finden sich deshalb neben den Adressen
der SFRs noch einige Makros zur Abhilfe.
Der Original-Assembler AST6 von SGS-Thomson verwendet teilweise andere
Pseudobefehle als \asname{}. Au"ser der Tatsache, da"s \asname{} Pseudobefehle nicht
mit einem vorangestellten Punkt kennzeichnet, sind folgende Befehle
identisch:
\begin{verbatim}
ASCII, ASCIZ, BLOCK, BYTE, END, ENDM, EQU, ERROR, MACRO,
ORG, TITLE, WARNING
\end{verbatim}
Tabelle \ref{TabAST6} zeigt die AST6-Befehle, zu denen analoge in \asname{}
existieren.
\begin{table*}[htbp]
\begin{center}\begin{tabular}{|l|l|l|}
AST6 & \asname{} & Bedeutung/Funktion \\
\tty{.DISPLAY} & \tty{MESSAGE} & Meldung ausgeben \\
\tty{.EJECT} & \tty{NEWPAGE} & neue Seite im Listing \\
\tty{.ELSE} & \tty{ELSEIF} & bed. Assemblierung \\
\tty{.ENDC} & \tty{ENDIF} & bed. Assemblierung \\
\tty{.IFC} & \tty{IF...} & bed. Assemblierung \\
\tty{.INPUT} & \tty{INCLUDE} & Include-Datei einbinden \\
\tty{.LIST} & \tty{LISTING}, \tty{MACEXP\_DFT} & Listing-Einstellung \\
\tty{.PL} & \tty{PAGE} & Seitenl"ange Listing \\
\tty{.ROMSIZE} & \tty{CPU} & Zielprozessor einstellen \\
\tty{.VERS} & \tty{VERSION} (Symbol) & Version abfragen \\
\tty{.SET} & \tty{EVAL} & Variablen neu setzen \\
\end{tabular}\end{center}
\caption{"aquivalente Befehle AST6$\leftrightarrow$\asname{}\label{TabAST6}}
\end{table*}
%%---------------------------------------------------------------------------
In \cite{ST7Man} ist der '.w'-Postfix f"ur 16-Bit-Adressen nur f"ur
speicherindirekte Operanden definiert, um zu vermerken, da"s auf einer
Zeropageadresse eine 16-bittige Adresse liegt; \asname{} unterst"utzt ihn jedoch
zus"atzlich auch f"ur absolute Adressen oder Displacements in indizierter
Adressierung, um trotz eines nur 8 Bit langen Wertes (0..255) ein
16-bittiges Displacement zu erzeugen.
%%---------------------------------------------------------------------------
Die Bitadressierungsm"oglichkeiten des ST9 sind relativ eingeschr"ankt:
Mit Ausnahme des \tty{BTSET}-Befehls ist es nur m"oglich, auf Bits innerhalb
des aktuellen Arbeitsregistersatzes zuzugreifen. Eine Bit-Adresse
sieht also folgenderma"sen aus:
\begin{verbatim}
rn.[!]b
\end{verbatim}
wobei \verb?!? eine optionale Invertierung eines Quelloperanden bedeutet.
Wird ein Bit symbolisch mittels des \tty{BIT}-Befehles definiert, so wird
die Registernummer im Symbolwert in Bit 7..4, die Bitnummer in Bit
3..1 und eine optionale Invertierung in Bit 0 vermerkt. \asname{} unterscheidet
direkte und symbolische Bitangaben am Fehlen eines Punktes,
der Name eines Bitsymboles darf also keinen Punkt enthalten, obwohl
sie an sich zul"assig w"aren. Es ist auch zul"assig, bei der Referenzierung
von Bitsymbolen diese zu nachtr"aglich zu invertieren:
\begin{verbatim}
bit2 bit r5.3
.
.
bld r0.0,!bit2
\end{verbatim}
Auf diese Weise ist es auch m"oglich, eine inverse Definition nachtr"aglich
wieder aufzuheben.
Bitdefinitionen finden sich in gro"ser Zahl in der Include-Datei
REGST9.INC, in der die Register- und Bitnamen aller On-Chip-Peripherie
beschrieben sind. Beachten Sie jedoch, da"s deren Nutzung
nur m"oglich ist, wenn die Arbeitsregisterbank vorher auch auf diese
Register ausgerichtet wurde!
Im Gegensatz zu der zum AST9 von SGS-Thomson geh"orenden Definitionsdatei
sind f"ur \asname{} die Namen der Peripherieregister nur als allgemeine
Registernamen definiert (\tty{R...}), nicht auch noch als Arbeitsregister
(\tty{r...}). Dies ist so, weil \asname{} Geschwindigkeitsgr"unden keine
Aliasnamen f"ur Register definieren kann.
%%---------------------------------------------------------------------------
Eigentlich habe ich diesen Prozessor ja nur eingebaut, um mich "uber
das seltsame Gebaren von SGS-Thomson zu beklagen: Als ich das
6804-Datenbuch zum ersten Mal in die Hand bekam, f"uhlte ich mich ob des
etwas ,,unvollst"andigen'' Befehlssatzes und der eingebauten Makros
spontan an die ST62-Serie vom gleichen Hersteller erinnert. Ein
genauerer Vergleich der Opcodes f"orderte erstaunliches zu Tage:
Ein 6804-Opcode ergibt sich durch Spiegelung aller Bits im entsprechenden
ST62-OpCode! Thomson hat hier also offensichtlich etwas
Prozessorkern-Recycling betrieben...wogegen ja auch nichts einzuwenden
w"are, wenn nicht so eine Verschleierungstaktik betrieben werden w"urde:
andere Peripherie, Motorola- anstelle Zilog-Syntax sowie das h"a"sliche
Detail, in Opcodes enthaltene Argumente (z.B. Bitfelder mit Displacements)
\bb{nicht} zu drehen. Letzterer Punkt hat mich auch nach l"angerem "Uberlegen
dazu bewogen, den 6804 doch in \asname{} aufzunehmen. Ich wage "ubrigens keine
Spekulationen, welche Abteilung bei Thomson von welcher abgekupfert hat...
Im Gegensatz zur ST62-Version enth"alt die Include-Datei f"ur den
6804 keine Makros, die die L"ucken im Befehlssatz etwas ,,auspolstern''
sollen. Dies "uberlasse ich dem geneigten Leser als Finger"ubung!
%%---------------------------------------------------------------------------
Offensichtlich ist es Ehrgeiz jedes Prozessorherstellers, seine eigene
Notation f"ur Hexadezimalkonstanten zu erfinden. Texas Instruments
war bei diesen Prozessoren besonders originell: ein vorangestelltes
$>$-Zeichen! Die "Ubernahme dieses Formates in \asname{} h"atte zu schweren
Konflikten mit den Vergleichs-und Schiebeoperatoren von \asname{} im Formelparser
gef"uhrt. Ich habe mich deshalb f"ur die Intel-Notation entschieden, zu
der sich TI bei der 340x0-Serie und den 3201x-Nachfolgern ja dann auch
durchgerungen hat...
Leider hat das Instruktionswort dieser Prozessoren nicht gen"ugend Bits,
um bei direkter Adressierung alle 8 Bits zu enthalten, weshalb der
Datenadre"sraum logisch in 2 B"anke zu 128 W"ortern gespalten ist. \asname{}
verwaltet diesen als ein durchgehendes Segment von 256 W"ortern und
l"oscht bei direkten Zugriffen automatisch das Bit 7 (Ausnahme: Befehl
\tty{SST}, der nur in die obere Bank schreiben kann). Der Programmierer
ist daf"ur erforderlich, da"s das Bank-Bit stets den richtigen Wert hat!
Ein weiterer, nur sehr versteckt im Datenbuch stehender Hinweis: Die
\tty{SUBC}-Anweisung ben"otigt zur Ausf"uhrung intern mehr als einen
Takt, das Steuerwerk arbeitet jedoch schon an dem n"achsten Befehl weiter.
Im auf ein \tty{SUBC} folgenden Befehl darf deshalb nicht auf den
Akkumulator zugegriffen werden. \asname{} nimmt hier \bb{keine} Pr"ufung vor!
%%---------------------------------------------------------------------------
Da ich nicht selber diesen Codegenerator geschrieben habe (was nichts an
seiner Qualit"at mindert), kann ich nur kurz hier umrei"sen, wieso es
Befehle gibt, bei denen ein vorangestelltes Label als untypisiert, d.h.
keinem Adre"sraum zugeordnet, gespeichert wird: Der 20er der TMS-Reihe
kennt sowohl ein 64 Kbyte gro"ses Code- als auch Datensegment. Je nach
externer Beschaltung kann man dabei Code- und Datenbereiche "uberlappen,
um z.B. Konstanten im Codebereich zu abzulegen und auf diese als Daten
zuzugreifen (Ablage im Code ist notwendig, weil "altere \asname{}-Versionen davon
ausgehen, da"s ein Datensegment aus RAM besteht, das in einem
Standalone-System nach dem Einschalten keinen definierten Inhalt hat und
verweigern in Segmenten au"ser Code deshalb die Ablage von Daten). Ohne
dieses Feature w"urde \asname{} nun jeden Zugriff auf die abgelegten Daten mit
einer Warnung (,,Symbol aus falschem Segment'') quittieren. Im einzelnen
erzeugen folgende Pseudobefehle untypisierte Labels:
\begin{quote}
{\tt BSS, STRING, RSTRING, BYTE, WORD , LONG, FLOAT \\
DOUBLE, EFLOAT, BFLOAT} und {\tt TFLOAT}
\end{quote}
Sollten doch einmal typisierte Labels gew"unscht sein, so kann man sich
behelfen, indem man das Label in eine getrennte Zeile vor dem Pseudobefehl
schreibt. Umgekehrt kann man einen der anderen Pseudobefehle mit einem
typenlosen Label versehen, indem man vor dem Befehl das Label mit
\begin{verbatim}
<Name> EQU $
\end{verbatim}
definiert.
%%---------------------------------------------------------------------------
Die gr"o"sten Magenschmerzen bei diesem Prozessor hat mir die Syntax
paralleler Befehle bereitet, die auf zwei Zeilen verteilt werden,
wobei beide Befehle an sich auch sequentiell ausgef"uhrt werden k"onnen.
Deshalb erzeugt \asname{} zuerst den Code f"ur die einzelne erste Operation,
wenn er dann in der zweiten Zeile erkennt, da"s eine parallele Anweisung
vorliegt, wird der zuerst erzeugte Code durch den neuen ersetzt.
Im Listing kann man dies daran erkennen, da"s der Programmz"ahler
nicht weiterl"auft und in der zweiten Zeile anstelle eines Doppelpunktes
ein \tty{R} vor dem erzeugten Code steht.
Bez"uglich der doppelten senkrechten Striche und ihrer Position in der
Zeile ist man nicht ganz so flexibel wie beim TI-Assembler: Entweder
man schreibt sie anstelle eines Labels (d.h. in der ersten Spalte oder
mit einem angeh"angten Doppelpunkt, das ist aber nicht mehr
TI-kompatibel...) oder direkt vor den zweiten Befehl ohne Leerzeichen,
sonst bekommt der Zeilenparser von \asname{} Probleme und h"alt die Striche
f"ur das Mnemonic.
%%---------------------------------------------------------------------------
Wie bei den meisten "alteren Prozessorfamilien auch, hatte TI seinerzeit
ein eigenes Format zur Schreibweise von Hexadezimal- und Bin"arkonstanten
verwendet, anstelle deren \asname{} die normale, heute auch bei TI
gebr"auchliche Intel-Notation verwendet.
Die TI-Syntax f"ur Register erlaubt es, da"s anstelle eines echten Namens
(entweder \tty{Rx} oder \tty{WRx}) auch eine einfache Integer-Zahl
zwischen 0 und 15 benutzt werden kann. Dies hat zwei Folgen:
\begin{itemize}
\item{\tty{R0...R15} bzw. \tty{WR0..WR15} sind einfache, vordefinierte
Integersymbole mit den Werten 0..15, und die Definition von
Registeraliasen funktioniert "uber schlichte \tty{EQUs}.}
\item{Im Gegensatz zu einigen anderen Prozessoren kann ich nicht das
zus"atzliche \asname{}-Feature anbieten, da"s das Kennzeichen f"ur
absolute Adressierung (hier ein Klammeraffe) weggelassen werden
darf. Da ein fehlendes Kennzeichen hier aber Registernummern (im
Bereich 0 bis 15) bedeuten w"urde, war das hier nicht m"oglich.}
\end{itemize}
Weiterhin wechselt TI mit der Registerbezeichnung zwischen \tty{Rx} und
\tty{WRx}...vorerst ist beides zugelassen.
%%---------------------------------------------------------------------------
Diese Prozessorreihe geh"ort noch zu den "alteren, von TI entwickelten
Reihen, und deswegen benutzt TI in ihren eigenen Assemblern noch die
herstellereigene Syntax f"ur hexadezimale und bin"are Konstanten
(vorangestelltes $<$ bzw. ?). Da das in \asname{} aber so nicht machbar ist, wird
defaultm"a"sig die Intel-Syntax verwendet. Auf diese ist Texas bei den
Nachfolgern dieser Familie, n"amlich den 370ern auch umgestiegen. Beim
genaueren Betrachten des Maschinenbefehlssatzes stellt man fest, da"s
ca. 80\% der 7000er-Befehle bin"ar aufw"artskompatibel sind, und auch die
Assemblersyntax ist fast gleich - aber eben nur fast. Bei der Erweiterung
des 7000er-Befehlssatzes hat TI n"amlich auch gleich die Chance genutzt,
die Syntax etwas zu vereinheitlichen und zu vereinfachen. Ich habe mich
bem"uht, einen Teil dieser "Anderungen auch in die 7000er Syntax
einflie"sen zu lassen:
\begin{itemize}
\item{Anstelle eines Prozentzeichens zur Kennzeichnung von
unmittelbarer Adressierung darf auch das allgemein bekanntere Doppelkreuz
verwendet werden.}
\item{Wenn bei den Befehlen \tty{AND, BTJO, BTJZ, MOV, OR} und
\tty{XOR} eine Port-Adresse (\tty{P...}) als Quelle oder Ziel
benutzt wird, ist es nicht notwendig, die Mnemonic-Form mit explizit
angeh"angtem \tty{P} zu benutzen - die allgemeine Form reicht genauso
aus.}
\item{Der vorangestelle Klammeraffe f"ur absolute oder B-indizierte
Adressierung darf weggelassen werden.}
\item{Anstelle des \tty{CMPA}-Befehls darf auch einfach
\tty{CMP} mit \tty{A} als Ziel benutzt werden.}
\item{Anstelle \tty{LDA} oder \tty{STA} darf auch einfach der \tty{MOV}-Befehl
mit \tty{A} als Ziel bzw. Quelle benutzt werden.}
\item{Anstelle des \tty{MOVD}-Befehls darf auch \tty{MOVW} benutzt werden.}
\item{Anstelle von \tty{RETS} oder \tty{RETI} darf auch verk"urzt
\tty{RTS} bzw. \tty{RTI} geschrieben werden.}
\item{\tty{TSTA} bzw. \tty{TSTB} d"urfen auch als \tty{TST A} bzw. \tt{TST
B} geschrieben werden.}
\item{\tty{XCHB B} ist als Alias f"ur \tty{TSTB} zugelassen.}
\end{itemize}
Wichtig - diese Varianten sind nur beim TMS70Cxx zugelassen - entsprechende
7000er-Varianten sind bei den 370ern {\em nicht} erlaubt!
%%---------------------------------------------------------------------------
Obwohl diese Prozessoren keine speziellen Befehle zur Bitmanipulation
besitzen, wird mit Hilfe des Assemblers und des \tty{DBIT}-Befehles
(siehe dort) die Illusion erzeugt, als ob man einzelne Bits manipulieren
w"urde. Dazu wird beim \tty{DBIT}-Befehl eine Adresse mit einer
Bitposition zusammengefa"st und in einem Symbol abgelegt, das man dann
als Argument f"ur die Pseudobefehle \tty{SBIT0, SBIT1, CMPBIT, JBIT0}
und \tty{JBIT1} verwenden kann. Diese werden in die Befehle
\tty{OR, AND, XOR, BTJZ} und \tty{BTJO} mit einer passenden Bitmaske
"ubersetzt.
An diesen Bit-Symbolen ist "uberhaupt nichts geheimnisvolles, es handelt
sich um schlichte Integerwerte, in deren unterer H"alfte die
Speicheradresse und in deren oberer H"alfte die Bitstelle gespeichert
wird. Man k"onnte sich seine Symbole also auch ohne weiteres selber
basteln:
\begin{verbatim}
defbit macro name,bit,adr
name equ adr+(bit<<16)
endm
\end{verbatim}
aber mit dieser Schreibweise erreicht man nicht den \tty{EQU}-artigen Stil,
den Texas vorgegeben hat (d.h. das zu definierende Symbol steht anstelle
eines Labels). ACHTUNG! Obwohl \tty{DBIT} eine beliebige Adresse
zul"a"st, k"onnen f"ur die Pseudobefehle nur die Adressen 0..255 und
1000h..10ffh verwendet werden, eine absolute Adressierungsart kennt
der Prozessor an dieser Stelle nicht...
%%---------------------------------------------------------------------------
Der MSP430 wurde als RISC-Prozessor mit minimalem Stromverbrauch
konzipiert. Aus diesem Grund ist der Satz von Befehlen, die der
Prozessor in Hardware versteht, auf das absolut notwendige reduziert
worden (da RISC-Prozessoren keinen Mikrocode besitzen, mu"s jeder
Befehl mit zus"atzlichem Silizium implementiert werden und erh"oht so
den Stromverbrauch). Eine Reihe von Befehlen, die bei anderen
Prozessoren in Hardware gegossen wurden, werden beim MSP durch eine
Emulation mit anderen Befehlen realisiert. Fr"uhere Versionen
von \asname{} implementierten diese Befehle "uber Makros in der Datei
\tty{REGMSP.INC}. Wer diese Datei nicht einband, erhielt bei "uber
der H"alfte der insgesamt von TI definierten Befehle
Fehlermeldungen. Dies ist aktuell nicht mehr so, zusammen mit
der Erweiterung auf den CPU430X-Befehlssatz werden die
Instruktionen vom Assembler direkt implementiert.
\tty{REGMSP.INC} enth"alt nur noch die Adressen von I/O-Registern.
Wer aus irgendwelchen Gr"unden die alten Makros braucht, findet
sie jetzt in der Datei \tty{EMULMSP.INC}.
Die emulierten Instruktionen decken auch einige Sonderf"alle ab,
die der TI-Assembler nicht beherrscht. So wird zum Beispiel
\begin{verbatim}
rlc @r6+
\end{verbatim}
automatisch in
\begin{verbatim}
addc @r6+,-2(r6)
\end{verbatim}
umgesetzt.
%%---------------------------------------------------------------------------
Der erste Mikrocontroller der Welt nun endlich auch in \asname{} - lange hat es
gedauert, nun ist die L"ucke geschlossen. Dieses Target hat aber einige
T"ucken, die in diesem Abschnitt kurz angesprochen werden sollen.
Zum einen ist der Befehlssatz dieser Controller teilweise "uber die ROM-Maske
ver"anderbar, d.h. man kann die Funktion einiger Opcodes in Grenzen frei
definieren. \asname{} kennt nur die Befehle und deren Kodierungen, die in
\cite{TMS1000PGMRef} als Default-Kodierungen beschrieben sind. Wer f"ur eine
spezielle Anwendung andere Befehle bzw. gleiche Befehle mit anderem Opcode
hat, kann diese "uber Makros mit passende \tty{DB}-Befehlen "andern.
Des weiteren ist zu beachten, da"s Spr"unge und Unterprogrammaufrufe nur die
unteren 6 Bit der Zieladresse im Befehl selber beinhalten. Die oberen 4 bzw.
5 Bits kommen aus Page- bzw. Chapter-Registern, die vorher passend zu setzen
sind. \asname{} selber kann hier nicht "uberpr"ufen, ob die Register vom Programmierer
korrekt gesetzt werden!. Zumindest f"ur den Fall, da"s man im gleichen Chapter
bleibt, gibt es die Assembler-Pseudobefehle \tty{CALLL} bzw.
\tty{BL}, die einen \tty{LDP}- und einen \tty{CALL/BR}-Befehl zusammenfassen
(was angesichts des kanppen Programmspeichers eine bequeme, aber nicht immer
effiziente Variante ist).
%%---------------------------------------------------------------------------
Leider Gottes hat sich auch National dazu entschieden, als
Schreibweise f"ur nichtdezimale Integer-Konstanten die von
IBM-Gro"srechnern bekannte (und von mir nicht geliebte) Variante
\verb!X'...! zu benutzen. Das geht nat"urlich (wie immer) nicht.
Zum Gl"uck scheint der ASMCOP aber auch die C-Variante zuzulassen,
und diese wurde deshalb der Default f"ur die COPs...
%%---------------------------------------------------------------------------
Benutzt man beim SC/MP indirekte Adressierung mit Displacement, und
ist das benutzte Basis- bzw. Pointer-Register nicht P0 bzw. PC, dann
hat ein Displacement von -128 (80 hex) eine Sonderbedeutung: Anstelle
eben dieses Werts wird der Inhalt des E-Registers als Displacement
verwendet. Im 'klassischen' NS-Assembler mu"s der Programmierer um
diesen Umstand wissen bzw. ihn explizit benutzen, z.B. so:
\begin{verbatim}
ereg equ -128
ld ereg(p1)
\end{verbatim}
Dies birgt aber das Risiko, da"s sich der Wert -128 auch einmal
'versehentlich' als Teil einer Berechnung ergeben kann, und man
sucht erst einmal, warum das Programm nicht tut, was erwartet
wurde. Ich habe mich deshalb entschlossen, diesen Sonderwert
etwas expliziter zu machen:
Wird ein Displacement von -128 verwendet, so erfolgt eine Warnung.
Diese Warnung kann man ignorieren; will man sie los werden, so
verwende man das eingebaute Literal \verb!E!, das eben dieses Register
referenziert:
\begin{verbatim}
ld e(p1)
\end{verbatim}
Da das SC/MP-Target Registersymbole unterst"utzt, ist es auch m"oglich,
das 'eigene Symbol' passend zu definieren:
\begin{verbatim}
ereg reg e
ld ereg(p1)
\end{verbatim}
Dies sollte die Anzahl notwendiger Anpassungen in existierendem
Code auf ein Minimum reduzieren.
%%---------------------------------------------------------------------------
Original gab es f"ur diese Reihe von DECT-Controllern mit relativ
einfachem Befehlssatz nur einen sehr schlichten Assembler von National
selber. Ein Assembler von IAR Systems ist angek"undigt, aber noch nicht
erh"altlich. Da die Entwicklungstools von IAR allerdings auch nach
M"oglichkeit CPU-unabh"angig angelegt sind, kann man anhand erh"altlicher
Zielplattformen in ungef"ahr absch"atzen, wie dessen Pseudobefehle
aussehen werden, und damit im Blick sind die (wenigen) SC144xx-spezifisch
realisierten Befehle {\tt DC, DC8, DW16, DS, DS8, DS16, DW} angelegt. Bei
Befehlen, die bereits im \asname{}-Kern angelegt sind, wollte ich nat"urlich
nicht das Rad neu erfinden, deshalb hier eine Tabelle mit "Aquivalenzen:
Die Befehle \tty{ALIGN, END, ENDM, EXITM, MACRO, ORG, RADIX, SET} und
\tty{REPT} exisieren sowohl bei IAR als auch \asname{} und haben gleiche
Bedeutung. Bei folgenden Befehlen mu"s man umstellen:
\begin{table*}[htb]
\begin{center}\begin{tabular}{|l|l|l|}
IAR & \asname{} & Funktion\\
\tty{\#include} & \tty{include} & Include-Datei einbinden \\
\tty{\#define} & \tty{SET, EQU} & Symbole definieren \\
\tty{\#elif, ELIF, ELSEIF} & \tty{ELSEIF} & Weiterer Zweig einer IF-Kette \\
\tty{\#else, ELSE} & \tty{ELSE} & Letzter Zweig einer IF-Kette \\
\tty{\#endif, ENDIF} & \tty{ENDIF} & Beendet eine IF-Kette \\
\tty{\#error} & \tty{ERROR, FATAL} & Fehlermeldung erzeugen \\
\tty{\#if, IF} & \tty{IF} & Beginn einer IF-Kette\\
\tty{\#ifdef} & \tty{IFDEF} & Symbol definiert ? \\
\tty{\#ifndef} & \tty{IFNDEF} & Symbol nicht definiert ? \\
\tty{\#message} & \tty{MESSAGE} & Nachricht ausgeben \\
\tty{=, DEFINE, EQU} & \tty{=, EQU} & Feste Wertzuweisung \\
\tty{EVEN} & \tty{ALIGN 2} & Programmz"ahler gerade machen \\
\tty{COL, PAGSIZ} & \tty{PAGE} & Seitengr"o"se f"ur Listing setzen \\
\tty{ENDR} & \tty{ENDM} & Ende einer REPT-Struktur \\
\tty{LSTCND, LSTOUT} & \tty{LISTING} & Umfang des Listings steuern \\
\tty{LSTEXP, LSTREP} & \tty{MACEXP} & Expandierte Makros anzeigen? \\
\tty{LSTXRF} & \verb!<Kommandozeile>! & Querverweisliste erzeugen \\
\tty{PAGE} & \tty{NEWPAGE} & Neue Seite im Listing \\
\tty{REPTC} & \tty{IRPC} & Repetition mit Zeichenersetzung \\
\end{tabular}\end{center}
\end{table*}
Keine direkte Entsprechung gibt es f"ur die Befehle {\tt CASEON, CASEOFF,
LOCAL, LSTPAG, \#undef} und {\tt REPTI}.
Ein direktes "Aquivalent der Pr"aprozessorbefehle ist nat"urlich nicht
m"oglich, solange \asname{} keinen C-artigen Pr"aprozessor besitzt. C-artige
Kommentare sind im Moment leider auch nicht m"oglich. Achtung: Wer
IAR-Codes f"ur \asname{} umsetzt, mu"s die Pr"aprozessorstatements nicht nur
umwandeln, sondern auch aus Spalte 1 herausbewegen, da bei \asname{} in Spalte 1
nur Labels stehen d"urfen!
%%---------------------------------------------------------------------------
Wie es sich f"ur CISC-Prozessoren geh"ort, verf"ugt diese Serie "uber ausgefeilte
und komplexe Adressierungsarten. National definiert in ihren Manuals f"ur
jede davon die Assembler-Syntax, und \asname{} setzt auch genau diese um. Wie bei
fast jeder Architektur, f"ur die Werkzeuge von Drittherstellern erstellt wurden,
gibt es jedoch auch Abweichungen und Erweiterungen, und ein paar davon habe
ich auch ,,mitgenommen'':
Die von National vorgesehene Methode, PC-relativ zu adressieren, ist folgende:
\begin{verbatim}
movb r0,*+disp
\end{verbatim}
Das dr"uckt nat"urlich sehr klar aus, was in diesem Fall passiert, will man aber
einfach eine bestimmte Speicherstelle PC-relativ adressieren, dann mu"s man die
Distanz selber berechnen:
\begin{verbatim}
movb r0,*+(addr-*)
\end{verbatim}
Die erste Vereinfachung ist, da"s es unter bestimmten Umst"anden auch ausreicht,
einfach nur
\begin{verbatim}
movb r0,addr
\end{verbatim}
zu schreiben - absolute Adressierung wird ja durch ein vorangestelltes \@-Zeichen
kenntlich gemacht. Diese vereinfachte Schreibweise ist unter folgenden Bedingungen
erlaubt:
\begin{itemize}
\item{Immediate-Adressierung ist nicht erlaubt, z.B. weil es sich um einen
Zieloperanden handelt, so da"s keine Verwechslung damit m"oglich ist.}
\item{Es wird mit einer Index-Erweiterung gearbeitet (in eckigen Klammern angeh"angt),
die nicht mit Immediate-Adressierung kombinierbar ist.}
\end{itemize}
Alternativ unterst"utzt \asname{} f"ur PC-relative Addressierung immer die Schreibweise
\begin{verbatim}
movb r0,addr(pc)
\end{verbatim}
Hier wird - analog zum 68000 - die Distanz ebenfalls automatisch berechnet.
F"ur den External-Mode, der in der National-Syntax folgenderma"sen geschrieben
wird:
\begin{verbatim}
movb r0,ext(disp1)+disp2
\end{verbatim}
wird auch die Variante
\begin{verbatim}
movb r0,disp2(disp1(ext))
\end{verbatim}
unterst"utzt, die wohl im UNIX-Umfeld g"angig war.
%%---------------------------------------------------------------------------
F"ur relative, unbedingte Spr"unge gibt es den \tty{JR}-Befehl (Sprungdistanz
-32...+31, 1 Byte) sowie den \tty{JRE}-Befehl (Sprungdistanz -256...+255, 2
Bytes). \asname{} kennt weiterhin den Pseudobefehl \tty{J}, der automatisch den
k"urzestm"oglichen Befehl benutzt.
Architektur und Befehlssatz dieser Prozessoren sind grob an den
Intel 8080/8085 angelehnt - das gilt auch f"ur die Mnemonics. Die
Adressierungsart (direkt, indirekt, immediate) ist mit in das
Mnemonic verpackt, und 16-Bit-Register (BC, DE, HL) werden wie
beim 8080 mit einem Buchstaben abgek"urzt. Da NEC in der
Erkl"arung der einzelnen Adressierungsarten aber immer mal
wieder die ausgeschriebenen Registernamen benutzt, und auch mal
und mal nicht Klammern benutzt, um indirekte Adressierung anzudeuten,
habe ich mich entschlossen, neben den 'offiziellen'
Notationen aus dem NEC-Manual auch einige alternative Notationen
zuzulassen. Einige nicht-NEC-Tools wie z.B. Disassembler
scheinen solche Notationen ebenfalls zu benutzen:
\begin{itemize}
\item{Anstelle \tty{B} darf auch \tty{BC}, \tty{(B)} oder
\tty{(BC)} geschrieben werden.}
\item{Anstelle \tty{D} darf auch \tty{DE}, \tty{(D)} oder
\tty{(DE)} geschrieben werden.}
\item{Anstelle \tty{H} darf auch \tty{HL}, \tty{(H)} oder
\tty{(HL)} geschrieben werden.}
\item{Anstelle \tty{D+} darf auch \tty{DE+}, \tty{(D+)},
\tty{(DE+)} oder \tty{(DE)+} geschrieben werden.}
\item{Anstelle \tty{H+} darf auch \tty{HL+}, \tty{(H+)},
\tty{(HL+)} oder \tty{(HL)+} geschrieben werden.}
\item{Anstelle \tty{D-} darf auch \tty{DE-}, \tty{(D-)},
\tty{(DE-)} oder \tty{(DE)-} geschrieben werden.}
\item{Anstelle \tty{H-} darf auch \tty{HL-}, \tty{(H-)},
\tty{(HL-)} oder \tty{(HL)-} geschrieben werden.}
\item{Anstelle \tty{D++} darf auch \tty{DE++}, \tty{(D++)},
\tty{(DE++)} oder \tty{(DE)++} geschrieben werden.}
\item{Anstelle \tty{H++} darf auch \tty{HL++}, \tty{(H++)},
\tty{(HL++)} oder \tty{(HL)++} geschrieben werden.}
\item{Anstelle \tty{D--} darf auch \tty{DE--}, \tty{(D--)},
\tty{(DE--)} oder \tty{(DE)--} geschrieben werden.}
\item{Anstelle \tty{H--} darf auch \tty{HL--}, \tty{(H--)},
\tty{(HL--)} oder \tty{(HL)--} geschrieben werden.}
\item{Anstelle \tty{H+A} darf auch \tty{HL+A}, \tty{A+H},
\tty{A+HL}, \tty{(H+A)}, \tty{(HL+A)}, \tty{(A+H)}
oder \tty{(A+HL)} geschrieben werden.}
\item{Anstelle \tty{H+B} darf auch \tty{HL+B}, \tty{B+H},
\tty{B+HL}, \tty{(H+B)}, \tty{(HL+B)}, \tty{(B+H)}
oder \tty{(B+HL)} geschrieben werden.}
\item{Anstelle \tty{H+EA} darf auch \tty{HL+EA}, \tty{EA+H},
\tty{EA+HL}, \tty{(H+EA)}, \tty{(HL+EA)}, \tty{(EA+H)}
oder \tty{(EA+HL)} geschrieben werden.}
\end{itemize}
Da Architektur und Befehlssatz so ,,8080-artig''
sind, lag es auch nahe, den Schalter {\tt Z80SYNTAX} zu
unterst"utzen, so da"s sich viele Befehle in einer eing"angigeren
und vertrauteren Art und Weise schreiben lassen. Da die
Architektur und der Original-Befehlssatz der uCOM87-Familie
sich jedoch in einigen Punkten von 8080 unterscheiden, ist hier
keine eins-zu-eins Abbildung m"oglich: Nicht alle Originalbefehle
haben ein ,,Z80-"Aquivalent'', und einge vom 8080/Z80 bekannten
Befehle haben kein Pendant beim uCOM87. Deshalb ergibt ein
{\tt Z80SYNTAX EXCLUSIVE} hier auch keinen Sinn.
Die folgende Tabelle listet alle im {\tt Z80SYNTAX}-Modus
definierten Befehle und ihre "Aquivalente in der Original-Syntax:
\begin{longtable}{|l|l|l|l|}
{\tt Z80SYNTAX} & Original & Operation & CPUs \\
\endhead
\input{../doc_COM/78z80inst.tex}
\multicolumn{4}{|l|}{CPU-Gruppe 1: 78C05, 78C06} \\
\multicolumn{4}{|l|}{CPU-Gruppe 2: 7800, 7801, 7802} \\
\multicolumn{4}{|l|}{CPU-Gruppe 3: 7807, 7808, 7809, 7810} \\
\multicolumn{4}{|l|}{CPU-Gruppe 4: 7810, 78C1x} \\
\caption{Befehlsvarianten im {\tt Z80SYNTAX}-Modus}
\end{longtable}
%%---------------------------------------------------------------------------
Wie bei einigen anderen Prozessoren auch, kennt die Assemblersprache
der 75er von NEC Pseudo-Bitoperanden, d.h. man kann einem Symbol
eine Kombination aus Adresse und Bitnummer zuweisen, die dann bei
bitorientierten Befehlen anstelle direkter Ausdr"ucke verwendet werden
kann. Die drei folgenden Befehle erzeugen daher z.B. identischen
Code:
\begin{verbatim}
ADM sfr 0fd8h
SOC bit ADM.3
skt 0fd8h.3
skt ADM.3
skt SOC
\end{verbatim}
\asname{} unterscheidet direkte und symbolische Bitzugriffe an einem
bei Symbolen fehlenden Punkt; Punkte in Symbolnamen darf man daher
nicht verwenden, da es sonst zu Mi"sverst"andnissen bei der Aufl"osung
kommt.
Die Ablage von Bitsymbolen orientiert sich dabei weitgehend an der
bin"aren Kodierung, die die Prozessorhardware selber verwendet: Es
werden 16 Bit belegt, und es existieren ein ,,kurzes'' und ein ,,langes''
Format. Das kurze Format kann folgende Varianten aufnehmen:
\begin{itemize}
\item{direkte Zugriffe auf die Bereiche 0FBxH und 0FFxH}
\item{indirekte Zugriffe der Form Adr.@L (0FC0H $\leq$ \tty{Adr} $\leq$ 0FFFH)}
\item{indirekte Zugriffe der Form @H+d4.bit}
\end{itemize}
Das obere Byte ist auf 0 gesetzt, das untere Byte enth"alt den gem"a"s
\cite{NEC75} kodierten Bitausdruck. Das lange Format kennt im Gegensatz
dazu nur direkte Adressierung, kann daf"ur aber (korrekte Einstellungen
von \tty{MBS} und \tty{MBE} vorausgesetzt) den ganzen Adre"sraum abdecken.
Bei langen Ausdr"ucken stehen im unteren Byte Bit 7..0 der Adresse, in
Bit 8 und 9 die Bitstelle sowie in Bit 10 und 11 konstant 01. Letztere
erm"oglichen es, langes und kurzes Format einfach durch einen Vergleich
des oberen Bytes gegen Null zu unterscheiden. Die Bits 12..15 enthalten
Bit 8..11 der Adresse; sie werden zwar nicht zur Generierung des Kodes
ben"otigt, m"ussen jedoch gespeichert werden, da eine Pr"ufung auf ein
korrektes Banking erst bei der Verwendung des Symboles erfolgen kann.
%%---------------------------------------------------------------------------
NEC benutzt in seinen Datenb"uchern zur Kennzeichnung der Zugriffsweise
auf absolute Adressen verschiedene Schreibweisen:
\begin{itemize}
\item{absolut kurz: kein Pr"afix}
\item{absolut lang: vorangestelltes \verb"!"}
\item{PC-relativ: vorangestelltes \verb"$"}
\end{itemize}
Bei \asname{} sind diese Pr"afixe nur notwendig, falls man eine bestimmte
Adressierung erzwingen will und der Befehl verschiedene Varianten
zul"a"st. Setzt man keinen Pr"afix, so w"ahlt \asname{} automatisch die
k"urzeste Variante. Es d"urfte daher in der Praxis sehr selten
notwendig sein, einen Pr"afix zu verwenden.
%%---------------------------------------------------------------------------
Analog wie beim 78K0 benutzt NEC auch hier wieder Dollar- und
Ausrufezeichen f"ur verschiedene L"angen von Adre"sausdr"ucken.
Zwischen langen und kurzen Adressen (sowohl im RAM- als auch
SFR-Bereich) wird wieder automatisch entschieden, nur relative
Adressierung mu"s man manuell anw"ahlen, wenn ein Befehl beides
unterst"utzt (z.B. {\tt BR}).
Noch eine Anmerkung (die im "ubrigens auch f"ur den 78K0 gilt): Wer
mittels {\tt RELAXED} mit Motorola-Syntax arbeitet, mu"s
Hexadezimalkonstanten klammern, weil das f"uhrende Dollarzeichen u.U. als
relative Adressierung mi"sverstanden wird...
%%---------------------------------------------------------------------------
Sowohl 7720 als auch 7725 werden von dem gleichen Codegenerator behandelt
und sind sich in ihren Befehlssatz extrem "ahnlich. Trotzdem sollte man
sich nicht zu der Annahme verleiten lassen, sie seien bin"ar kompatibel:
Um die l"angeren Adre"sfelder und zus"atzlichen Befehle unterbringen zu
k"onnen, haben sich die Bitpositionen einiger Felder im Instruktionswort
verschoben, die Instruktionsl"ange hat sich auch insgesamt von 23 auf 24
Bit ge"andert. Im Code-Format sind deshalb auch unterschiedliche
Header-Ids f"ur beide reserviert.
Gemeinsam ist beiden, da"s sie neben Code- und Datensegment auch noch ein
ROM zur Ablage von Konstanten besitzen. Dieses ist bei \asname{} auf das
\tty{ROMDATA}-Segment abgebildet!
%%---------------------------------------------------------------------------
Darauf, da"s man bei Anwendungen mit mehr als 64K ROM oder 64K RAM darauf
achten sollte, \asname{} die korrekte momentane Belegung der Bank-Register
mitzuteilen, wurde bereits in Zusammenhang mit dem {\tt ASSUME}-Befehl
erw"ahnt. \asname{} "uberpr"uft bei jedem absoluten Zugriff anhand dieser
Annahmen, ob evtl. ein Zugriff auf eine Speicherstelle erfolgt, die
momentan "uberhaupt nicht greifbar ist. Standardm"a"sig sind daf"ur
nat"urlich nur DTB und DPR wichtig, denn ADB bzw. SSB/USB werden nur bei
indirekten Zugriffen "uber RW2/RW6 bzw. RW3/RW7 benutzt, und bei
indirekten Zugriffen greift diese Pr"ufmimik ohnehin nicht. Nun ist es
aber so, da"s man - "ahnlich wie beim 8086 - einem Befehl eine
Segmentpr"afix voranstellen kann, mit dem DTB f"ur den folgenden Befehl
durch ein beliebiges anderes Register ersetzt werden kann. \asname{} f"uhrt
deswegen "uber die verwendeten Pr"afixbefehle Buch und schaltet bei der
Pr"ufung f"ur den n"achsten {\em Prozessorbefehl} um - eine zwischen dem
Segmentpr"afix und Prozessorbefehl eingestreute Pseudoanweisung l"oscht
den Merker also {\em nicht}. Dies gilt auch f"ur Pseudobefehle zur
Datenablage oder Ver"anderung des Programmz"ahlers - aber wer macht so
etwas schon ;-)
%%---------------------------------------------------------------------------
F"ur dieses Target gilt die Besonderheit, da"s man zwischen zwei
Code-Generatoren w"ahlen kann: Einer wurde freundlicherweise von Haruo Asano
geschrieben und ist "uber die CPU-Namen \tty{MN1610} bzw. \tty{MN1613}
erreichbar; der andere wurde von mir erstellt und ist "uber die Namen
\tty{MN1610ALT} bzw. \tty{MN1613ALT} aktivierbar. Wer den erweiterten
Adre"sraum von 256 KWorten des MN1613 verwenden will, oder mit dem
Gleitkommaformat des MN1613 experimentieren will, mu"s das \tty{ALT}-
Target verwenden.
%%---------------------------------------------------------------------------
Prozessoren dieser Reihe kennen sowohl kurze als auch lange Sprungbefehle:
W"ahrend ein kurzer Sprung nur innerhalb der gleichen Speicherseite von 256 Byte
m"oglich ist, kann man mit einem langen Sprung jedes beliebige Ziel im
Adre"sraum von 64 KByte erreichen. Die Assembler-Syntax sieht f"ur beide
Varianten unterschiedliche Mnemonics vor (die lange Variante mit vorangestelltem
'L'), aber keine, die dem Assembler gestatten w"urde, automatisch einen langen
oder kurzen Befehl einzusetzen. \asname{} kennt solche 'Pseudobehle' als Erweiterung:
\begin{itemize}
\item{\tty{JMP} wird zu \tty{BR} oder \tty{LBR}.}
\item{\tty{JZ} wird zu \tty{BZ} oder \tty{LBZ}.}
\item{\tty{JNZ} wird zu \tty{BNZ} oder \tty{LBNZ}.}
\item{\tty{JDF} wird zu \tty{BDF} oder \tty{LBDF}.}
\item{\tty{JPZ} wird zu \tty{BPZ} oder \tty{LBPZ}.}
\item{\tty{JGE} wird zu \tty{BGE} oder \tty{LBGE}.}
\item{\tty{JNF} wird zu \tty{BNF} oder \tty{LBNF}.}
\item{\tty{JM} wird zu \tty{BM} oder \tty{LBM}.}
\item{\tty{JL} wird zu \tty{BL} oder \tty{LBL}.}
\item{\tty{JQ} wird zu \tty{BQ} oder \tty{LBQ}.}
\item{\tty{JNQ} wird zu \tty{BNQ} oder \tty{LBNQ}.}
\end{itemize}
%%---------------------------------------------------------------------------
Der KENBAK-1 wurde 1970 entwickelt, zu einer Zeit, als der erste
Mikroprozessor noch drei Jahre entfernt war. Man kann davon ausgehen, da"s
er f"ur die Hobbyisten, die sich den Bausatz seinerzeit leisten konnten, ihr
erster und einziger Computer war. Demzufolge hatten sie auch nichts, auf
dem sie einen Assembler f"ur diesen Computer h"atten laufen lassen k"onnen -
der KENBAK-1 mit seinem Speicher von 256 Byte war daf"ur viel zu klein. Die
pr"aferierte Methode waren vorgedruckte Tabellen, in die man die Befehle und
ihren Maschinencode eintrug. War man mit dieser ,,Programmierung'' fertig,
konnte man den Code "uber die Schalterleiste per Hand in den Computer laden.
Daraus resultiert leider, da"s die Assembler-Sprache des KENBAK zwar im
Programming Manual beschrieben, aber nicht wirklich formal definiert ist. Als
Grant Stockly vor ein paar Jahren neue KENBAK-Kits herausbrachte, hat er
eine erste KENBAK-Portierung f"ur meinen Assembler gemacht, die hat ihren
Weg jedoch leider nie wieder ''upstream'' gefunden. In meiner Implementierung
habe ich versucht, seine Ideen aufzugreifen, jedoch andererseits auch eine
Syntax anzubieten, wie sie Programmierern eines 6502, Z80 oder "ahnlichem
eher vertraut sein d"urfte. In der folgenden Tabelle sind die Syntax-Unterschiede
gegen"uber gestellt:
\hfuzz=5pt
\begin{center}\begin{longtable}{|l|l|l|}
Stockly & Alternativ & Bemerkung \\
\endhead
\multicolumn{3}{|l|}{\bf Arithmetisch/Logisch (ADD/SUB/LOAD/STORE/AND/OR/LNEG)} \\
{\it instr} {\tt Constant}, {\it Reg}, {\it Wert}, & {\it instr} {\it Reg}, {\it \#Wert} & immediate \\
{\it instr} {\tt Memory}, {\it Reg}, {\it Addr}, & {\it instr} {\it Reg}, {\it Addr} & direkt \\
{\it instr} {\tt Indirect}, {\it Reg}, {\it Addr}, & {\it instr} {\it Reg}, {\it (Addr)} & direkt \\
{\it instr} {\tt Indexed}, {\it Reg}, {\it Addr}, & {\it instr} {\it Reg}, {\it Addr},X & indiziert \\
{\it instr} {\tt Indirect-Indexed}, {\it Reg}, {\it Addr}, & {\it instr} {\it Reg}, {\it (Addr)},X & indirekt-indiziert \\
\multicolumn{3}{|l|}{\bf Spr"unge} \\
{\tt JPD} {\it Reg}, {\it Cond}, {\it Addr} & {\tt JP} {\it Reg}, {\it Cond}, {\it Addr} & bedingt-direkt \\
{\tt JPI} {\it Reg}, {\it Cond}, {\it Addr} & {\tt JP} {\it Reg}, {\it Cond}, {\it (Addr)} & bedingt-indirekt \\
{\tt JMD} {\it Reg}, {\it Cond}, {\it Addr} & {\tt JM} {\it Reg}, {\it Cond}, {\it Addr} & bedingt-direkt \\
{\tt JMI} {\it Reg}, {\it Cond}, {\it Addr} & {\tt JM} {\it Reg}, {\it Cond}, {\it (Addr)} & bedingt-indirekt \\
{\tt JPD} {\tt Unconditional}, {\it Cond}, {\it Addr} & {\tt JP} {\it Addr} & unbedingt-direkt \\
{\tt JPI} {\tt Unconditional}, {\it Cond}, {\it Addr} & {\tt JP} {\it (Addr)} & unbedingt-indirekt \\
{\tt JMD} {\tt Unconditional}, {\it Cond}, {\it Addr} & {\tt JM} {\it Addr} & unbedingt-direkt \\
{\tt JMI} {\tt Unconditional}, {\it Cond}, {\it Addr} & {\tt JM} {\it (Addr)} & unbedingt-indirekt \\
\multicolumn{3}{|l|}{\bf Sprungbedingungen} \\
{\tt Non-zero} & {\tt NZ} & $\neq 0$ \\
{\tt Zero} & {\tt Z} & $= 0$ \\
{\tt Negative} & {\tt N} & $< 0$ \\
{\tt Positive} & {\tt P} & $\geq 0$ \\
{\tt Positve-Non-zero} & {\tt PNZ} & $ > 0$ \\
\multicolumn{3}{|l|}{\bf Skips} \\
{\tt SKP 0}, {\it bit}, {\it Addr} & {\tt SKP0} {\it bit}, {\it Addr} {\it [,Dest]} & \\
{\tt SKP 1}, {\it bit}, {\it Addr} & {\tt SKP1} {\it bit}, {\it Addr} {\it [,Dest]} & \\
\multicolumn{3}{|l|}{\bf Bitmanipulation} \\
{\tt SET 0}, {\it bit}, {\it Addr} & {\tt SET0} {\it bit}, {\it Addr} & \\
{\tt SET 1}, {\it bit}, {\it Addr} & {\tt SET1} {\it bit}, {\it Addr} & \\
\multicolumn{3}{|l|}{\bf Schiebe/Rotierbefehle} \\
{\tt SHIFT LEFT}, {\it cnt}, {\it Reg} & {\tt SFTL} {\it [cnt,]} {\it Reg} & \\
{\tt SHIFT RIGHT}, {\it cnt}, {\it Reg} & {\tt SFTR} {\it [cnt,]} {\it Reg} & arithm. Shift \\
{\tt ROTATE LEFT}, {\it cnt}, {\it Reg} & {\tt ROTL} {\it [cnt,]} {\it Reg} & \\
{\tt ROTATE RIGHT}, {\it cnt}, {\it Reg} & {\tt ROTR} {\it [cnt,]} {\it Reg} & \\
\end{longtable}\end{center}
\hfuzz=0pt
Es gibt keinen Pseudobefehl, um zwischen diesen beiden Syntax-Varianten umzuschalten.
Beide d"urfen jederzeit und auch in beliebiger Mischung genutzt werden.
Die Zieladresse {\it [Dest]}, die man optional bei den Skip-Befehlen angeben
kann, geht nicht in den erzeugten Code ein. Der Assembler "uberpr"uft lediglich,
ob der Prozessor zur Laufzeit wirklich zur angegebene Adresse springen w"urde.
Dadurch kann z.B. gepr"uft werden, ob man nicht versehentlich versucht, einen
einzelnen Ein-Byte-Befehl zu "uberspringen. Ein weggelassenes Schiebeargument
{\it [cnt]} bedeutet, da"s um eine Stelle geschoben werden soll.
%%---------------------------------------------------------------------------
Der HP Nanoprocessor verf"ugt "uber keinerlei Befehle, Daten aus dem ROM-
Adre"sraum zu lesen und in ein Register zu transferieren. Die diesbez"uglichen
Befehle {\tt LDR} und {\tt STR} sind eher das, was man bei anderen Prozessoren
als ,,immediate-Adressierung'' bezeichnen w"urde. Aus diesen Grund sind f"ur
den HP Nanoprocessor keinerlei Pseudobefehen definiert, mit denen sich Konstanten
im ROM ablegen oder Platz reservieren l"a"st.
%%---------------------------------------------------------------------------
Dieser Mikroprozessor ist quasi eine Single-Chip-Implementierung einer PDP/8E,
weshalb als ,,Assembler-Referenz'' in Quellcode-Beispielen "ublicherweise der
PAL-III von Digital Equipment benutzt wird. Die \asname{}-Implementierung weicht in
einigen Punkten von der PAL-III-Syntax ab, unter anderem auch, weil sich manche
Dinge nur mit gro"sem Aufwand h"atten bereit stellen lassen. Hier einige Hinweise,
wie sich bestehender Code anpassen l"a"st:
\begin{itemize}
\item{Bei PAL-III werden Label durch ein angeh"angtes Komma gekennzeichnet.
Bei \asname{} ist diese ein Doppelpunkt, bzw. gar nichts, wenn das Label in der
ersten Spalte beginnt.}
\item{Die Ablage von Daten im Speicher erfolgt bei PAL-III einfach dadurch,
da"s man die Konstante in das Feld des Mnemonics schreibt. \asname{} verwendet
zur Datenablage die \tty{DC}-Anweisung, die daf"ur auch mehrere Worte
auf einmal als Argument akzeptiert. Unter Umst"anden kann man sich
die Ablage von Konstanten durch den \tty{LTORG}-Mechanismus aber auch
teilweise ersparen.}
\item{Den Programmz"ahler setzt man mit \tty{ORG address} anstelle {*address}.}
\end{itemize}
%%===========================================================================
\cleardoublepage
In diesem Kapitel sollen die Formate von von \asname{} erzeugten Dateien
beschrieben werden, deren Format sich nicht direkt erschlie"st.
Das vom Assembler ausgegebene Codedatenformat mu"s in der Lage sein,
die Codeteile f"ur unterschiedliche Prozessoren voneinander zu trennen,
und sieht daher etwas anders aus als g"angige Formate. Obwohl dem
Assembler Tools zur Bearbeitung der Codedateien beiliegen, halte ich es
f"ur guten Stil, das Format hier kurz offenzulegen:
Sofern in der Datei Mehrbyte-Integers gespeichert sind, werden sie
im Intelformat abgelegt, d.h. mit dem LSB zuerst. Diese Regel gilt
bereits f"ur das 16-Bit-Kennungswort mit dem Wert \$1489, d.h. jede
Codedatei beginnt mit den Bytes \$89/\$14.
Danach folgt eine Reihe beliebig vieler ,,Records'', wobei ein Record
entweder ein zusammenh"angendes Teilfeld des Codes darstellt oder bestimmte
Zusatzinformationen enth"alt. Eine Datei
kann auch ohne Umschaltung des Prozessortyps mehrere Records enthalten,
wenn Code- oder Konstantenbereiche durch reservierte (und nicht zu
initialisierende) Speicherbereiche unterbrochen werden. Der Assembler
versucht auf diese Weise, die Datei nicht l"anger als n"otig werden
zu lassen.
Allen Records ist gemein ist ein Header-Byte, das den Typ des Records
und die damit folgenden Datenstrukturen festlegt. In einer Pascal-artigen
Form l"a"st sich die Record-Struktur folgenderma"sen beschreiben:
\begin{verbatim}
FileRecord = RECORD CASE Header:Byte OF
$00:(Creator:ARRAY[] OF Char);
$01..
$7f:(StartAdr : LongInt;
Length : Word;
Data : ARRAY[0..Length-1] OF Byte);
$80:(EntryPoint:LongInt);
$81:(Header : Byte;
Segment : Byte;
Gran : Byte;
StartAdr : LongInt;
Length : Word;
Data : ARRAY[0..Length-1] OF Byte);
END
\end{verbatim}
Was in dieser Schreibweise nicht ganz zum Ausdruck kommt, ist, da"s
die L"ange von Datenfeldern variabel ist und von {\tt Length} abh"angt.
Ein Record mit einem Header-Byte von \verb!$81! ist ein Record, der Code
oder Daten aus beliebigen Segmenten beinhalten kann. Das erste
Byte (Header) gibt an, f"ur welche Prozessorfamilie die folgenden
Daten bzw. der folgende Code bestimmt ist (siehe Tabelle \ref{TabHeader}).
\begin{center}\begin{longtable}{|c|l||c|l|}
Header & Familie & Header & Familie \\
\endhead
\input{../doc_COM/tabids.tex}
\caption{Headerbytes f"ur die verschiedenen Prozessorfamilien}
\end{longtable}\end{center}
Das Segment-Feld gibt an, in welchen Adre"sraum des Prozessors der
folgende Code geh"ort. Dabei gilt die in Tabelle \ref{TabSegments}
angegeben Zuordnung.
\begin{table*}[htbp]
\begin{center}\begin{tabular}{|c|l||c|l|}
Nummer & Segment & Nummer & Segment \\
\$00 & $<$undefiniert$>$ & \$01 & CODE \\
\$02 & DATA & \$03 & IDATA \\
\$04 & XDATA & \$05 & YDATA \\
\$06 & BDATA & \$07 & IO \\
\$08 & REG & \$09 & ROMDATA \\
\end{tabular}\end{center}
\caption{Kodierungen des {\tt Segment}-Feldes\label{TabSegments}
\end{table*}
Das Gran-Feld gibt die ,,Granularit"at'' des Codes an, d.h. die Gr"o"se
der kleinsten, adressierbaren Einheit im folgenden Datensatz. Dieser
Wert ist eine Funktion von Prozessortyp und Segment und ein wichtiges
Detail f"ur die Interpretation der beiden folgenden Felder, die
Startadresse und L"ange angeben: W"ahrend die Startadresse sich auf die
Granularit"at bezieht, erfolgt die L"angenangabe immer in Bytes! W"are
die Startadresse z.B. \$300 und die L"ange 12, so w"are die sich
ergebende Endadresse bei einer Granularit"at von 1 \$30b, bei einer
Granularit"at von z.B. 4 jedoch \$303! Andere Granularit"aten als eins
sind selten und treten in erster Linie bei Signalprozessoren auf, die
nicht auf Einzelbyteverarbeitung ausgelegt sind deren Datenspeicher z.B.
aus 64kWorten zu 16 Bit besteht (DSP56K). Der sich ergebende Speicherplatz
betr"agt dann zwar 128 KByte, er ist aber in $2^{16}$ Worten organisiert,
die mit Adressen von 0,1,2,...65535 adressiert werden!
Die Startadresse ist 32-bittig, unabh"angig von der Adre"sbreite der
jeweiligen Prozessorfamilie. Im Gegensatz dazu ist die L"angenangabe
nur 16 Bit lang, ein Record kann also maximal (4+4+2+(64K-1)) = 65545
Byte lang werden.
Daten-Records mit den Header-Bytes \verb!$01..$7f! stellen eine
Kurzschreibweise dar und stellen die Abw"artskompatibilit"at mit fr"uheren
Definitionen des Dateiformats her: Das Header-Byte gibt direkt den
Prozessortyp gem"a"s der ersten Tabelle an, das Zielsegment ist auf \tty{CODE}
festgelegt und die Granularit"at ergibt sich aus dem Prozessortyp,
aufgerundet auf eine Zweierpotenz von Bytes. \asname{} bevorzugt diese Records,
wenn Daten bzw. Code f"ur das \tty{CODE}-Segment anstehen.
Der Record mit dem Typ-Byte \verb!$80! legt den Einsprungpunkt fest, d.h.
die Adresse, an der mit der Ausf"uhrung des Programms begonnen werden
soll. Ein solcher Record ist das Ergebnis einer \tty{END}-Anweisung mit
einer entsprechenden Adresse als Argument.
Der letzte Record in der Datei tr"agt das Header-Byte \verb!$00! und besitzt
als einziges Datenfeld einen String, dessen Ende durch das Dateiende
definiert ist. Dieser String spezifiziert, von welchem Programm diese
Datei erzeugt wurde und hat keine weitere Bedeutung.
Debug-Dateien k"onnen optional von \asname{} erzeugt werden und liefern
nachgeschalteten Werkzeugen wie Disassemblern oder Debuggern f"ur diese
wichtige Informationen. \asname{} kann Debug-Informationen in drei Formaten
ausgeben: Zum einen im Objekt-Format der AVR-Tools von Atmel sowie eine zu
NoICE kompatible Kommandodatei und zum anderen in einem eigenen Format.
Die ersten beiden werden in \cite{AVRObj} bzw. der Dokumentation zu
NoICE ausf"uhrlich beschrieben, deshalb beschr"ankt sich die folgende
Beschreibung auf das \asname{}-eigene MAP-Format:
Diese Informationen in einer MAP-Datei teilen sich in drei Gruppen:
\begin{itemize}
\item{Speicherberlegung, auf Sektionen verteilt}
\item{Maschinenadressen von Quellzeilen}
\end{itemize}
Letzterer Teil findet sich zuerst in der Datei. Ein einzelner
Eintrag in dieser Liste besteht aus zwei, von einem Doppelpunkt
getrennten Zahlen:
\begin{verbatim}
<Zeilennummer>:<Adresse>
\end{verbatim}
Ein solcher Eintrag besagt, da"s der aus einer bestimmten
Quellcodezeile erzeugte Maschinencode auf der angegebenen Adresse
(hexadezimal) zu liegen kam. Mit einer solchen Information kann ein
Debugger beim Durchsteppen des Programms die entsprechenden
Quellcodezeilen anzeigen. Da ein Programm aber auch aus mehreren
Include-Dateien bestehen kann, und viele Prozessoren mehr als nur
einen Adre"sraum besitzen (von dem zugegebenerma"sen nur in einem Code
liegt), m"ussen die oben beschriebenen Eintr"age sortiert werden. \asname{}
tut dies in zwei Stufen: Das prim"are Sortierkriterium ist das
Zielsegment, innerhalb dieser Segmente wird noch einmal nach Dateien
sortiert. Einzelne Abschnitte werden dabei durch durch spezielle
Zeilen der Form
\begin{verbatim}
Segment <Segmentname>
\end{verbatim}
bzw.
\begin{verbatim}
File <Dateiname>
\end{verbatim}
getrennt.
Die Symboltabelle folgt der Quellzeileninformation und ist wieder
prim"ar nach den Segmenten geordnet, aus denen die Symbole stammen.
Im Gegensatz zur Zeileninformation kommt hier allerdings auch der
Abschnitt \tty{NOTHING} hinzu, der die Symbole beinhaltet, die keinem
speziellen Adre"sraum zugeordnet sind (z.B. Symbole, die einfach mit
\tty{EQU} definiert wurden). Die Einleitung eines Abschnittes in der
Symboltabelle erfolgt mit einer Zeile der Form
\begin{verbatim}
Symbols in Segment <Segmentname> .
\end{verbatim}
Innerhalb eines Abschnittes sind die Symbole nach Namen sortiert, und
ein Symboleintrag belegt genau eine Zeile. Eine solche Zeile besteht
wiederum aus sechs Feldern, die durch jeweils mindestens ein Leerzeichen
getrennt sind:
Das erste Feld ist der Name des Symbols selber, eventuell erweitert
um eine in eckigen Klammern eingeschlossene Sektionsnummer, die den
G"ultigkeitsbereich des Symbols einschr"ankt. Die zweite Spalte
bezeichnet den Typ des Symbols: \tty{Int} f"ur Integerzahlen, \tty{Float} f"ur
Gleitkommazahlen und \tty{String} f"ur Zeichenketten. Die dritte Zeile
schlie"slich beinhaltet den eigentliche Wert des Symbols. Falls das
Symbol eine Zeichenkette beinhaltet, ist es notwendig, Steuer- und
Leerzeichen mit einer gesonderten Notation zu kennzeichnen, damit ein
im String enthaltenes Leerzeichen nicht eventuell als Trennzeichen
zur n"achsten Spalte interpretiert werden kann. \asname{} bedient sich dazu
der bereits der in Assemblerquellen "ublichen Schreibweise, den
ASCII-Zahlenwert mit einem f"uhrenden Backslash (\verb!\!) einzusetzen. Aus
dem String
\begin{verbatim}
Dies ist ein Test
\end{verbatim}
wird also z.B.
\begin{verbatim}
Dies\032ist\032ein\032Test
\end{verbatim}
Die Zahlenangabe ist immer dezimal und dreistellig, und der Backslash
selber wird ebenfalls in dieser Schreibweise kodiert.
Das vierte Feld gibt - falls vorhanden - die Gr"o"se der Datenstruktur
an, die an der durch das Symbol gekennzeichneten Adresse abgelegt
ist. Ein Debugger kann eine solche Information z.B. nutzen, um
symbolisch angesprochene Variablen direkt in der korrekten L"ange
aufzulisten. Hat \asname{} keine Informationen "uber die Symbolgr"o"se, so
steht in diesem Feld eine schlichte -1.
Das f"unfte und letzte Feld gibt an, ob das Symbol w"ahrend der
Assemblierung jemals referenziert wurde. Ein Programm, da"s die
Symboltabelle liest, kann auf diese Weise z.B. nicht benutzte Symbole
automatisch verwerfen, da sie beim folgenden Debugging oder der
Disassemblierung mit hoher Wahrscheinlichkeit auch nicht ben"otigt werden.
das sechste und letzte Feld gibt schlu"sendlich durch eine 0 oder 1 an,
ob es sich bei dem Symbol um eine Konstante (0) oder Variable (1) handelt.
Konstanten bekommen einmalig einen Wert zugewiesen (z.B. "uber die
\tty{EQU}-Anweisung oder ein Label), Variablen k"onnen ihren Wert beliebig
oft "andern. In der MAP-Datei wird der letztg"ultige Wert aufgef"uhrt.
Der dritte Abschnitt in einer Debug-Datei beschreibt die im Programm
benutzten Sektionen n"aher. Eine solche Beschreibung ist erforderlich,
da Sektionen den G"ultigkeitsbereich von Symbolen einschr"anken
k"onnen. Je nach momentanem Stand des Programmz"ahlers kann z.B. ein
symbolischer Debugger einzelne Symboldefinitionen f"ur eine R"uck"ubersetzung
nicht nutzen oder mu"s Priorit"aten bei der Symbolnutzung beachten.
Die Definition einer Sektion beginnt mit einer Zeile der Form
\begin{verbatim}
Info for Section nn ssss pp ,
\end{verbatim}
wobei \tty{nn} die Nummer der Sektion angibt (die Nummer, die als Postfix
f"ur Symbolnamen in der Symboltabelle genutzt wird), \tty{ssss} der Name der
Sektion ist und \tty{pp} die Nummer der Vatersektion darstellt. Letztere
Information ben"otigt ein R"uck"ubersetzer, um sich bei der Auffindung
eines Symbols f"ur einen Zahlenwert ausgehend von der aktuellen Sektion
im Baum bis zur Wurzel ,,durchhangeln'' kann, bis ein passendes
Symbol gefunden wird. Auf diese Zeile folgt eine Reihe weiterer
Zeilen, die den von dieser Sektion belegten Code-Bereich beschreiben.
Jeder einzelne Eintrag (genau einer pro Zeile) beschreibt entweder
eine einzelne Adresse oder einen durch zwei Grenzwerte beschriebenen
Bereich (Trennung von Anfangs-und Endwert durch ein Minuszeichen).
Die Grenzen sind dabei ,,inklusive'', d.h. die Grenzen geh"oren auch zu
dem Bereich. Wichtig ist, da"s ein einer Sektion zugeh"origer Bereich
nicht nochmals f"ur ihre Vatersektionen aufgef"uhrt wird (eine Ausnahme
ist nat"urlich, wenn Bereiche absichtlich mehrfach belegt werden, aber
so etwas macht man ja auch nicht, gelle?). Dies dient einer Optimierung
der Bereichsspeicherung w"ahrend der Assemblierung und sollte auch
f"ur eine Symbolr"uck"ubersetzung keine Probleme darstellen, da durch
die einfache Kennzeichnung bereits der Einstiegspunkt und damit der
Suchpfad im Sektionsbaum gegeben ist. Die Beschreibung einer Sektion
wird durch eine Leerzeile oder das Dateiende gekennzeichnet.
Programmteile, die au"serhalb aller Sektionen liegen, werden nicht
gesondert ausgewiesen. Diese ,,implizite Wurzelsektion'' tr"agt die
Nummer -1 und wird auch als Vatersektion f"ur Sektionen benutzt, die
keine eigentliche Vatersektion besitzen.
Es ist m"oglich, da"s die Datei Leerzeilen oder Kommentarzeilen
(Semikolon am Zeilenanfang) beinhaltet. Diese sind von einem
Leseprogramm zu ignorieren.
%%===========================================================================
\cleardoublepage
Um die Arbeit mit dem Codeformat des Assemblers etwas zu erleichtern,
lege ich einige Progamme zu deren Bearbeitung bei. F"ur diese Programme
gilt sinngem"a"s das gleiche wie in \ref{SectLicense}!
Allen Programmen gemeinsam sind die Returncodes, die sie liefern (Tabelle
\begin{table*}[ht]
\begin{center}\begin{tabular}{|c|l|}
Returncode & tritt auf bei... \\
0 & kein Fehler \\
1 & Kommandozeilenparameterfehler \\
2 & I/O-Fehler \\
3 & Dateiformatfehler \\
\end{tabular}\end{center}
\caption{Returncodes der Dienstprogramme\label{TabToolReturns}}
\end{table*}
Ebenso eintr"achtig wie \asname{} lesen sie ihre Eingaben von STDIN und schreiben
Meldungen auf STDOUT (bzw. Fehlermeldungen auf STDERR). Ein-und
Ausgaben sollten sich daher problemlos umleiten lassen.
Sofern Programme im folgenden Zahlen-oder Adre"sangaben von der
Kommandozeile lesen, d"urfen diese auch hexadezimal geschrieben werden,
indem man sie mit einem hintangestellten \tty{h}, einem voranstehenden
Dollarzeichen oder \tty{0x} wie in C versieht (z.B. \verb!$10!,
\verb!10h! oder \verb!0x10! anstelle von 16).
Unix-Shells \marginpar{{\em UNIX}} ordnen dem Dollarzeichen allerdings
eine spezielle Bedeutung zu (Parameterexpansion), weshalb es n"otig ist,
einem Dollarzeichen direkt einen Backslash voranzustellen. Die
\tty{0x}-Variante ist hier sicherlich angenehmer.
Ansonsten folgen die Aufrufkonventionen und -variationen (bis auf PLIST
und AS2MSG) denen von \asname{}, d.h. man kann dauernd gebrauchte Schalter in
einer Environmentvariablen ablegen (deren Name sich aus dem Anh"angen von
CMD an den Programmnamen ergibt, z.B. BINDCMD f"ur BIND), Optionen
negieren und Gro"s-bzw. Kleinschreibung erzwingen (n"aheres zu dem Wie in
Abschnitt \ref{SectCallConvention}).
Sofern Adre"sangaben benutzt werden, beziehen sie sich immer auf die
Granularit"at des Adre"sraumes des jeweiligen Prozessors; beim PIC bedeutet
z.B. eine Adre"sdifferenz von 1 nicht ein Byte, sondern ein Wort.
%%---------------------------------------------------------------------------
PLIST ist das einfachste Programm der vier mitgelieferten; es dient
einfach nur dazu, die in einer Codedatei gespeicherten Records aufzulisten.
Da das Programm nicht allzuviel bewirkt, ist der Aufruf ziemlich simpel:
\begin{verbatim}
PLIST $<$Dateiname$>$
\end{verbatim}
Der Dateiname wird automatisch um die Endung P erweitert, falls keine
Endung vorhanden ist.
\bb{ACHTUNG!} An dieser Stelle sind keine Jokerzeichen erlaubt! Falls mit
einem Befehl trotzdem mehrere Programmdateien gelistet werden sollen,
kann man sich mit folgendem ''Minibatch'' behelfen:
\begin{verbatim}
for %n in (*.p) do plist %n
\end{verbatim}
PLIST gibt den Inhalt der Codedatei in Tabellenform aus, wobei f"ur
jeden Record genau eine Zeile ausgegeben wird. Die Spalten haben
dabei folgende Bedeutung:
\begin{itemize}
\item{Codetyp: die Prozessorfamilie, f"ur die der Code erzeugt wurde.}
\item{Startadresse: absolute Speicheradresse, an die der Code zu laden ist.}
\item{L"ange: L"ange des Codest"ucks in Byte.}
\item{Endadresse: letzte absolute Adresse des Codest"ucks. Diese berechnet
sich als Startadresse+L"ange-1.}
\end{itemize}
Alle Angaben sind als hexadezimal zu verstehen.
Zuletzt gibt PLIST noch einen Copyrightvermerk aus, sofern er einen
solchen in der Datei findet, und die Summe aller Codel"angen.
PLIST ist praktisch ein DIR f"ur Codedateien. Man kann es benutzen,
um sich den Inhalt einer Datei auflisten zu lassen, bevor man sie
weiterbearbeitet.
%%---------------------------------------------------------------------------
BIND ist ein Programm, mit dem man die Records mehrerer Codedateien
in eine Datei zusammenkopieren kann. Die dabei vorhandene Filterfunktion
erlaubt es aber auch, nur Records eines bestimmten Typs zu "ubernehmen.
Auf diese Weise kann BIND auch dazu verwendet werden, um eine Codedatei
in mehrere aufzuspalten.
Die allgemeine Syntax von BIND lautet
\begin{verbatim}
BIND <Quelldatei(en)> <Zieldatei> [Optionen]
\end{verbatim}
Wie auch \asname{} betrachtet BIND alle nicht mit einem +, - oder / eingeleiteten
Parameter als Dateiangaben, von denen die letzte die Zieldatei angeben
mu"s. Alle anderen Dateiangaben bezeichnen Quellen, diese Angaben d"urfen
auch wieder Jokerzeichen enthalten.
An Optionen definiert BIND momentan nur eine:
\begin{itemize}
\item{\tty{f $<$Header[,Header...]$>$}: gibt eine Liste von Header-IDs
an, die kopiert werden sollen. Alle anderen Records werden
nicht kopiert. Ohne diese Angabe werden alle Records kopiert.
Die in der Liste angegebenen entsprechen dem Header-Feld in der
Recordstruktur, wie es in Abschnitt \ref{SectCodeFormat} beschrieben wurden. Die
einzelnen Header-Nummern in der Liste werden durch Kommas getrennt.}
\end{itemize}
Um z.B. alle MCS-51-Codeteile aus einer Programmdatei auszusieben,
benutzt man BIND folgenderma"sen:
\begin{verbatim}
BIND <Quellname> <Zielname> -f $31
\end{verbatim}
Fehlt bei einer Dateiangabe eine Endung, so wird automatisch die Endung
P angef"ugt.
%%---------------------------------------------------------------------------
P2HEX ist eine Erweiterung von BIND. Es besitzt alle
Kommandozeilenoptionen von BIND und hat die gleichen Konventionen
bzgl. Dateinamen. Im Gegensatz zu BIND wird die Zieldatei aber als
Hexfile ausgegeben, d.h. als eine Folge von Zeilen, die den Code als
ASCII-Hexzahlen enthalten.
P2HEX kennt neun verschiedene Zielformate, die "uber den
Kommandozeilenparameter \bb{F} ausgew"ahlt werden k"onnen:
\begin{itemize}
\item{Motorola S-Record (\tty{-F Moto})}
\item{MOS Hex (\tty{-F MOS})}
\item{Intel-Hex (Intellec-8, \tty{-F Intel})}
\item{16-Bit Intel-Hex (MCS-86, \tty{-F Intel16})}
\item{32-Bit Intel-Hex (\tty{-F Intel32})}
\item{Tektronix Hex (\tty{-F Tek})}
\item{Texas Instruments DSK (\tty{-F DSK})}
\item{Atmel AVR Generic (\tty{-F Atmel}, siehe \cite{AVRObj})}
\item{Lattice Mico8 prom\_init (\tty{-F Mico8})}
\item{C-Arrays, zum Inkludieren in C(++)-Quelldateien (\tty{-F C})}
\end{itemize}
Wird kein Zielformat explizit angegeben, so w"ahlt P2HEX anhand des
Prozessortyps automatisch eines aus, und zwar S-Records f"ur Motorola-
Prozessoren, Hitachi und TLCS-900(0), MOS f"ur 65xx/MELPS, DSK f"ur die
16-Bit-Texas-Signalprozessoren, Atmel Generic f"ur die AVRs und Intel-Hex
f"ur den Rest. Je nach Breite der Startadresse kommen bei S-Record Records
der Typen 1,2 oder 3 zum Einsatz, jedoch nie in einer Gruppe gemischt.
Diese Automatik l"a"st sich mit der Kommandozeilenoption
\begin{verbatim}
-M <1|2|3>
\end{verbatim}
teilweise unterdr"ucken: Ein Wert von 2 bzw. 3 sorgt daf"ur, da"s
S-Records mit einem Mindesttyp von 2 bzw. 3 benutzt werden, w"ahrend ein
Wert von 0 der vollen Automatik entspricht.
Normalerweise benutzt das AVR-Format immer eine Adre"sl"ange von 3 Bytes.
Manche Programme m"ogen das leider nicht...deshalb kann man mit dem
Schalter
\begin{verbatim}
-avrlen <2|3>
\end{verbatim}
die L"ange zur Not auf 2 Bytes reduzieren.
Das Mico8-Format unterscheidet sich insofern aus den anderen
Formaten, als da"s es keine Adre"sfelder besitzt - es ist eine
schlichte Auflistung der Instruktionsw"orter im Programmspeicher.
Bei der Benutzung mu"s darauf geachtet werden, da"s der
belegte Adre"sbereich (der sich z.B. mit PLIST anzeigen l"a"st)
bei Null beginnt und fortlaufend ist.
Die Intel-, Tektronix- und MOS-Formate sind auf 16 Bit-Adressen
beschr"ankt, das 16-Bit Intel-Format reicht 4 Bit weiter. L"angere
Adressen werden von P2HEX mit einer Warnung gemeldet und abgeschnitten(!).
F"ur die PICs k"onnen die drei von Microchip spezifizierten Varianten des
Intel-Hex-Formates erzeugt werden, und zwar mit dem Schalter
\begin{verbatim}
-m <0..3>
\end{verbatim}
Das Format 0 ist INHX8M, in dem alle Bytes in Lo-Hi-Ordnung enthalten
sind. Die Adre"sangaben verdoppeln sich, weil bei den PICs die Adresse
sich nur um 1 pro Wort erh"oht. Dieses Format ist gleichzeitig die Vorgabe.
Im Format 1 (INHX16M) werden alle Worte in ihrer nat"urlichen Ordnung
abgelegt. Dieses Format verwendet Microchip f"ur seine eigenen
Programmierger"ate. Format 2 (INHX8L) und 3 (INHX8H) trennen die Worte
in ihre oberen und unteren Bytes auf. Um die komplette Information zu
erhalten, mu"s P2HEX zweimal aufgerufen werden, z.B. so:
\begin{verbatim}
p2hex test -m 2
rename test.hex test.obl
p2hex test -m 3
rename test.hex test.obh
\end{verbatim}
F"ur das Motorola-Format verwendet P2HEX zus"atzlich einen in \cite{CPM68K}
genannten Recordtyp mit der Nummer 5, der die Zahl der folgenden
Daten-Records (S1/S2/S3) bezeichnet. Da dieser Typ vielleicht nicht jedem
Programm bekannt ist, kann man ihn mit der Option
\begin{verbatim}
+5
\end{verbatim}
unterdr"ucken.
Das C-Format f"allt insofern aus dem Rahmen, als da"s es immer explizit
ausgew"ahlt werden mu"s. Die Ausgabedatei stellt im Prinzip ein vollst"andiges
St"uck C- oder C++-Code dar, das die Daten als eine Liste von C-Arrays
enth"alt. Neben den eigentlichen Daten wird noch eine Liste von Deskriptoren
geschrieben, die Start, L"ange und Ende der Datenbl"ocke
beschreiben. Was diese Deskriptoren enthalten, kann mit der Option
\begin{verbatim}
-cformat <Format>
\end{verbatim}
bestimmt werden. Jeder Buchstabe in \verb!Format! legt ein Element des
Deskriptors fest:
\begin{itemize}
\item{Ein \verb!d! oder \verb!D! definiert einen Zeiger auf die Daten.
"Uber den Gro"s- oder Kleinbuchstaben wird festgelegt, ob die Hex-
Konstanten Gro"s- oder Kleinbuchstaben verwenden sollen.}
\item{Ein \verb!s! oder \verb!S! definiert die Startadresse der Daten,
wahlweise vom Typ {\em unsigned} oder {\em unsigned long}.}
\item{Ein \verb!l! oder \verb!L! definiert die L"ange der Daten,
wahlweise vom Typ {\em unsigned} oder {\em unsigned long}.}
\item{Ein \verb!e! oder \verb!E! definiert die Endadresse der Daten,
d.h. die letzte von den Daten benutzte Adresse,
wahlweise vom Typ {\em unsigned} oder {\em unsigned long}.}
\end{itemize}
Finden sich Code-Records verschiedener Prozessoren in einer Quelldatei,
so erscheinen die verschiedenen Hexformate auch gemischt in der Zieldatei
--- es empfiehlt sich also dringend, von der Filterfunktion Gebrauch zu
machen, oder ein fixes Format "uber die \verb!-F!-Option festzulegen.
Neben dem Codetypenfilter kennt P2HEX noch ein Adre"sfilter, das n"utzlich
ist, falls der Code auf mehrere EPROMs verteilt werden mu"s:
\begin{verbatim}
-r <Startadresse>-<Endadresse>
\end{verbatim}
Die Startadresse ist dabei die erste Speicherzelle, die im Fenster liegen
soll, die Endadresse die der letzten Speicherzelle im Fenster, \ii{nicht}
die der ersten au"serhalb. Um z.B. ein 8051-Programm in 4 2764-EPROMs
aufzuteilen, geht man folgenderma"sen vor:
\begin{verbatim}
p2hex <Quelldatei> eprom1 -f $31 -r $0000-$1fff
p2hex <Quelldatei> eprom2 -f $31 -r $2000-$3fff
p2hex <Quelldatei> eprom3 -f $31 -r $4000-$5fff
p2hex <Quelldatei> eprom4 -f $31 -r $6000-$7fff
\end{verbatim}
Anstelle einer festen Adresse kann man als Anfang bzw. Ende auch ein
einfaches Dollarzeichen oder ein '0x' angeben. Dies bedeutet, da"s die
niedrigste bzw. h"ochste in der Quelldatei gefundene Adresse als Anfang
bzw. Ende genommen wird. Der Default f"ur den Bereich ist '0x-0x', d.h.
es werden alle Daten aus der Quelldatei "ubernommen.
\bb{ACHTUNG!} Die Splittung "andert nichts an den absoluten Adressen, die
in den Hexfiles stehen! Sollen die Adressen im Hexfile bei 0 beginnen,
so kann man dies durch den zus"atzlichen Schalter
\begin{verbatim}
-a
\end{verbatim}
erreichen. Um im Gegenteil die Adre"slage auf einen bestimmten Wert zu
verschieben, kann man den Schalter
\begin{verbatim}
-R <Wert>
\end{verbatim}
verwenden. Der dabei angegebene Wert ist ein {\em Offset}, d.h. er wird
auf die in der Code-Datei angegebenen Adressen aufaddiert.
Den Inhalt einer Datei kann man mit einem Offset auf eine beliebige
Position verschieben; diesen Offset h"angt man einfach in Klammern an
den Dateinamen an. Ist der Code in einer Datei z.B. auf Adresse 0 in
der P-Datei abgelegt, man m"ochte ihn jedoch auf Adresse 1000h
verschieben, so h"angt man an \tty{(\$1000)} an den Dateinamen (ohne
Leerzeichen!) an.
Sofern die P-Datei nicht nur Daten aus dem Code-Segment enth"alt, kann
man mit dem Schalter
\begin{verbatim}
-segment <name>
\end{verbatim}
ausw"ahlen, aus welchen Segment Daten extrahiert und ins HEX-Format
gewandelt werden sollen. Die als Argument anzugebenden Segmentnamen sind
die gleichen wie f"ur den \tty{SEGMENT}-Befehl (\ref{SEGMENT}). Ein
Sonderfall ist das TI-DSK-Format, das als einziges Format vermerken kann,
ob Daten ins Code- oder Datensegment geh"oren. In diesem Fall extrahiert
P2HEX automatisch beide Segmente, solange kein Segment explizit angegeben
ist.
Analog zur \verb!-r! Option kann man mit der Option
\begin{verbatim}
-d <Start>-<Ende>
\end{verbatim}
ein Filter f"ur das Datensegment angeben.
F"ur das DSK-, Intel- und Motorola-Format relevant ist die Option
\begin{verbatim}
-e <Adresse> ,
\end{verbatim}
mit der man die in die Hex-Datei einzutragende Startadresse festlegen
kann. Fehlt diese Angabe, so wird nach einen entsprechenden Eintrag
in der Code-Datei gesucht. Ist auch dort kein Hinweis auf einen
Einsprungpunkt zu finden, so wird kein Eintrag in die HEX-Datei
geschrieben (DSK/Intel) bzw. das entsprechende Feld wird auf 0 gesetzt
(Motorola).
Leider ist sich die Literatur nicht ganz "uber die Endezeile f"ur
Intel-Hexfiles einig. P2HEX kennt daher 3 Varianten, einstellbar "uber
den Parameter \bb{i} mit einer nachfolgenden Ziffer:
\begin{description}
\end{description}
Defaultm"a"sig wird die Variante 0 benutzt, die die gebr"auchlichste zu
sein scheint.
Fehlt der Zieldateiangabe eine Endung, so wird \tty{HEX} als Endung angenommen.
Defaultm"a"sig gibt P2HEX pro Zeile maximal 16 Datenbytes aus, wie es
auch die meisten anderen Tools tun, die Hex-Files erzeugen. Wollen
Sie dies "andern, so k"onnen Sie dies mit dem Schalter
\begin{verbatim}
-l <Anzahl>
\end{verbatim}
tun. Der erlaubte Wertebereich liegt dabei zwischen 2 und 254 Datenbytes;
ungerade Werte werden implizit auf gerade Anzahlen aufgerundet.
Meist werden die tempor"aren, von \asname{} erzeugten Code-Dateien nach einer
Umwandlung nicht mehr unbedingt gebraucht. Mit der Kommandozeilen-
option
\begin{verbatim}
-k
\end{verbatim}
kann man P2HEX anweisen, diese automatisch nach der Konversion zu l"oschen.
Anders als BIND erzeugt P2HEX keine Leerdatei, wenn nur ein Dateiname
(=Zieldatei) angegeben wurde, sondern bearbeitet die dazugeh"orige
Codedatei. Es ist also ein Minimalaufruf \`a la
\begin{verbatim}
P2HEX <Name>
\end{verbatim}
m"oglich, um $<$Name: $>$.HEX aus $<$Name: $>$.P zu erzeugen.
%%---------------------------------------------------------------------------
P2BIN funktioniert wie P2HEX und bietet die gleichen Optionen (bis
auf die a- und i- Optionen, die bei Bin"ardateien keinen Sinn ergeben), nur
wird das Ergebnis nicht als Hexdatei, sondern als einfache Bin"ardatei
abgelegt. Dies kann dann z.B. direkt in ein EPROM gebrannt werden.
Zur Beeinflussung der Bin"ardatei kennt P2BIN gegen"uber P2HEX noch
drei weitere Optionen:
\begin{itemize}
\item{\tty{l $<8-Bit-Zahl>$}: gibt den Wert an, mit dem unbenutzte
Speicherstellen in der Datei gef"ullt werden sollen.
Defaultm"a"sig ist der Wert \$ff, so da"s ein halbwegs
intelligenter EPROM-Brenner sie "uberspringt. Man kann aber
hiermit auch andere Werte einstellen, z.B. enthalten die gel"oschten
Speicherzellen der MCS-48-EPROM-Versionen Nullen. In einem solchen
Falle w"are 0 der richtige Wert.}
\item{\tty{s}: weist das Programm an, eine Pr"ufsumme "uber die Bin"ardatei zu
berechnen. Die Pr"ufsumme wird einmal als 32-Bit-Wert ausgegeben,
zum anderen wird das Zweierkomplement der Bits 0..7 in der letzten
Speicherstelle abgelegt, so da"s die Modulo-256-Summe zu 0 wird.}
\item{\tty{m}: f"ur den Fall, da"s ein Prozessor mit 16- oder 32-Bit-Datenbus
eingesetzt wird und die Bin"ardatei f"ur mehrere EPROMs aufgesplittet
werden mu"s. Das Argument kann folgende Werte annehmen:
\begin{itemize}
\item{\tty{ALL}: alles kopieren}
\item{\tty{ODD}: alle Bytes mit ungerader Adresse kopieren}
\item{\tty{EVEN}: alle Bytes mit gerader Adresse kopieren}
\item{\tty{BYTE0}..\tty{BYTE3}: nur alle Bytes kopieren, deren Adresse die Form
$4n+0$...$4n+3$ hat.}
\item{\tty{WORD0},\tty{WORD1}: nur das untere bzw. obere 16-Bit-Wort der
32-Bit-Worte kopieren.}
\end{itemize}}
\end{itemize}
Nicht wundern: Bei letzteren Optionen ist die Bin"ardatei um den Faktor 2
oder 4 kleiner als bei \tty{ALL}. Dies ist bei konstantem Adre"sfenster logisch!
Falls die Code-Datei keine Startadresse enth"alt, kann man diese
analog zu P2HEX "uber die \tty{-e}-Kommandozeilenoption vorgeben. Auf
Anforderung teilt P2BIN ihren Wert der Ergebnisdatei voran. Mit der
Kommandozeilenoption
\begin{verbatim}
-S
\end{verbatim}
wird diese Funktion aktiviert. Sie erwartet als Argument eine
Zahlenangabe zwischen 1 und 4, die die L"ange des Adressfeldes in
Bytes bestimmt. Optional kann dieser Angabe auch noch der Buchstabe
L oder B vorangestellt werden, um die Byte-Order dieser Adresse
festzulegen. So erzeugt z.B. die Angabe \tty{B4} eine 4-Byte-Adresse in
Big-Endian-Anordnung, \tty{L2} oder nur '2' eine 2-Byte-Adresse in
Little-Endian-Anordnung.
%%---------------------------------------------------------------------------
Bei AS2MSG handelt es sich eigentlich um kein Hilfsprogramm, sondern um ein
Filter, das (gl"ucklichen) Besitzern von Borland-Pascal 7.0 das Arbeiten
mit dem Assembler erleichtern soll. In den DOS-Arbeitsumgebungen existiert
ein ,,Tools''-Men"u, das man um eigene Programme, z.B. \asname{} erweitern kann.
Das Filter erlaubt, die von \asname{} gelieferten Fehlermeldungen mit Zeilenangabe
direkt im Editorfenster anzuzeigen. Dazu mu"s im Tools-Men"u ein neuer
Eintrag angelegt werden (\tty{Options/Tools/New}). Tragen Sie in die
einzelnen Felder folgende Werte ein :
\begin{itemize}
\item{Title: {\tt \verb!~!M\verb!~!akroassembler}}
\item{Program path: \tty{\asname{}}}
\item{Command line: \tty{-E !1 \$EDNAME \$CAP MSG(AS2MSG) \$NOSWAP \$SAVE
ALL}}
\item{bei Bedarf einen Hotkey zuordnen (z.B. Shift-F7)}
\end{itemize}
Die Option \tty{-E} sorgt daf"ur, da"s Turbo-Pascal nicht mit STDOUT und
STDERR durcheinander kommt.
Ich setze dabei voraus, da"s sowohl \asname{} als auch AS2MSG sich in einem
Verzeichnis befinden, welches in der Pfadliste aufgef"uhrt ist. Nach einem
Druck auf dem passenden Hotkey (oder Auswahl aus dem Tools-Men"u) wird \asname{} mit
dem Namen der Textdatei im aktiven Editorfenster aufgerufen. Die dabei
aufgetretenen Fehler werden in ein separates Fenster geleitet, durch das man
nun ,,browsen'' kann. Mit \bb{Ctrl-Enter} springt man eine fehlerhafte
Zeile an. Zus"atzlich enth"alt das Fenster die Statistik, die \asname{} am Ende
der Assemblierung ausgibt. Diese erhalten als Dummy-Zeilennummer 1.
F"ur diese Arbeitsweise sind sowohl TURBO.EXE (Real Mode) als auch BP.EXE
(Protected Mode) geeignet. Ich empfehle BP, da in dieser Variante beim
Aufruf nicht erst der halbe DOS-Speicher ,,freigeswappt'' werden mu"s.
\cleardoublepage
%%===========================================================================
\cleardoublepage
\chapter{Fehlermeldungen von \asname{}}
Im folgenden findet sich eine halb-tabellarische Auflistung der in \asname{}
definierten Fehlermeldungen. Zu jeder Fehlermeldung finden sich folgende
Angaben:
\begin{itemize}
\item{interne Fehlernummer (f"ur den Anwender nur mit der \tty{n}-Option sichtbar);}
\item{Fehlermeldung im Klartext;}
\begin{itemize}
\item{Warnung: zeigt m"ogliche Fehler oder ineffizienten Code an.
Assemblierung geht weiter.}
\item{Fehler: echte Fehler. Assemblierung geht weiter, aber keine
Code-Datei wird geschrieben.}
\item{Fatal: schwerwiegende Fehler. Assemblierung wird abgebrochen.}
\end{itemize}}
\item{Ursache: die Situation(en), in denen der Fehler ausgegeben
wird;}
\item{Argument: Die Ausgabe, die auf Wunsch als erweiterte Fehlermeldung
erfolgt.}
\end{itemize}
\begin{description}
\end{description}}
}
\begin{description}
\errentry{ 5}{Displacement=0, "uberfl"ussig}
{Warnung}
{bei 680x0-,6809- und COP8-Prozessoren: Das Displacement
in einem Adre"sausdruck hat den Wert 0 ergeben. Es wird
ein Adre"sausdruck ohne Displacement erzeugt. Um keine
Phasenfehler zu erzeugen, werden NOP-Befehle eingef"ugt.}
{keines}
\errentry{ 10}{Kurzadressierung m"oglich}
{Warnung}
{bei 680x0-, 6502- und 68xx-Prozessoren k"onnen
bestimmte Speicherbereiche mit kurzen Adressen erreicht
werden. Um keine Phasefehler zu erzeugen, wird zwar der
k"urzere Ausdruck erzeugt, der freie Platz wird aber mit
NOPs aufgef"ullt.}
{keines}
\errentry{ 20}{kurzer Sprung m"oglich}
{Warnung}
{Bei 680x0 und 8086-Prozessoren kann der Sprung
sowohl mit langem als auch kurzem Displacement ausgef"uhrt
werden. Da kein kurzer Sprung angefordert wurde, wurde im
ersten Pass Platz f"ur den langen Sprung freigehalten.
Es wird ein kurzer Sprung erzeugt, der freie Platz wird
mit NOPs aufgef"ullt, um Phasenfehler zu vermeiden.}
{keines}
\errentry{ 30}{kein Sharefile angelegt, SHARED ignoriert}
{Warnung}
{Es wurde eine \tty{SHARED}-Anweisung gefunden, es
wurde aber keine Kommandozeilenoption angegeben, um eine
Shared-Datei zu erzeugen.}
{keines}
\errentry{ 40}{FPU liest Wert evtl. nicht korrekt ein ($>$=1E1000)}
{Warnung}
{Das BCD-Gleitkommaformat der 680x0-Koprozessoren
erlaubt zwar vierstellige Exponenten, lt. Datenbuch
k"onnen solche Werte aber nicht korrekt eingelesen werden.
Der vierstellige Wert wird zwar erzeugt, eine Funktion ist
aber nicht gew"ahleistet.}
{keines}
\errentry{ 50}{Privilegierte Anweisung}
{Warnung}
{Es wurde eine Anweisung benutzt, die nur im
Supervisor-Mode zul"assig ist, obwohl dieser nicht mittels
\tty{SUPMODE ON} vorher explizit angezeigt wurde.}
{keines}
\errentry{ 60}{Distanz 0 nicht bei Kurzsprung erlaubt (NOP erzeugt)}
{Warnung}
{Ein kurzer Sprung mit der Distanz 0 ist bei
680x0- bzw. COP8-Prozessoren nicht erlaubt, da dieser Sonderwert f"ur
lange Spr"unge ben"otigt wird. Stattdessen wurde ein
NOP-Befehl eingef"ugt.}
{keines}
\errentry{ 70}{Symbol aus falschem Segment}
{Warnung}
{Das in dem Operanden benutzte Symbol
ist aus einem Adre"sraum, der nicht mit dem benutzten
Befehl bearbeitet werden kann.}
{keines}
\errentry{ 75}{Segment nicht adressierbar}
{Warnung}
{Das in dem Operanden benutzte Symbol
ist aus einem Adre"sraum, der mit keinem der Segmentregister
des 8086 adressiert werden kann.}
{Name des nicht adressierbaren Segments}
\errentry{ 80}{"Anderung des Symbolwertes erzwingt zus"atzlichen Pass}
{Warnung}
{Ein Symbol hat einen anderen Wert zugewiesen
bekommen als im vorhergehenden Pass. Diese Warnung wird
nur ausgegeben, falls die \tty{r}-Option angegeben wurde.}
{Der Name des fraglichen Symbols}
\errentry{ 90}{"Uberlappende Speicherbelegung}
{Warnung}
{Bei der Bildung der Belegungsliste wurde
festgestellt, da"s ein Speicherbereich im Codesegment
mehrfach benutzt wurde. Ursache k"onnen un"uberlegte
\tty{ORG}-Anweisungen sein.}
{keines}
\errentry{ 95}{"Uberlappende Registernutzung}
{Warnung}
{In der Anweisung wurden Register ganz oder teilweise
mehrfach in nicht zul"assiger Weise verwendet.}
{Das den Konflikt ausl"osende Argument}
\errentry{ 100}{keine CASE-Bedingung zugetroffen}
{Warnung}
{bei einem \tty{SWITCH}..\tty{CASE}-Konstrukt ohne
\tty{ELSECASE}-Zweig traf keiner der \tty{CASE}-Zweige zu.}
{keines}
\errentry{ 110}{Seite m"oglicherweise nicht adressierbar}
{Warnung}
{Das in dem Operanden benutzte Symbol
liegt nicht in der momentan mit \tty{ASSUME} eingestellten
Fenster (ST6,78(C)10).}
{keines}
\errentry{ 120}{Registernummer mu"s gerade sein}
{Warnung}
{Die Hardware erlaubt nur ein Registerpaar
zu verketten, dessen Startadresse gerade ist (RR0, RR2...,
nur Z8).}
{keines}
\errentry{ 130}{veralteter Befehl}
{Warnung}
{Der verwendete Befehl ist zwar noch
definiert, ist in seiner Funktion aber durch andere,
neue Befehle ersetzbar und daher in zuk"unftigen
Prozessorversionen eventuell nicht mehr vorhanden.}
{keines}
\errentry{ 140}{Nicht vorhersagbare Ausf"uhrung dieser Anweisung}
{Warnung}
{Die verwendete Adressierungsart ist bei
diesem Befehl zwar prinzipiell erlaubt, ein Register
wird jedoch in einer Weise doppelt verwendet, da"s je
nach Aus"uhrungsreihenfolge sich unterschiedliche
Ergebnisse einstellen k"onnen.}
{keines}
\errentry{ 150}{Lokaloperator au"serhalb einer Sektion "uberfl"ussig}
{Warnung}
{Ein vorangestellter Klammeraffe dient
dazu, sich explizit auf zu der Sektion lokale Symbole
zu beziehen. Wenn man sich au"serhalb einer Sektion
befindet, gibt es keine lokalen Symbole, weshalb dieser
Operator "uberfl"ussig ist.}
{keines}
\errentry{ 160}{sinnlose Operation}
{Warnung}
{Die Anweisung ergibt entweder "uberhaupt
keinen Sinn oder kann auf andere Weise schneller und k"urzer
ausgef"uhrt werden.}
{keines}
\errentry{ 170}{unbekannter Symbolwert erzwingt zus"atzlichen Pass}
{Warnung}
{\asname{} vermutet eine Vorw"artsreferenz eines
Symbols, d.h. das Symbol wird benutzt, bevor es definiert
wurde, und h"alt einen weiteren Pass f"ur unumg"anglich.
Diese Warnung wird nur ausgegeben, falls die \tty{r}-Option
angegeben wurde.}
{Der Name des fraglichen Symbols}
\errentry{ 180}{Adresse nicht ausgerichtet}
{Warnung}
{Eine Adresse ist nicht ein mehrfaches der
Operandengr"o"se. Das Datenbuch verbietet zwar solche Zugriffe,
im Instruktionswort ist aber Platz f"ur diese Adresse, so da"s
\asname{} es bei einer Warnung belassen hat.}
{keines}
\errentry{ 190}{I/O-Adresse darf nicht verwendet werden}
{Warnung}
{Der verwendete Adressierungsmodus oder die
angesprochene Adresse sind zwar prinzipiell erlaubt, die
Adresse liegt aber im Bereich der Peripherieregister, die in
diesem Zusammenhang nicht verwendet werden d"urfen.}
{keines}
\errentry{ 200}{m"ogliche Pipeline-Effekte}
{Warnung}
{Ein Register wird in einer Befehlsfolge so
verwendet, da"s die Befehlsausf"uhrung m"oglicherweise nicht
in der hingeschriebenen Form ablaufen wird. "Ublicherweise
wird ein Register benutzt, bevor der neue Wert zur Verf"ugung
steht.}
{das die Verklemmung verursachende Register}
\errentry{ 210}{mehrfache Adre"sregisterbenutzung in einer Anweisung}
{Warnung}
{Ein Adre"sregister wird in mehreren
Adre"sausdr"ucken eines Befehls benutzt. Sofern einer der
beiden Ausdr"ucke das Register modifiziert, sind die
Ergebnisadressen nicht eindeutig festgelegt.}
{das mehrfach verwendete Register}
\errentry{ 220}{Speicherstelle ist nicht bitadressierbar}
{Warnung}
{Mit einer \tty{SFRB}-Anweisung wurde
versucht, eine Speicherstelle als bitadressierbar zu
deklarieren, die aufgrund der Architektur des 8051 nicht
bitadressierbar ist.}
{keines}
\errentry{ 230}{Stack ist nicht leer}
{Warnung}
{Am Ende eines Durchlaufes ist ein vom
Programm definierter Stack nicht leer.}
{der Name des Stacks sowie seine Resttiefe}
\errentry{ 240}{NUL-Zeichen in Strings, Ergebnis undefiniert}
{Warnung}
{Eine String-Konstante enth"alt ein
NUL-Zeichen. Dies funktioniert zwar mit der Pascal-Version,
in Hinblick auf die C-Version von \asname{} ist dies aber ein Problem,
da C Strings mit einem NUL-Zeichen terminiert, d.h. der String
w"are f"ur C an dieser Stelle zu Ende...}
{keines}
\errentry{ 250}{Befehl "uberschreitet Seitengrenze}
{Warnung}
{Ein Befehl steht zu Teilen auf
verschiedenen Seiten. Da der Programmz"ahler des Prozessors
aber nicht "uber Seitengrenzen hinweg inkrementiert wird,
w"urde zur Laufzeit anstelle des Instruktionsbytes von der
Folgeseite wieder das erste Byte der alten Seite geholt; das
Programm w"urde fehlerhaft ablaufen.}
{keines}
\errentry{ 255}{Bereichsunterschreitung}
{Warnung}
{Ein Zahlenwert lag unterhalb des erlaubten Bereichs. \asname{}
hat den Wert durch ein Abschneiden der oberen Bitstellen
in den erlaubten Bereich gebracht, es ist jedoch nicht
garantiert, da"s sich durch diese Operation sinnvoller und
korrekter Code ergibt.}
{keines}
\errentry{ 260}{Bereichs"uberschreitung}
{Warnung}
{Ein Zahlenwert lag oberhalb des erlaubten Bereichs. \asname{}
hat den Wert durch ein Abschneiden der oberen Bitstellen
in den erlaubten Bereich gebracht, es ist jedoch nicht
garantiert, da"s sich durch diese Operation sinnvoller und
korrekter Code ergibt.}
{keines}
\errentry{ 270}{negatives Argument f"ur DUP}
{Warnung}
{Das Wiederholungsargument einer \tty{DUP}-Direktive war
kleiner als 0. Es werden (analog zu einem Argument von
genau 0) keine Daten abgelegt.}
{keines}
\errentry{ 280}{einzelner X-Operand wird als indizierte und nicht als
implizite Adressierung interpretiert}
{Warnung}
{Ein einzelner X-Operand kann sowohl als Register X als
auch X-indizierte Adressierung mit Null-Displacement
interpretiert werden, da sich Motorola hier nicht festlegt.
\asname{} w"ahlt die letztere Variante, was m"oglicherweise nicht
das erwartete ist.}
{keines}
\errentry{ 300}{Bit-Nummer wird abgeschnitten werden}
{Warnung}
{Die Instruktion arbeitet nur auf Byte- bzw.
Langwort-Operanden, Bitnummern jenseits 7 bzw. 31 werden
von der CPU modulo-8 bzw. modulo-32 behandelt werden.}
{keines}
\errentry{ 310}{Ung"ultiger Wert f"ur Registerzeiger}
{Warnung}
{G"ultige bzw. sinnvolle Werte f"ur den Registerzeiger sind
nur Werte von 0x00...0x70 bzw. 0xf0, weil die anderen
Registerbereiche unbelegt sind.}
{keines}
\errentry{ 320}{Makro-Argument umdefiniert}
{Warnung}
{Einem Makroparameter wurden zwei oder mehr
verschiedene Werte zugewiesen. Dies kann bei der
Verwendung von Schl"usselwortparametern auftreten.
Das zuletzt angegebene Argument wird benutzt.}
{Name des Makroparameters}
\errentry{ 330}{veraltete Anweisung}
{Warnung}
{Dies Anweisung ist veraltet und sollte nicht mehr
in neuen Programmen verwendet werden.}
{Die Anweisung, die stattdessen verwendet werden sollte.}
\errentry{ 340}{Quelloperand l"anger oder gleich Zieloperand}
{Warnung}
{Der Quelloperand ist l"anger oder gleich gro"s wie der
Zieloperand, gemessen in Bits. Eine Null- oder Vorzeichenerweiterung
ergibt keinen Sinn mit diesen Argumenten. Schlagen Sie im
Referenzhandbuch der CPU das Verhalten in diesem Fall nach.}
{keines}
\errentry{ 350}{TRAP-Nummer ist g"ultige Instruktion}
{Warnung}
{Ein TRAP mit dieser Nummer benutzt den gleichen Maschinencode
wie ein von der CPU unterst"utzter Maschinenbefehl.}
{keines}
\errentry{ 360}{Padding hinzugef"ugt}
{Warnung}
{Die Menge abgelegter Bytes ist ungerade; eine H"alfte des letzten
16-Bit-Wortes bleibt ungenutzt.}
{keines}
\errentry{ 370}{Registernummer-Umlauf}
{Warnung}
{Die Startregisternummer plus die Anzahl der Register ergibt ein
letztes Register jenseits des Endes der Registerbank.}
{das Argument mit der Registeranzahl}
\errentry{ 380}{verwende indizierte anstelle indirekter Adressierung}
{Warnung}
{Indirekte Adressierung ist an dieser Stelle nicht erlaubt.
Es wird stattdessen indizierte Adressierung mit einem
(Dummy-)Displacement von Null verwendet.}
{das Argument mit dem Adressierungsausdruck}
\errentry{ 390}{nicht im Normal-Modus erlaubt}
{Warnung}
{Dieser Maschinenbefehl ist nur im Panel-Modus und nicht
im ,,Normalbetrieb'' erlaubt.}
{die fragliche Instruktion}
\errentry{ 400}{nicht im Panel-Modus erlaubt}
{Warnung}
{Dieser Maschinenbefehl ist nur im ,,Nornalbetrieb''
und nicht im Panel-Modus erlaubt.}
{die fragliche Instruktion}
\errentry{ 410}{Argument ausserhalb erlauben Bereichs}
{Warnung}
{Das Argument oder die Summe zweier Argumente
liegt au"serhalb des f"ur diesen Befehls erlaubten
Bereichs, obwohl in der Instruktion prinzipiell
Raum f"ur gr"o"sere Werte ist.}
{das fragliche Argument}
\errentry{ 420}{Versuch, eine Mehrwort-Instruktion zu "uberspringen}
{Warnung}
{Die vorherige Anweisung war eine Skip-Anweisung, die
nur ein Maschinenwort im Code "uberspringen kann. Da
die aktuelle Anweisung l"anger als ein Maschinenwort
ist, w"urde der Skip mitten in die Anweisung springen.}
{die fragliche Anweisung}
\errentry{ 430}{implizite Vorzeichenerweiterung}
{Warnung}
{Der Prozessor f"uhrt bei diesem Befehl eine Vorzeichenerweiterung
auf die volle Registerbreite aus. Das bedeutet, dass
die oberen Bits f"ur das gegebene Argument mit 1 und
nicht mit 0 gef"ullt werden. Je nach folgender Nutzung
kann dies irrelevant sein, mu"s aber nicht.}
{der fragliche Wert}
\errentry{ 440}{numerischer Wert -128 bedeutet Nutzung des E-Registers (Literal 'E' verwenden, um diese Warnung zu vermeiden)}
{Warnung}
{Ein Displacement von -128 bedeutet beim SC/MP in diesem Fall, dass
das Displacement aus dem E-Register genommen wird. Der Assembler
kann in diesem Fall nicht sicher entscheiden, ob das gewollt ist
oder der Wert -128 sich unbeabsichtigt aus einer Berechnung ergeben
hat. Verwenden Sie stattdessen das Literal 'E' oder ein auf 'E'
definiertes Registersymbol, um die Absicht klar zu machen und die
Warnung zu vermeiden.}
{das fragliche Displacement-Argument}
\errentry{ 450}{I/O-Adresse mu"s mit INS/OUTS angesprochen werden}
{Warnung}
{I/O-Adressen im Bereich des Prozessormoduls (0..3) k"onnen nur
"uber die Befehle {\tt INS} und {\tt OUTS} erreicht werden,
nicht "uber {\tt IN} und {\tt OUT}.}
{das fragliche Adress-Argument}
\errentry{1000}{Symbol doppelt definiert}
{Fehler}
{Einem Symbol wurde durch ein Label oder
\tty{EQU}, \tty{PORT}, \tty{SFR}, \tty{LABEL},
\tty{SFRB} oder \tty{BIT} ein neuer Wert zugewiesen, dies
ist aber nur bei \tty{SET/EVAL} erlaubt.}
{Name des fraglichen Symbols, bei eingeschalteter
Querverweisliste zus"atzlich die Zeile der ersten Definition}
\errentry{1010}{Symbol nicht definiert}
{Fehler}
{Ein benutztes Symbol ist auch im 2.Pass noch
nicht in der Symboltabelle enthalten.}
{Name des nicht gefundenen Symbols}
\errentry{1020}{Ung"ultiger Symbolname}
{Fehler}
{Ein Symbolname entspricht nicht den Bedingungen
f"ur einen g"ultigen Symbolnamen. Beachten Sie, da"s f"ur
Makro-und Funktionsparameter strengere Regeln gelten!}
{der fehlerhafte Symbolname}
\errentry{1090}{Ung"ultiges Format}
{Fehler}
{Das benutzte Befehlsformat existiert bei diesem
Befehl nicht.}
{Der Kennbuchstabe des verwendeten Formates}
\errentry{1100}{"Uberfl"ussiges Attribut}
{Fehler}
{Der benutzte Befehl (Prozessor oder Pseudo) darf
kein mit einem Punkt angeh"angtes Attribut haben.}
{keines}
\errentry{1105}{Attribut darf nur 1 Zeichen lang sein}
{Fehler}
{Das mit einem Punkt an einen Befehl angeh"angte
Attribut mu"s genau ein Zeichen lang sein; weder mehr noch
weniger ist erlaubt.}
{keines}
\errentry{1107}{undefiniertes Attribut}
{Fehler}
{Das an einem Befehl angef"ugte Attribut ist ung"ultig.}
{keines}
\errentry{1110}{Unpassende Operandenzahl}
{Fehler}
{Die bei einem Befehl (Prozessor oder Pseudo)
angegebene Operandenzahl liegt nicht in dem f"ur diesen
Befehl erlaubten Bereich.}
{Die erwartete Anzahl Argumente bzw. Operanden}
\errentry{1112}{Kann Argument nicht in Teile aufspaltenl}
{Fehler}
{Bei bestimmten Prozessoren (z.B. DSP56000)
m"ussen die kommaseparierten Argumente weiter in
Einzeloperanden aufgespalten werden, diese ist
fehlgeschlagen.}
{keines}
\errentry{1115}{Unpassende Optionenzahl}
{Fehler}
{Die bei diesem Befehl angegebene Zahl
von Optionen liegt nicht in dem f"ur diesen
Befehl erlaubten Bereich.}
{keines}
\errentry{1120}{nur immediate-Adressierung erlaubt}
{Fehler}
{Der benutzte Befehl l"a"st nur
immediate-Operanden (mit vorangestelltem \#) zu.}
{keines}
\errentry{1130}{Unpassende Operandengr"o"se}
{Fehler}
{Der Operand hat zwar einen f"ur den Befehl
zugelassenen Typ, jedoch nicht die richtige L"ange (in
Bits).}
{keines}
\errentry{1131}{Widersprechende Operandengr"o"sen}
{Fehler}
{Die angegebenen Operanden haben unterschiedliche
L"angen (in Bit).}
{keines}
\errentry{1132}{Undefinierte Operandengr"o"se}
{Fehler}
{Aus Opcode und Operanden l"a"st sich die
Operandengr"o"se nicht eindeutig bestimmen (ein Problem
des 8086-Assemblers). Sie m"ussen die Operandengr"o"se
durch einen \tty{BYTE}, \tty{WORD}, usw. \tty{PTR}-Pr"afix
festlegen.}
{keines}
\errentry{1133}{Ganzzahl oder String erwartet, aber Gleitkommazahl erhalten}
{Fehler}
{An dieser Stelle kann keine Gleitkommazahl als Argument
verwendet werden.}
{das fehlerhafte Argument}
\errentry{1134}{Ganzzahl erwartet, aber Gleitkommazahl erhalten}
{Fehler}
{An dieser Stelle kann keine Gleitkommazahl als Argument
verwendet werden.}
{das fehlerhafte Argument}
\errentry{1136}{Gleitkommazahl erwartet, aber String erhalten}
{Fehler}
{An dieser Stelle kann kein String als Argument
verwendet werden.}
{das fehlerhafte Argument}
\errentry{1137}{Operandentyp-Diskrepanz}
{Fehler}
{Die beiden Argumente eines Operanden haben nicht
den gleichen Datentyp (Integer/Gleitkomma/String).}
{keines}
\errentry{1138}{String erwartet, aber Ganzzahl erhalten}
{Fehler}
{An dieser Stelle kann keine Ganzzahl als Argument
verwendet werden.}
{das fehlerhafte Argument}
\errentry{1139}{String erwartet, aber Gleitkommazahl erhalten}
{Fehler}
{An dieser Stelle kann keine Gleitkommazahl als Argument
verwendet werden.}
{das fehlerhafte Argument}
\errentry{1140}{zu viele Argumente}
{Fehler}
{Einem Befehl wurden mehr als die unter \asname{}
zul"assigen 20 Parameter "ubergeben.}
{keines}
\errentry{1141}{Ganzzahl erwartet, aber String erhalten}
{Fehler}
{An dieser Stelle kann kein String als Argument
verwendet werden.}
{das fehlerhafte Argument}
\errentry{1142}{Ganz- oder Gleitkommazahl erwartet, aber String erhalten}
{Fehler}
{An dieser Stelle kann kein String als Argument
verwendet werden.}
{das fehlerhafte Argument}
\errentry{1143}{String erwartet}
{Fehler}
{An dieser Stelle kann nur ein (in einfachen Hochkommas
eingeschlossener) String als Argument verwendet werden.}
{das fehlerhafte Argument}
\errentry{1144}{Ganzzahl erwartet}
{Fehler}
{An dieser Stelle kann nur eine ganze Zahl als Argument
verwendet werden.}
{das fehlerhafte Argument}
\errentry{1145}{Ganz-, Gleitkommazahl oder String erwartet, aber Register bekommen}
{Fehler}
{An dieser Stelle kann kein Registersymbol als Argument verwendet werden.}
{das fehlerhafte Argument}
\errentry{1146}{Ganzzahl oder String erwartet}
{Fehler}
{An dieser Stelle kann keine Gleitkommazahl oder Registersymbol als Argument verwendet werden.}
{das fehlerhafte Argument}
\errentry{1147}{Register erwartet}
{Fehler}
{An dieser Stelle kann nur ein Register als Argument verwendet werden.}
{das fehlerhafte Argument}
\errentry{1148}{Registersymbol f"ur anderes Ziel}
{Fehler}
{Das angesprochene Registersymbol wurde f"ur einen anderen Zielprozessor
als den aktuell verwendeten definiert und ist nicht kompatibel.}
{das fehlerhafte Argument}
\errentry{1149}{Gleitkomma-Argument erwartet, aber Ganzzahl bekommen}
{Fehler}
{An dieser Stelle kann kein Ganzzahl-, sondern nur ein Gleitkomma-
Argument verwendet werden.}
{das fehlerhafte Argument}
\errentry{1151}{Ganz- oder Gleitkommazahl erwartet, aber Register bekommen}
{Fehler}
{An dieser Stelle kann kein Register, sondern nur eine Ganz-
oder Gleitkommazahl als Argument verwendet werden.}
{das fehlerhafte Argument}
\errentry{1152}{Ganzzahl oder String erwartet, aber Register bekommen}
{Fehler}
{An dieser Stelle kann kein Register, sondern nur eine Ganzzahl
oder ein String als Argument verwendet werden.}
{das fehlerhafte Argument}
\errentry{1153}{Ganzzahl erwartet, aber Register bekommen}
{Fehler}
{An dieser Stelle kann kein Register, sondern nur eine Ganzzahl
als Argument verwendet werden.}
{das fehlerhafte Argument}
\errentry{1200}{Unbekannter Befehl}
{Fehler}
{Der benutzte Befehl ist weder ein Pseudobefehl
von \asname{} noch ein Befehl des momentan eingestellten
Prozessors.}
{keines}
\errentry{1300}{Klammerfehler}
{Fehler}
{Der Formelparser ist auf einen (Teil-)Ausdruck
gesto"sen, in dem die Summe "offnender und schlie"sender
Klammern nicht "ubereinstimmt.}
{der beanstandete (Teil-)Ausdruck}
\errentry{1310}{Division durch 0}
{Fehler}
{Bei einer Division oder Modulooperation ergab
die Auswertung des rechten Teilausdruckes 0.}
{keines}
\errentry{1315}{Bereichsunterschreitung}
{Fehler}
{Der angegebene Integer-Wert unterschreitet
den zul"assigen Bereich.}
{aktueller Wert und zul"assiges Minimum
(manchmal, ich stelle das seit Jahren um...)}
\errentry{1320}{Bereichs"uberschreitung}
{Fehler}
{Der angegebene Integer-Wert "uberschreitet
den zul"assigen Bereich.}
{aktueller Wert und zul"assiges Maximum
(manchmal, ich stelle das seit Jahren um...)}
\errentry{1322}{keine Zweierpotenz}
{Fehler}
{Hier sind nur Zweierpotenzen (1,2,4,8...)
als Wert erlaubt}
{der fragliche Wert}
\errentry{1325}{Adresse nicht ausgerichtet}
{Fehler}
{Die angegebene direkte Speicheradresse
entspricht nicht den Anspr"uchen des Datentransfers, d.h.
ist nicht ein mehrfaches der Operandengr"o"se. Nicht alle
Prozessoren erlauben unausgerichtete Datenzugriffe.}
{keines}
\errentry{1330}{Distanz zu gro"s}
{Fehler}
{Der in einem Adre"sausdruck enthaltene
Displacement-Wert ist zu gro"s.}
{keines}
\errentry{1331}{Ziel nicht auf gleicher Seite}
{Fehler}
{Befehl und Operandenadresse m"ussen
auf der gleichen Seite liegen.}
{das fragliche Adre"s-Argument}
\errentry{1340}{Kurzadressierung nicht m"oglich}
{Fehler}
{Die Adresse des Operanden liegt au"serhalb des
Speicherbereiches, in dem Kurzadressierung m"oglich ist.}
{keines}
\errentry{1350}{Unerlaubter Adressierungsmodus}
{Fehler}
{Der benutzte Adressierungsmodus existiert
generell zwar, ist an dieser Stelle aber nicht erlaubt.}
{keines}
\errentry{1351}{Adresse mu"s gerade sein}
{Fehler}
{An dieser Stelle sind nur gerade Adressen erlaubt,
da das unterste Bit f"ur andere Zwecke verwendet wird
oder reserviert ist.}
{das fragliche Argument}
\errentry{1352}{Adresse mu"s ausgerichtet sein}
{Fehler}
{An dieser Stelle sind nur ausgerichtete
(d.h glatt durch 2, 4, 8... teilbare) Adressen erlaubt,
da die untersten Bits f"ur andere Zwecke verwendet werden
oder reserviert sind.}
{das fragliche Argument}
\errentry{1355}{Adressierungsmodus im Parallelbetrieb nicht erlaubt}
{Fehler}
{Die verwendeten Adressierungsmodi
sind zwar im sequentiellen Modus zul"assig, jedoch nicht
bei parallelen Instruktionen.}
{keines}
\errentry{1360}{undefinierte Bedingung}
{Fehler}
{Die benutzte Bedingung f"ur bedingte Spr"unge
existiert nicht.}
{keines}
\errentry{1365}{inkompatible Bedingungen}
{Fehler}
{Die benutzte Kombination von Bedingungen kann nicht
in einem Befehl verwendet werden.}
{die Bedingung, bei der die Unvertr"aglichkeit
entdeckt wurde.}
\errentry{1366}{unbekanntes Flag}
{Fehler}
{Das angegebene Flag existiert nicht.}
{Das Argument mit dem fraglichen Flag}
\errentry{1367}{doppeltes Flag}
{Fehler}
{Das angegebene Flag wurde mehrfach in der Liste verwendet.}
{Das Argument mit dem doppelten Flag}
\errentry{1368}{unbekannter Interrupt}
{Fehler}
{Der angegebene Interrupt existiert nicht.}
{Das Argument mit dem fraglichen Interrupt}
\errentry{1369}{doppelter Interrupt}
{Fehler}
{Der angegebene Interrupt wurde mehrfach in der Liste verwendet.}
{Das Argument mit dem doppelten Interrupt}
\errentry{1370}{Sprungdistanz zu gro"s}
{Fehler}
{Sprungbefehl und Sprungziel liegen zu weit
auseinander, um mit einem Sprung der benutzten L"ange
"uberbr"uckt werden zu k"onnen.}
{keines}
\errentry{1371}{Sprungdistanz ist Null}
{Fehler}
{Sprungbefehl und Sprungziel liegen direkt hintereinander,
und eine Sprungdistanz von null kann nicht kodiert werden.}
{Die Zieladresse im Quellcode}
\errentry{1375}{Sprungdistanz ist ungerade}
{Fehler}
{Da Befehle nur auf geraden Adressen liegen
d"urfen, mu"s eine Sprungdistanz zwischen zwei Befehlen
auch immer gerade sein, das Bit 0 der Distanz wird
anderweitig verwendet. Diese Bedingung ist verletzt
worden. Grund ist "ublicherweise die Ablage einer
ungeraden Anzahl von Daten in Bytes oder ein falsches \tty{ORG}.}
{keines}
\errentry{1376}{Skip-Ziel passt nicht}
{Fehler}
{Das angegebene Sprungziel ist nicht die Adresse, die der
Prozessor bei Ausf"uhrung der Skip-Anweisung anspringen w"urde.}
{die angegebene (beabsichtigte) Sprungadresse}
\errentry{1380}{ung"ultiges Schiebeargument}
{Fehler}
{als Argument f"ur die Schiebeamplitude darf nur
eine Konstante oder ein Datenregister verwendet werden.
(nur 680x0)}
{keines}
\errentry{1390}{Nur Bereich 1..8 erlaubt}
{Fehler}
{Konstanten f"ur Schiebeamplituden oder
\tty{ADDQ}-Argumente d"urfen nur im Bereich 1..8 liegen. (nur
680x0)}
{keines}
\errentry{1400}{Schiebezahl zu gro"s}
{Fehler}
{(nicht mehr verwendet)}
{keines}
\errentry{1410}{Ung"ultige Registerliste}
{Fehler}
{Das Registerlisten-Argument von \tty{MOVEM}
oder \tty{FMOVEM} hat ein falsches Format. (nur 680x0)}
{keines}
\errentry{1420}{Ung"ultiger Modus mit CMP}
{Fehler}
{Die verwendete Operandenkombination von \tty{CMP}
ist nicht erlaubt. (nur 680x0)}
{keines}
\errentry{1430}{Ung"ultiger Prozessortyp}
{Fehler}
{Den mit \tty{CPU} angeforderten Zielprozessor kennt \asname{}
nicht.}
{der unbekannte Prozessortyp}
\errentry{1431}{Ung"ultiger FPU-Typ}
{Fehler}
{Den mit \tty{FPU} angeforderten numerischen Koprozessor kennt \asname{}
nicht.}
{der unbekannte FPU-Typ}
\errentry{1432}{Ung"ultiger PMMU-Typ}
{Fehler}
{Die mit \tty{PMMU} angeforderte MMU kennt \asname{} nicht.}
{der unbekannte PMMU-Typ}
\errentry{1440}{Ung"ultiges Kontrollregister}
{Fehler}
{Das bei z.B. \tty{MOVEC} benutzte
Kontrollregister kennt der mit CPU gesetzte Prozessor
(noch) nicht.}
{keines}
\errentry{1445}{Ung"ultiges Register}
{Fehler}
{Das benutzte Register ist zwar prinzipiell
vorhanden, hier aber nicht erlaubt.}
{keines}
\errentry{1446}{Register mehr als einmal gelistet}
{Fehler}
{Ein Register taucht in der Liste der zu sichernden bzw.
wiederherzustellenden Register mehrfach auf.}
{keines}
\errentry{1447}{Register-Bank-Diskrepanz}
{Fehler}
{In einem Adre"sausdruck werden Register aus unterschiedlichen
B"anken verwendet.}
{das fragliche Register}
\errentry{1448}{Registerl"ange undefiniert}
{Fehler}
{An dieser Stelle k"onnen Register verschiedener L"ange verwendet werden,
und die Registerl"ange ist nicht alleine aus der Adresse ableitbar.}
{das fragliche Argument}
\errentry{1449}{ung"ultige Operation auf Register}
{Fehler}
{Diese Operation kann auf dieses Register nicht angewendet werden, z.B.
weil das Register nur gelesen oder nur geschrieben werden darf.}
{das fragliche Register}
\errentry{1450}{RESTORE ohne SAVE}
{Fehler}
{Es wurde ein \tty{RESTORE}-Befehl gefunden, obwohl
kein mit \tty{SAVE} gespeicherter Zustand (mehr) auf dem Stapel
vorhanden ist.}
{keines}
\errentry{1460}{fehlendes RESTORE}
{Fehler}
{Nach der Assemblierung sind nicht alle
\tty{SAVE}-Befehle wieder aufgel"ost worden.}
{keines}
\errentry{1465}{unbekannte Makro-Steueranweisung}
{Fehler}
{Eine beim \tty{MACRO}-Befehl zus"atzlich angegebene
Steueranweisung ist \asname{} unbekannt.}
{die fragliche Anweisung}
\errentry{1470}{fehlendes ENDIF/ENDCASE}
{Fehler}
{Nach der Assemblierung sind nicht alle
Konstrukte zur bedingten Assemblierung aufgel"ost
worden.}
{keines}
\errentry{1480}{ung"ultiges IF-Konstrukt}
{Fehler}
{Die Reihenfolge der Befehle in einem \tty{IF}-
oder \tty{SWITCH}-Konstrukt stimmt nicht.}
{keines}
\errentry{1483}{doppelter Sektionsname}
{Fehler}
{Es existiert bereits eine Sektion gleichen
Namens auf dieser Ebene.}
{der doppelte Name}
\errentry{1484}{unbekannte Sektion}
{Fehler}
{Im momentanen Sichtbarkeitsbereich existiert
keine Sektion dieses Namens.}
{der unbekannte Name}
\errentry{1485}{fehlendes ENDSECTION}
{Fehler}
{Nach Ende eines Durchganges sind nicht alle
Sektionen wieder geschlossen worden.}
{keines}
\errentry{1486}{falsches ENDSECTION}
{Fehler}
{die bei \tty{ENDSECTION} angegebene Sektion
ist nicht die innerste offene.}
{keines}
\errentry{1487}{ENDSECTION ohne SECTION}
{Fehler}
{Es wurde ein \tty{ENDSECTION}-Befehl gegeben, obwohl
gar keine Sektion offen war.}
{keines}
\errentry{1488}{nicht aufgel"oste Vorw"artsdeklaration}
{Fehler}
{ein mit \tty{FORWARD} oder \tty{PUBLIC}
angek"undigtes Symbol wurde nicht in der Sektion definiert.}
{der Name des fraglichen Symbols, plus die
Position der Vorw"arts-Deklaration im Quelltext}
\errentry{1489}{widersprechende FORWARD $\leftrightarrow$PUBLIC-Deklaration}
{Fehler}
{Ein Symbol wurde sowohl als privat als auch
global definiert.}
{der Name des Symbols}
\errentry{1490}{falsche Argumentzahl f"ur Funktion}
{Fehler}
{Die Anzahl der Argumente f"ur eine
selbst definierte Funktion stimmt nicht mit der geforderten
Anzahl "uberein.}
{keines}
\errentry{1495}{unaufgel"oste Literale (LTORG fehlt)}
{Fehler}
{Am Programmende oder beim Umachalten
zu einem anderen Zielprozessor blieben noch nicht
abgelegte Literale "ubrig.}
{keines}
\errentry{1500}{Befehl auf dem ... nicht vorhanden}
{Fehler}
{Der benutzte Befehl existiert zwar
grunds"atzlich, das eingestellte Mitglied der
Prozessorfamilie beherrscht ihn aber noch nicht.}
{Die Prozessorvarianten, die diesen Befehl
unterst"utzen w"urden.}
\errentry{1501}{FPU-Befehle nicht freigeschaltet}
{Fehler}
{Die FPU-Befehlssatzerweiterungen m"ussen erlaubt
werden, um diesen Befehl zu benutzen}
{keines}
\errentry{1502}{PMMU-Befehle nicht freigeschaltet}
{Fehler}
{Die PMMU-Befehlssatzerweiterungen m"ussen erlaubt
werden, um diesen Befehl zu benutzen}
{keines}
\errentry{1503}{voller PMMU-Befehlssatz nicht freigeschaltet}
{Fehler}
{Dieser Befehl ist nur im Befehlssatz der
68851-PMMU enthalten, nicht im reduzierten
Befehlssatz der integrierten PMMU.}
{keines}
\errentry{1504}{Z80-Syntax nicht erlaubt}
{Fehler}
{Dieser Befehl ist nur erlaubt, wenn die
Z80-Syntax f"ur 8080/8085-Befehle freigeschaltet
wurde.}
{keines}
\errentry{1505}{Adressierungsart auf dem ... nicht vorhanden}
{Fehler}
{Der benutzte Adressierungsmodus existiert
zwar grunds"atzlich, das eingestellte Mitglied der
Prozessorfamilie beherrscht ihn aber noch nicht.}
{Die Prozessorvarianten, die diesen
Adressierungsmodus unterst"utzen w"urden.}
\errentry{1506}{nicht im Z80-Syntax Exklusiv-Modus erlaubt}
{Fehler}
{Dieser Befehl ist nicht (mehr) erlaubt, wenn nur
noch Z80-Syntax f"ur 8080/8085-Befehle erlaubt
wurde.}
{keines}
\errentry{1507}{FPU-Befehl auf dem ... nicht unterst"utzt}
{Fehler}
{Der benutzte FPU-Befehl existiert zwar
grunds"atzlich, der eingestellte FPU-Typ
beherrscht ihn aber noch nicht.}
{Der fragliche Befehl}
\errentry{1508}{Custom-Befehle nicht freigeschaltet}
{Fehler}
{Die benutzerdefinierten Befehlssatzerweiterungen
m"ussen erlaubt werden, um diesen Befehl zu benutzen.}
{Der fragliche Befehl}
\errentry{1509}{Befehls-Erweiterung nicht freigeschaltet}
{Fehler}
{Dieser Befehl ist Teil einer Befehlssatz-Erweiterung,
deren Benutzung nicht erlaubt wurde.}
{Der Name der Erweiterung}
\errentry{1510}{Ung"ultige Bitstelle}
{Fehler}
{Die angegebene Bitnummer ist nicht erlaubt
oder eine Angabe fehlt komplett.}
{keines}
\errentry{1520}{nur ON/OFF erlaubt}
{Fehler}
{Dieser Pseudobefehl darf als Argument nur \tty{ON}
oder \tty{OFF} haben.}
{keines}
\errentry{1530}{Stack ist leer oder nicht definiert}
{Fehler}
{Es wurde bei einem \tty{POPV}
einen Stack anzusprechen, der entweder nie definiert oder
bereits leerger"aumt wurde.}
{der Name des fraglichen Stacks}
\errentry{1540}{Nicht genau ein Bit gesetzt}
{Fehler}
{In einer Bitmaske, die der \tty{BITPOS}-
Funktion "ubergeben wurde, war nicht genau ein Bit
gesetzt.}
{keines}
\errentry{1550}{ENDSTRUCT ohne STRUCT}
{Fehler}
{Eine \tty{ENDSTRUCT}-Anweisung wurde gegeben, obwohl
momentan keine Strukturdefinition in Gange war.}
{keines}
\errentry{1551}{offene Strukturdefinition}
{Fehler}
{Nach Ende der Assemblierung waren noch nicht alle
\tty{STRUCT}-Anweisungen durch passende \tty{ENDSTRUCT}s
abgeschlossen.}
{die innerste, noch nicht abgeschlossene
Strukturdefinition}
\errentry{1552}{falsches ENDSTRUCT}
{Fehler}
{Der Namensparameter einer \tty{ENDSTRUCT}-Anweisung
entspricht nicht der innersten, offenen
Strukturdefinition.}
{keines}
\errentry{1553}{Phasendefinition nicht in Strukturen erlaubt}
{Fehler}
{Was gibt es dazu zu sagen? \tty{PHASE} in einem Record
ergibt einfach keinen Sinn und nur Verwirrung...}
{keines}
\errentry{1554}{ung"ultige \tty{STRUCT}-Direktive}
{Fehler}
{Als Direktive f"ur \tty{STRUCT} ist nur
\tty{EXTNAMES}, \tty{NOEXTNAMES}, \tty{DOTS} und
\tty{NODOTS} zugelassen.}
{die unbekannte Direktive}
\errentry{1555}{Struktur redefiniert}
{Fehler}
{Eine Struktur dieses Namens wurde bereits definiert.}
{der Name der Struktur}
\errentry{1556}{nicht aufl"osbare Strukturelement-Referenz}
{Fehler}
{Ein Element bezieht sich auf ein anderes Element in
einer Strukturdefintions, dieses ist aber nicht
definiert oder dessen Referenz selber is nicht
aufl"osbar.}
{Name des Elements und seine Referenz}
\errentry{1557}{Strukturelement doppelt}
{Fehler}
{Ein Element dieses Namens ist bereits in der Struktur
enthalten.}
{Name des Elements}
\errentry{1560}{Anweisung nicht wiederholbar}
{Fehler}
{Diese Maschinenanweisung kann nicht mit Hilfe eines
{\tt RPT}-Konstruktes wiederholt werden.}
{keines}
\errentry{1600}{vorzeitiges Dateiende}
{Fehler}
{Es wurde mit einem \tty{BINCLUDE}-Befehl versucht,
"uber das Ende einer Datei hinauszulesen.}
{keines}
\errentry{1700}{ROM-Offset geht nur von 0..63}
{Fehler}
{Das Konstanten-ROM der 680x0-Koprozessoren hat
nur max. 63 Eintr"age.}
{keines}
\errentry{1710}{Ung"ultiger Funktionscode}
{Fehler}
{Als Funktionscodeargument darf nur SFC, DFC, ein
Datenregister oder eine Konstante von 0..15 verwendet
werden. (nur 680x0-MMU)}
{keines}
\errentry{1720}{Ung"ultige Funktionscodemaske}
{Fehler}
{Als Funktionscodemaske darf nur ein Wert von
0..15 verwendet werden. (nur 680x0-MMU)}
{keines}
\errentry{1730}{Ung"ultiges MMU-Register}
{Fehler}
{Die MMU hat kein Register mit dem angegebenen
Namen. (nur 680x0-MMU)}
{keines}
\errentry{1740}{Level nur von 0..7}
{Fehler}
{Die Ebene f"ur \tty{PTESTW} und \tty{PTESTR} mu"s eine
Konstante von 0..7 sein. (nur 680x0-MMU)}
{keines}
\errentry{1750}{ung"ultige Bitmaske}
{Fehler}
{Die bei den Bit-Feld-Befehlen angegebene
Bitmaske hat ein falsches Format. (nur 680x0)}
{keines}
\errentry{1760}{ung"ultiges Registerpaar}
{Fehler}
{Das angegebene Registerpaar ist hier nicht
verwendbar oder syntaktisch falsch. (nur 680x0)}
{keines}
\errentry{1800}{offene Makrodefinition}
{Fehler}
{Eine Makrodefinition war am Dateiende nicht
abgeschlossen. Vermutlich fehlt ein \tty{ENDM}.}
{keines}
\errentry{1801}{IRP ohne ENDM}
{Fehler}
{Ein IRP-Block war am Dateiende nicht
abgeschlossen. Vermutlich fehlt ein \tty{ENDM}.}
{keines}
\errentry{1802}{IRPC ohne ENDM}
{Fehler}
{Ein IRPC-Block war am Dateiende nicht
abgeschlossen. Vermutlich fehlt ein \tty{ENDM}.}
{keines}
\errentry{1803}{REPT ohne ENDM}
{Fehler}
{Ein REPT-Block war am Dateiende nicht
abgeschlossen. Vermutlich fehlt ein \tty{ENDM}.}
{keines}
\errentry{1804}{WHILE ohne ENDM}
{Fehler}
{Ein WHILE-Block war am Dateiende nicht
abgeschlossen. Vermutlich fehlt ein \tty{ENDM}.}
{keines}
\errentry{1805}{EXITM au"serhalb eines Makrorumpfes}
{Fehler}
{\tty{EXITM} bricht die Expansion von
Makro-Konstrukten ab. Dieser Befehl macht nur innerhalb
von Makros Sinn und es wurde versucht, ihn au"serhalb
aufzurufen.}
{keines}
\errentry{1810}{mehr als 10 Makroparameter}
{Fehler}
{Ein Makro darf h"ochstens 10 Parameter haben.}
{keines}
\errentry{1811}{Schl"usselwortargument nicht in Makro definiert}
{Fehler}
{Ein Schl"usselwortargument bezog sich auf einen
Parameter, den das aufgerufene Makro gar nicht
besitzt.}
{verwendetes Schl"usselwort bzw. Makroparameter}
\errentry{1812}{Positionsargument nach Schl"usselwortargumenten nicht mehr erlaubt}
{Fehler}
{Positions- und Schl"usselwortargumente d"urfen in
einem Makroaufruf gemischt werden, aber nach dem
ersten Schl"usselwortargument sind nur noch
solche zugelassen.}
{keines}
\errentry{1815}{doppelte Makrodefinition}
{Fehler}
{Ein Makronamne wurde in einer Sektion doppelt
vergeben.}
{der doppelt verwendete Name}
\errentry{1820}{Ausdruck mu"s im ersten Pass berechenbar sein}
{Fehler}
{Der benutzte Befehl beeinflu"st die Codel"ange,
daher sind Vorw"artsreferenzen hier nicht erlaubt.}
{keines}
\errentry{1830}{zu viele verschachtelte IFs}
{Fehler}
{(nicht mehr verwendet)}
{keines}
\errentry{1840}{ELSEIF/ENDIF ohne ENDIF}
{Fehler}
{es wurde ein \tty{ELSEIF}- oder \tty{ENDIF}-Befehl gefunden,
obwohl kein offener \tty{IF}-Befehl vorhanden ist.}
{keines}
\errentry{1850}{verschachtelter/rekursiver Makroaufruf}
{Fehler}
{(nicht mehr verwendet)}
{keines}
\errentry{1860}{unbekannte Funktion}
{Fehler}
{Die angesprochene Funktion ist weder eingebaut
noch nachtr"aglich definiert worden.}
{der Funktionsname}
\errentry{1870}{Funktionsargument au"serhalb Definitionsbereich}
{Fehler}
{Das Argument liegt nicht im Bereich der
angesprochenen transzendenten Funktion.}
{keines}
\errentry{1880}{Gleitkomma"uberlauf}
{Fehler}
{Das Argument liegt zwar im Bereich der
angesprochenen transzendenten Funktion, das Ergebnis
w"are aber nicht mehr darstellbar.}
{keines}
\errentry{1890}{ung"ultiges Wertepaar}
{Fehler}
{Das benutzte P"archen aus Basis und Exponent
kann nicht berechnet werden.}
{keines}
\errentry{1900}{Befehl darf nicht auf dieser Adresse liegen}
{Fehler}
{Die Prozessorhardware erlaubt keine
Spr"unge von dieser Adresse.}
{keines}
\errentry{1905}{ung"ultiges Sprungziel}
{Fehler}
{Die Prozessorhardware erlaubt keine
Spr"unge zu dieser Adresse.}
{keines}
\errentry{1910}{Sprungziel nicht auf gleicher Seite}
{Fehler}
{Sprungbefehl und Sprungziel m"ussen bei diesem
Befehl auf der gleichen Seite liegen.}
{keines}
\errentry{1911}{Sprungziel nicht in gleicher Sektion}
{Fehler}
{Sprungbefehl und Sprungziel m"ussen bei diesem
Befehl in der gleichen (64K-)Sektion liegen.}
{keines}
\errentry{1920}{Code"uberlauf}
{Fehler}
{Es wurde versucht, mehr als 1024 Bytes Code oder
Daten in einer Zeile zu erzeugen.}
{keines}
\errentry{1925}{Adre"s"uberlauf}
{Fehler}
{Der Adre"sraum dieses Prozessors wurde
"uberschritten.}
{keines}
\errentry{1930}{Konstanten und Platzhalter nicht mischbar}
{Fehler}
{Anweisungen, die Speicher reservieren und solche,
die ihn mit Konstanten belegen, d"urfen nicht in einer
Pseudoanweisung gemischt werden.}
{keines}
\errentry{1940}{Codeerzeugung in Strukturdefinition nicht zul"assig}
{Fehler}
{Ein \tty{STRUCT}-Konstrukt dient nur der Beschreibung
einer Datenstruktur und nicht dem Anlegen einer solchen,
es sind daher keine Befehle zugelassen, die Code erzeugen.}
{keines}
\errentry{1950}{Paralleles Konstrukt nicht m"oglich}
{Fehler}
{Entweder sind die beiden Instruktionen
prinzipiell nicht parallel ausf"uhrbar, oder sie stehen nicht
unmittelbar untereinander.}
{keines}
\errentry{1960}{ung"ultiges Segment}
{Fehler}
{Das angegebene Segment ist an dieser Stelle
nicht anwendbar.}
{der benutzte Segmentname}
\errentry{1961}{unbekanntes Segment}
{Fehler}
{Das angegebene Segment existiert bei
diesem Prozessor nicht.}
{der benutzte Segmentname}
\errentry{1962}{unbekanntes Segmentregister}
{Fehler}
{Das angegebene Segmentregister existiert
nicht (nur 8086).}
{keines}
\errentry{1970}{ung"ultiger String}
{Fehler}
{Der angegebene String hat ein ung"ultiges
Format.}
{keines}
\errentry{1980}{ung"ultiger Registername}
{Fehler}
{Das angegebene Register existiert nicht oder
darf hier nicht verwendet werden.}
{keines}
\errentry{1985}{ung"ultiges Argument}
{Fehler}
{Der angegebene Befehl darf nicht mit einem
\tty{REP}-Pr"afix versehen werden.}
{keines}
\errentry{1990}{keine Indirektion erlaubt}
{Fehler}
{in dieser Kombination ist keine indirekte
Adressierung erlaubt.}
{keines}
\errentry{1995}{nicht im aktuellen Segment erlaubt}
{Fehler}
{(nicht mehr verwendet)}
{keines}
\errentry{1996}{nicht im Maximum-Modus zul"assig}
{Fehler}
{Dieses Register ist nur im Minimum-Modus
definiert.}
{keines}
\errentry{1997}{nicht im Minimum-Modus zul"assig}
{Fehler}
{Dieses Register ist nur im Maximum-Modus
definiert.}
{keines}
\errentry{2000}{Anweisungspaket "uberschreitet Adre"sgrenze}
{Fehler}
{Ein Anweisungspaket darf nicht "uber eine
32-Byte-Adre"sgrenze reichen.}
{keines}
\errentry{2001}{Ausf"uhrungseinheit mehrfach benutzt}
{Fehler}
{Eine der Ausf"uhrungseinheiten des Prozessors wurde in
einem Anweisungspaket mehrfach benutzt.}
{der Name der Funktionseinheit}
\errentry{2002}{mehrfache Lang-Leseoperation}
{Fehler}
{Ein Ausf"uhrungspaket enth"alt mehr als eine
Lang-Leseoperation, was nicht erlaubt ist.}
{eine der Funktionseinheiten, auf denen eine
Lang-Leseoperation ausgef"uhrt wird}
\errentry{2003}{mehrfache Lang-Schreiboperation}
{Fehler}
{Ein Ausf"uhrungspaket enth"alt mehr als eine
Lang-Schreiboperation, was nicht erlaubt ist.}
{eine der Funktionseinheiten, auf denen eine
Lang-Schreiboperation ausgef"uhrt wird}
\errentry{2004}{Lang-Lese- mit Schreiboperation}
{Fehler}
{Ein Ausf"uhrungspaket enth"alt sowohl eine
Lang-Leseoperation als auch eine Schreiboperation,
was nicht erlaubt ist.}
{eine der Funktionseinheiten, deren Operationen im
Konflikt stehen.}
\errentry{2005}{zu viele Lesezugriffe auf ein Register}
{Fehler}
{Auf das gleiche Register wurde mehr als viermal im
gleichen Anweisungspaket Bezug genommen.}
{der Name des Registers, das zu oft referenziert wurde}
\errentry{2006}{"uberlappende Ziele}
{Fehler}
{Auf das gleiche Register wurde mehrfach im gleichen
Ausf"uhrungspaket geschrieben, was nicht erlaubt ist.}
{der Name der fraglichen Registers}
\errentry{2008}{zu viele absolute Spr"unge in einem Anweisungspaket}
{Fehler}
{Ein Anweisungspaket beinhaltet mehr als einen direkten
Sprung, was nicht erlaubt ist.}
{keines}
\errentry{2009}{Anweisung nicht auf diese Funktionseinheit ausf"uhrbar}
{Fehler}
{Diese Anweisung kann nicht auf dieser Funktionseinheit
ausgef"uhrt werden.}
{keines}
\errentry{2010}{Ung"ultige Escape-Sequenz}
{Fehler}
{Das mit einem Backslash eingeleitete
Sonderzeichen ist nicht definiert.}
{keines}
\errentry{2020}{ung"ultige Pr"afix-Kombination}
{Fehler}
{Die angegebene Kombination von Pr"afixen
ist nicht zul"assig oder nicht im
Maschinenkode darstellbar.}
{keines}
\errentry{2030}{Konstante kann nicht als Variable redefiniert werden}
{Fehler}
{Ein einmal mit {\tt EQU} als Konstante\\
definiertes Symbol kann nicht nachtr"aglich mit\\
{\tt SET} ver"andert werden.}
{der Name des fraglichen Symbols}
\errentry{2035}{Variable kann nicht als Konstante redefiniert werden}
{Fehler}
{Ein einmal mit {\tt SET} als Variable\\
definiertes Symbol kann nicht nachtr"aglich als\\
Konstante deklariert werden (z.B. mit {\tt EQU}.}
{der Name des fraglichen Symbols}
\errentry{2040}{Strukturname fehlt}
{Fehler}
{Bei einer Strukturdefinition fehlt der zugeh"orende
Name f"ur die Struktur.}
{keines}
\errentry{2050}{leeres Argument}
{Fehler}
{In der Argumentenliste dieser Anweisung d"urfen keine
Leerstrings benutzt werden.}
{keines}
\errentry{2060}{nicht implementierte Anweisung}
{Fehler}
{Der benutzte Maschinenbefehl ist dem Assembler
zwar bekannt, ist aber aufgrund fehlender
Dokumentation seitens des Prozessorherstellers
momentan nicht implementiert.}
{Der benutzte Befehl}
\errentry{2070}{namenlose Struktur nicht Teil einer anderen Struktur}
{Fehler}
{Eine Struktur oder Union, die keinen Namen hat, mu"s
immer Teil einer anderen, benamten Struktur oder Union
sein.}
{keines}
\errentry{2080}{STRUCT durch ENDUNION beendet}
{Fehler}
{ENDUNION darf nur zum Beenden der Definition einer
Union benutzt werden, nicht einer Struktur.}
{Name der Struktur (falls vorhanden)}
\errentry{2090}{Speicheradresse nicht auf aktiver Seite}
{Fehler}
{Die Zieladresse befindet sich nicht in der durch
das Seitenregister aktuell adressierbaren
Speicherseite.}
{keines}
\errentry{2100}{unbekanntes Makro-Expansions-Argument}
{Fehler}
{Ein \tty{MACEXP\_DFT/OVR} gegebenes Argument konnte nicht
interpretiert werden.}
{das unbekannte Argument}
\errentry{2105}{zu viele Makro-Expansions-Argumente}
{Fehler}
{Die Anzahl der Argument zur Makro-Expansion hat ihre Maximalzahl "uberschritten}
{das Argument, das zu viel ist}
\errentry{2110}{widerspr"uchliche Angaben zur Makro-Expansion}
{Fehler}
{Eine Angabe zur Makroexpansion und ihr genaues
Gegenteil d"urfen nicht gleichzeitig als Argument
von \tty{MACEXP\_DFT/OVR} verwendet werden.}
{keines}
\errentry{2130}{erwarteter Fehler nicht eingetreten}
{Fehler}
{Ein per {\tt EXPECT} angek"undigter Fehler oder Warnung ist
in dem durch {\tt ENDEXPECT} abgeschlossenen Block nicht aufgetreten.}
{Der erwartete Fehler}
\errentry{2140}{Verschachtelung von EXPECT/ENDEXPECT nicht erlaubt}
{Fehler}
{Durch {\tt EXPECT/ENDEXPECT} eingerahmte Bl"ocke d"urfen keine
geschachtelten {\tt EXPECT/ENDEXPECT}-Bl"ocke enthalten.}
{keines}
\errentry{2150}{fehlendes ENDEXPECT}
{Fehler}
{Ein per {\tt EXPECT} ge"offneter Block wurde nicht per
{\tt ENDEXPECT} abgeschlossen.}
{keines}
\errentry{2160}{ENDEXPECT ohne EXPECT}
{Fehler}
{Zu einem {\tt ENDEXPECT} gibt es kein vorhergehendes {\tt EXPECT}.}
{keines}
\errentry{2170}{kein Default-Checkpoint-Register definiert}
{Fehler}
{Bei einer Typ-12-Instruktion wurde kein Checkpoint-Register angegeben
und es wurde auch keines "uber die {\tt CKPT}-Anweisung vorher definiert.}
{keines}
\errentry{2180}{ung"ultiges Bitfeld}
{Fehler}
{Das Bitfeld entspricht nicht der erwarteten {\tt (start,count)}-Syntax.}
{das fragliche Argument}
\errentry{2190}{Argument-Wert fehlt}
{Fehler}
{Argumente m"ussen die Form 'variable=wert' haben.}
{das fragliche Argument}
\errentry{2200}{unbekanntes Argument}
{Fehler}
{Dieses Variable wird von der gew"ahlten Zielplattform nicht unterst"utzt.}
{das fragliche Argument}
\errentry{2210}{Indexregister muss 16 Bit sein}
{Fehler}
{Indexregister beim Z8000 m"ussen eine L"ange von 16 Bit (Rn) haben.}
{das fragliche Argument}
\errentry{2211}{I/O Adressregister muss 16 Bit sein}
{Fehler}
{Z8000-Register, um I/O-Adressen zu adressieren, m"ussen eine L"ange von 16 Bit (Rn) haben.}
{das fragliche Argument}
\errentry{2212}{Adressregister im segmentierten Modus muss 32 Bit sein}
{Fehler}
{Z8000-Register, um Speicheradressen im segmentierten Modus zu adressieren, m"ussen
eine L"ange von 32 Bit (RRn) haben.}
{das fragliche Argument}
\errentry{2213}{Adressregister im nicht-segmentierten Modus muss 16 Bit sein}
{Fehler}
{Z8000-Register, um Speicheradressen im nicht-segmentierten Modus zu adressieren, m"ussen
eine L"ange von 16 Bit (Rn) haben.}
{das fragliche Argument}
\errentry{2220}{ung"ultiges Strukturargument}
{Fehler}
{Das Argument entspricht keinem der Argumente, die bei der Expansion einer
Struktur erlaubt sind.}
{das fragliche Argument}
\errentry{2221}{zu viele Array-Dimensionen}
{Fehler}
{Arrays von Strukturen d"urfen maximal drei Dimensionen haben.}
{die Dimension, die zu viel ist}
\errentry{2230}{unbekannte Integer-Notation}
{Fehler}
{Die angegebene Integer-Notation existiert nicht, oder es fehlt das
f"uhrende Plus/Minuszeichen.}
{das fehlerhafte Argument}
\errentry{2231}{ung"ultige Liste an Integer-Schreibweisen}
{Fehler}
{Die geforderte "Anderung der Liste von benutzbaren Integer-Schreibweisen
kann nicht vorgenommen werden, weil sie zu einem Widerspruch f"uhren
w"urde. Aktuell betrifft dies lediglich 0hex und 0oct, die nicht
gleichzeitig verwendet werden d"urfen.}
{keines}
\errentry{2240}{ung"ultige Skalierung}
{Fehler}
{Das angegebene Argument kann nicht als Skalierungsfaktor benutzt werden.}
{das fragliche Argument}
\errentry{2250}{widerspr"uchliche String-Optionen}
{Fehler}
{Das angegebene String-Option steht im Widerspruch zu einer vorherigen in der Liste.}
{die fragliche Option}
\errentry{2251}{unbekannte String-Option}
{Fehler}
{Das angegebene String-Option gibt es nicht.}
{die fragliche Option}
\errentry{2252}{ung"ultiger Cache-Invalidierungs-Modus}
{Fehler}
{Es k"onnen nur Daten-, Instruktions- oder beide Caches invalidiert werden.}
{das fragliche Argument}
\errentry{2253}{ung"ultige Config-Liste}
{Fehler}
{Die Konfigurationsliste ist entweder insgesamt syntaktisch falsch oder
enth"alt ung"ultige Elemente.}
{Die fragliche Liste oder ein Element daraus.}
\errentry{2254}{widerspr"uchliche Konfig-Optionen}
{Fehler}
{Das angegebene Option steht im Widerspruch zu einer vorherigen in der Liste oder ist dazu identisch.}
{die fragliche Option}
\errentry{2255}{unbekannte Konfig-Option}
{Fehler}
{Das angegebene Option gibt es nicht.}
{die fragliche Option}
\errentry{2260}{ung"ultiger Wert f"ur CBAR}
{Fehler}
{Dieser CBAR-Wert ist nicht erlaubt (CA mu"s gr"o"ser als BA sein).}
{keines}
\errentry{2270}{Seite nicht zugreifbar}
{Fehler}
{Die Zieladresse liegt auf einer Speicherseite, die aktuell nicht
zugreifbar ist.}
{keines}
\errentry{2280}{Feld nicht zugreifbar}
{Fehler}
{Die Zieladresse liegt in einem Speicherfeld, das aktuell nicht
zugreifbar ist.}
{keines}
\errentry{2281}{Ziel nicht in gleichem Feld}
{Fehler}
{Befehl und Operandenadresse m"ussen
im gleichen Speicherfeld liegen.}
{keines}
\errentry{2290}{Ung"ultige Instruktions-Kombination}
{Fehler}
{Diese Befehle k"onnen nicht miteinander kombiniert werden.}
{keines}
\errentry{2300}{nicht-gemapptes Zeichen}
{Fehler}
{Die Zeichenkette enth"alt einen nicht abbildbares Zeichen.}
{die fragliche Zeichenkette}
\errentry{2310}{Multi-Zeichenkonstante mit ung"ultiger L"ange}
{Fehler}
{Multi-Zeichenkonstanten m"ussen zwischen ein und vier Zeichen lang sein.}
{keines}
\errentry{2320}{kein Target gesetzt ('CPU ...' oder '-cpu ...', um eines zu setzen)}
{fatal}
{Es wurde noch kein Target gesetzt, der Assembler wei"s daher
nicht, f"ur welche CPU Code erzeugt werden soll.}
{keines}
\errentry{10001}{Fehler bein "Offnen der Datei}
{fatal}
{Beim Versuch, eine Datei zu "offnen, ist ein
Fehler aufgetreten.}
{Beschreibung des E/A-Fehlers}
\errentry{10002}{Listingschreibfehler}
{fatal}
{Beim Schreiben des Assemblerlistings ist ein
Fehler aufgetreten.}
{Beschreibung des E/A-Fehlers}
\errentry{10003}{Dateilesefehler}
{fatal}
{Beim Lesen aus einer Quelldatei ist ein
Fehler aufgetreten.}
{Beschreibung des E/A-Fehlers}
\errentry{10004}{Dateischreibfehler}
{fatal}
{Beim Schreiben von Code- oder Share-Datei
ist ein Fehler aufgetreten.}
{Beschreibung des E/A-Fehlers}
\errentry{10006}{Speicher"uberlauf}
{fatal}
{Der verf"ugbare Speicher reicht nicht mehr,
alle Datenstrukturen aufzunehmen. Weichen Sie auf die
DPMI- oder OS/2-Version von \asname{} aus.}
{keines}
\errentry{10007}{Stapel"uberlauf}
{fatal}
{Der Programmstapel ist wegen zu komplizierter
Formelausdr"ucke oder einer ung"unstigen Anlage der Symbol-
oder Makrotabelle "ubergelaufen. Versuchen Sie es noch
einmal mit der \tty{-A}-Option.}
{keines}
\errentry{10008}{INCLUDE zu tief verschachtelt}
{fatal}
{Die Include-Verschachtelungstiefe hat das gegebene Limit
(im Default 200) "uberschritten. Dieses Limit kann "uber
den {\tt -maxinclevel}-Schalter herauf gesetzt werden, eine
fehlerhafte (rekusive) Verschachtelung ist aber die
wahrscheinlichere Ursache.}
{Die INCLUDE-Anweisung, mit der das Limit "uberschritten wurde.}
\end{description}
%%===========================================================================
\cleardoublepage
Die hier aufgelisteten Fehlermeldungen werden nicht nur von \asname{} bei E/A-
Fehlern ausgegeben, sondern auch von den Hilfsprogrammen PLIST, BIND,
P2HEX und P2BIN. Es sind nur die Fehler n"aher erkl"art, die m.E. bei
der Arbeit auftreten k"onnen. Sollte doch einmal ein nicht erl"auterter
E/A-Fehler auftreten, so d"urfte der Grund in einem Programmfehler
liegen. Melden Sie dies unbedingt!!
\begin{description}
\item[2]{Datei nicht gefunden\\
Die angegebene Datei existiert nicht oder liegt auf einem
anderen Laufwerk.}
\item[3]{Pfad nicht gefunden\\
Der Pfad eines Dateinamens existiert nicht oder liegt auf
einem anderen Laufwerk.}
\item[4]{zu viele offene Dateien\\
DOS sind die Dateihandles ausgegangen. Erh"ohen Sie die
\tty{FILES=}-Angabe in der CONFIG.SYS.}
\item[5]{Dateizugriff verweigert\\
Entweder reichen die Netzwerkrechte f"ur einen Dateizugriff
nicht, oder es wur\-de ver\-sucht, ei\-ne schreib\-ge\-sch"utz\-te Da\-tei
zu "uber\-schrei\-ben oder zu ver\-"an\-dern. Bei Benutzung in
DOS- Fenstern von Multitasking- Systemen ist es "uberdies m"oglich,
da"s ein andere Proze"s die Datei in exklusivem Zugriff hat.}
\item[6]{ung"ultiger Dateihandle}
\item[12]{ung"ultiger Zugriffsmodus}
\item[15]{ung"ultiger Laufwerksbuchstabe\\
Das angesprochene Laufwerk existiert nicht.}
\item[16]{aktuelles Verzeichnis kann nicht gel"oscht werden}
\item[17]{RENAME geht nicht "uber Laufwerke}
\item[100]{vorzeitiges Dateiende\\
Eine Datei war zuende, obwohl sie es aufgrund ihrer Struktur
noch nicht sein d"urfte. Vermutlich ist sie besch"adigt.}
\item[101]{Diskette/Platte voll\\
Das spricht wohl f"ur sich! Aufr"aumen!!}
\item[103]{Datei nicht offen}
\item[104]{Datei nicht f"ur Einlesen offen}
\item[105]{Datei nicht f"ur Ausgaben offen}
\item[106]{Ung"ultiges numerisches Format}
\item[150]{Diskette ist schreibgesch"utzt\\
Wenn Sie schon keine Festplatte als Arbeitsmedium verwenden,
so sollten Sie wenigstens den Schreibschutz entfernen!}
\item[151]{Unbekanntes Ger"at\\
Sie haben versucht, ein Peripherieger"at anzusprechen, welches
DOS unbekannt ist. Dies sollte normalerweise nicht auftreten,
da der Name dann automatisch als Datei interpretiert wird.}
\item[152]{Laufwerk nicht bereit\\
Schlie"sen Sie die Klappe des Diskettenlaufwerks.}
\item[153]{unbekannte DOS-Funktion}
\item[154]{Pr"ufsummenfehler auf Diskette/Platte\\
Ein harter Lesefehler auf der Diskette. Nochmal versuchen; wenn
immer noch vorhanden, Diskette neu formatieren bzw. ernste Sorgen
um Festplatte machen!}
\item[155]{ung"ultiger DPB}
\item[156]{Positionierfehler\\
Der Platten/Disketten-Controller hat eine bestimmte Spur nicht
gefunden. Siehe Nr. 154!}
\item[157]{unbekanntes Sektorformat\\
DOS kann mit dem Format der Diskette nichts anfangen.}
\item[158]{Sektor nicht gefunden\\
Analog zu Nr. 158, nur da"s hier der angeforderte Sektor auf
der Spur nicht gefunden werden konnte.}
Offensichtlich haben Sie die Ausgaben von \asname{} direkt auf einen
Drucker umgeleitet. Assemblerlistings k"onnen seeehr lang
sein...}
\item[160]{Ger"atelesefehler\\
Nicht n"aher vom Ger"atetreiber klassifizierter Lesefehler.}
\item[161]{Ger"ateschreibfehler\\
Nicht n"aher vom Ger"atetreiber klassifizierter Schreibfehler.}
\item[162]{allgemeiner Ger"atefehler\\
Hier ist der Ger"atetreiber v"ollig ratlos, was passiert
sein k"onnte.}
\end{description}
%%===========================================================================
\cleardoublepage
Manche Fragen, wie man dieses oder jenes realisiert, werden h"aufiger gestellt,
und es ist vielleicht wert, sie in einer 'Tipps und Tricks' Ecke zu
dokumentieren. Hier in diesem Kapitel werde ich sie sammeln und vorstellen:
Viele 8-Bit-Prozessoren k"onnen - wie der Name schon sagt - immer nur acht Bit
auf einmal verarbeiten. Oft sind jedoch genug Register vorhanden, um zwei
davon zu einem virtuellen '16 Bit Akkumulator' zusammenzufassen. Nun soll dieser
per Makro definierte Befehlssatz m"oglichst die gleichen Adressierungsarten
wie die Hardware-Befehle unterst"utzen. Dazu m"u"ste man die Makro-Argumente
irgendwie parsen - aber wie?
Der Motorola 6800 hat zum Beispiel zwei Akkumulatoren A und B, und es liegt
nahe, diese als einem 16-Bit-Akku zu behandeln. Die Adressierungsarten
sollten die gleichen sein wie bei 8-Bit-Operationen:
\begin{itemize}
\item{direkt (Adresse innerhalb der ersten 256 Byte)}
\item{erweitert (beliebige Adresse)}
\end{itemize}
Ein Makro, das so einen virtuellen 16-Bit-Befehl implementiert, mu"s die ein oder
zwei Argumente also analysieren:
\begin{enumerate}
\item{Indizierte Adressierung hat als einzige zwei Argumente.}
\item{Immediate-Adressierung ist am f"uhrenden Hash-Zeichen zu erkennen.}
\item{Ob eine Adresse in den ersten 256 Byte liegt oder nicht, kann man
wieder dem Assembler "uberlassen.}
\end{enumerate}
Um Punkt 2 auszuf"uhren, mu"s ein Argument in einen String "uberf"uhrt werden. Von
diesem kann das f"uhrend Hash-Zeichen dann auch entfernt werden, um den eigentlichen
Wert zu evaluieren. Komplett ausgeschrieben sieht das Makro dann so aus:
\begin{verbatim}
subd macro ARG1,ARG2
if "ARG2" != "" ; indexed?
suba (ARG1)+1,ARG2
sbcb ARG1,ARG2
elseif ; not indexed?
_SARG1 set "ARG1" ; convert to string
if substr(_SARG1,0,1)='#' ; immediate?
_SARG1 set substr(_SARG1,1,strlen(_SARG1)-1) ; yes->remove #
suba #lo(VAL(_SARG1)) ; ...and subtract lo/hi bytes
sbcb #hi(VAL(_SARG1))
elseif ; no immediate->ext. or direct
suba (ARG1)+1 ; and subtract lo/hi bytes
sbcb ARG1
endif
endif
endm
\end{verbatim}
Makroargumente wurden bewusst in Gro"sbuchstaben geschrieben, so dass das Makro
unabh"angig davon funktioniert, ob der case-sensitve Modus eingeschaltet ist
oder nicht. Verwendet werden kann das Makro z.B. so:
\begin{verbatim}
subd $0007 ; direct
subd $1234 ; absolute
subd #$55aa ; immediate
subd $12,x ; indexed
\end{verbatim}
Jetzt ist es aber so, dass man nicht nur 16-bittig subtrahieren möchte. Man
k"onnte f"ur jede Operation eine eigene Version des Makros hinschreiben, es
geht aber auch eleganter. Ein Makro kann selber wieder eine Makro-Definition
enthalten. Man kann also ein 'Meta-Makro' definieren, das die Befehlsnamen
als Argumente erh"alt:
\begin{verbatim}
def16 macro NEWINST,LOINST,HIINST
NEWINST macro ARG1,ARG2
if "ARG2" != "" ; indexed?
LOINST (ARG1)+1,ARG2
HIINST ARG1,ARG2
elseif ; not indexed?
_SARG1 set "ARG1" ; convert to string
if substr(_SARG1,0,1)='#' ; immediate?
_SARG1 set substr(_SARG1,1,strlen(_SARG1)-1) ; yes->remove #
LOINST #lo(VAL(_SARG1)) ; ...and subtract lo/hi bytes
HIINST #hi(VAL(_SARG1))
elseif ; no immediate->ext. or direct
LOINST (ARG1)+1 ; ...and subtract lo/hi bytes
HIINST ARG1
endif
endif
endm
endm
\end{verbatim}
Dann sind die restlichen Definitionen Einzeiler:
\begin{verbatim}
def16 addd,adda,adcb
def16 subd,suba,sbcb
def16 andd,anda,andb
def16 ord,ora,orb
def16 eord,eora,eorb
\end{verbatim}
%%===========================================================================
\cleardoublepage
In diesem Kapitel habe ich versucht, einige besonders h"aufig gestellte
Fragen mit den passenden Antworten zu sammeln. Die Antworten auf
die hier auftauchenden Probleme finden sich zwar auch an anderer
Stelle in der Anleitung, jedoch findet man sie vielleicht nicht auf
den ersten Blick...
\begin{description}
\item[F:]{Ich bin DOS leid. F"ur welche Plattformen gibt es \asname{} sonst ?}
\item[A:]{Neben der Protected-Mode-Version, die \asname{} unter DOS mehr Speicher
zur Verf"ugung stellt, existieren Portierungen f"ur OS/2 und
Unix-Systeme wie z.B. Linux (im Teststadium). An Versionen,
die Softwareherstellern in Redmond beim Geldscheffeln zuarbeiten
w"urden, ist momentan nicht gedacht. Sofern jemand anders in
dieser Hinsicht aktiv werden will, stelle ich ihm aber gerne
die \asname{}-Quellen zur Verf"ugung, von denen sich die C-Variante
insbesondere eignen d"urfte. "Uber Fragen zu diesen Quellen
hinaus sollte er sich aber nicht viel von mir erwarten...}
\item[F:]{Ist eine Unterst"utzung des XYZ-Prozessors f"ur \asname{} geplant?}
\item[A:]{Es kommen immer neue Prozessoren heraus, und ich bem"uhe
mich, bei Erweiterung von \asname{} Schritt zu halten. Der Stapel
mit der Aufschrift ,,Unerledigt'' auf meinem Schreibtisch
unterschreitet aber selten die 10cm-Grenze... Bei der Planung,
welche Kandidaten zuerst abgearbeitet werden, spielen W"unsche
von Anwendern nat"urlich eine gro"se Rolle. Das Internet und
die steigende Zahl elektronisch publizierter Dokumentation
erleichtern die Beschaffung von Unterlagen, speziell bei
ausgefallenen oder "alteren Architekturen wird es aber immer
wieder schwierig. Wenn sich die fragliche Prozessorfamilie
nicht in der Liste in Planung befindlicher Prozessoren
befindet (siehe Kapitel 1), macht es sich sehr gut, der
Anfrage auch gleich ein passendes Datenbuch hinzuzupacken
(zur Not auch leihweise!).}
\item[F:]{Ein freier Assembler ist ja eine feine Sache, aber eigentlich
br"auchte ich jetzt auch noch einen Disassembler...und einen
Debugger...ein Simulator w"are auch ganz nett..}
\item[A:]{\asname{} ist ein Freizeitprojekt von mir, d.h. etwas, was ich in der
Zeit tue, wenn ich mich nicht gerade um den Broterwerb k"ummere.
Von dieser Zeit nimmt \asname{} schon einen ganz erheblichen Teil ein,
und ab und zu genehmige ich mir auch mal eine Auszeit, um den
L"otkolben zu schwingen, mal wieder eine Tangerine Dream-Platte
bewu"st zu h"oren, mich vor den Fernseher zu hocken oder einfach
nur dringenden menschlichen Bed"urfnissen nachzugehen. Ich habe
einmal angefangen, einen Disassembler zu konzipieren, der wieder
voll reassemblierbaren Code erzeugt und automatisch Daten- und
Code-Bereiche trennt, habe das Projekt aber relativ schnell wieder
eingestellt, weil die restliche Zeit f"ur so etwas einfach nicht
mehr reicht. Ich mache lieber eine Sache gut als ein halbes
Dutzend m"a"sig. Von daher mu"s die Antwort also wohl ,,nein''
hei"sen...}
\item[F:]{In den Bildschirmausgaben von \asname{} tauchen seltsame Zeichen auf,
z.B. Pfeile und eckige Klammern. Warum?}
\item[A:]{\asname{} verwendet zur Bildschirmsteuerung defaultm"a"sig einige
ANSI-Terminal-Steuersequenzen. Haben Sie keinen ANSI-Treiber
installiert, so kommen diese Steuerzeichen ungefiltert auf
Ihrem Bildschirm heraus. Installieren Sie entweder einen
ANSI-Treiber oder schalten Sie die Steuersequenzen mit dem
DOS-Befehl \tty{SET USEANSI=N} ab.}
\item[F:]{W"ahrend der Assemblierung bricht \asname{} pl"otzlich mit der
Meldung eines Stapel"uberlaufes ab. Ist mein Programm zu
kompliziert?}
\item[A:]{Ja und Nein. Die Symboltabelle f"ur Ihr Programm ist nur
etwas unregelm"a"sig gewachsen, was zu zu hohen Rekursionstiefen
im Zugriff auf die Tabelle gef"uhrt hat. Diese Fehler treten
insbesondere bei der 16-Bit-OS/2-Version von \asname{} auf, die nur
"uber einen relativ kleinen Stack verf"ugt. Starten Sie \asname{} noch
einmal mit dem \tty{-A}-Kommandozeilenschalter. Hilft dies auch
nicht, so kommen als m"ogliche Problemstellen noch zu komplizierte
Formelausdr"ucke in Frage. Versuchen Sie in einem solchen Fall,
die Formel in Zwischenschritte aufzuspalten.}
\item[F:]{\asname{} scheint mein Programm nicht bis zum Ende zu assemblieren.
Mit einer "alteren Version von \asname{} (1.39) hat es dagegen
funktioniert.}
\item[A:]{Neuere Versionen von \asname{} ignorieren das \tty{END}-Statement nicht
mehr, sondern beenden danach wirklich die Assemblierung.
Insbesondere bei Include-Dateien ist es fr"uher vorgekommen, da"s
Anwender jede Datei mit einem \tty{END}-Statement beendet haben.
Entfernen Sie die "uberfl"ussigen \tty{END}s.}
\item[F:]{Weil ich noch ein paar kompliziertere Assemblierfehler im Programm
hatte, habe ich mir ein Listing gemacht und es einmal genauer
angeschaut. Dabei ist mir aufgefallen, da"s einige Spr"unge nicht
auf das gew"unschte Ziel, sondern auf sich selbst zeigen!}
\item[A:]{Dieser Effekt tritt bei Vorw"artsspr"ungen auf, bei denen der
Formelparser von \asname{} im ersten Pass die Zieladresse noch nicht kennen
kann. Da der Formelparser ein unabh"angiges Modul ist, mu"s er sich
in einem solchen Fall einen Wert ausdenken, der auch relativen
Spr"ungen mit kurzer Reichweite nicht wehtut, und dies ist nun
einmal die aktuelle Programmz"ahleradresse selber...im zweiten Pass
w"aren die korrekten Werte erschienen, aber zu diesem ist es nicht
gekommen, da schon im ersten Pass Fehler auftraten. Korrigieren
Sie die anderen Fehler zuerst, so da"s \asname{} zum zweiten Pass kommt,
und das Listing sollte wieder vern"unftiger aussehen.}
\item[F:]{Mein Programm wird zwar korrekt assembliert, bei der Umwandlung
mit P2BIN oder P2HEX erhalte ich aber nur eine leere Datei.}
\item[A:]{Dann haben Sie wahrscheinlich das Adre"s\-fil\-ter nicht korrekt
eingestellt. De\-faul\-tm"a"sig ist der Filter abgeschaltet, d.h.
alle Daten werden "ubernommen, wenn ein manuell eingestellter
Bereichsfilter nicht zu den benutzten Adressen pa"st, kann man
mit der '-r' Option aber (versehentlich) auch leere Dateien
erzeugen.}
\item[F:]{Ich bekomme unter Unix bei der Benutzung von P2BIN oder P2HEX
das Dollarzeichen nicht eingegeben. Die automatische
Bereichsfestlegung funktioniert nicht, stattdessen gibt es
eigenartige Fehlermeldungen.}
\item[A:]{Unix-Shells benutzen das Dollarzeichen zur Expansion von
Shell-Variablen. Wollen Sie ein Dollarzeichen an eine Anwendung
durchreichen, stellen Sie einen Backslash (\verb!\!) voran.
Im Falle der Adre"sangabe bei P2BIN und P2HEX darf aber auch
\tty{0x} anstelle des Dollarzeichens benutzt werden, was dieses
Problem von vornherein vermeidet.}
\item[F:]{Ich nutze \asname{} auf einem Linux-System, das Ladeprogramm f"ur
mein Zielsystem l"auft aber auf einem Windows-Rechner. Um das
zu vereinfachen, greifen beide System auf das gleiche
Netzwerklaufwerk zu. Leider will die Windows-Seite aber die
von der Linux-Seite erzeugten Hex-Dateien nicht lesen :-(}
\item[A:]{Windows- und Linux-Systeme benutzen ein etwas abweichendes
Format f"ur Textdateien, unter die auch Hex-Dateien fallen.
W"ahrend Windows jede Zeile mit den Zeichen CR (Carriage Return)
und LF (Linefeed) abschlie"st, verwendet Linux nur ein Linefeed.
Es h"angt nun von der ''Gutm"utigkeit'' eines Windows-Programms
ab, ob es die Dateien im Linux-Format akzeptiert. Falls nicht,
kann man die Dateien anstelle "uber ein Netzwerklaufwerk "uber
FTP im ASCII-Modus "ubertragen, oder man konvertiert die Dateien
unter ins Windows-Format. Das Programm {\em unix2dos} kann dazu
z.B. verwendet werden, oder unter Linux ein kleines Script:
\begin{verbatim}
awk '{print $0"\r"}' test.hex >test_cr.hex
\end{verbatim}}
\item[F:]{Ich habe in meinem Programm eine 16-bittige Adresse und mu"s
die obere und untere H"alfte in getrennte CPU-Register laden.
Wie extrahiere ich diese H"alften? Bei anderen Assemblern
gibt es daf"ur eingebaute Funktionen.}
\item[A:]{Das geht zum einen ,,zu Fu"s'' mit den logischen und
Schiebeoperatoren, zum anderen bekommt man die Funktionen
{\tt lo()} und {\tt hi()}, indem man die mitgelieferte Datei
{\tt bitfuncs.inc} in das Programm inkludiert.}
\end{description}
%%===========================================================================
\cleardoublepage
\chapter{Pseudobefehle und Integer-Syntax, gesammelt}
In diesem Anhang finden sich noch einmal als schnelle Referenz alle
von \asname{} zur Verf"ugung gestellten Pseudobefehle. Die Liste ist in zwei
Teile gegliedert: Im ersten Teil finden sich Befehle, die unabh"angig
vom eingestellten Zielprozessor vorhanden sind, danach folgen f"ur
jede Prozessorfamilie die zus"atzlich vorhandenen Befehle:
\input{../doc_COM/pscomm.tex}
Zus"atzlich existieren:
\begin{itemize}
\item{\tty{SET} als Alias zu \tty{EVAL}, falls \tty{SET} nicht bereits ein
Prozessorbefehl ist.}
\item{\tty{SHIFT} bzw. \tty{SHFT}, falls \tty{SHIFT} bereits ein Prozessorbefehl
ist.}
\item{\tty{RESTORE} als Alias zu \tty{RESTOREENV}, falls \tty{RESTORE} nicht bereits ein
Prozessorbefehl ist.}
\item{\tty{SAVE} als Alias zu \tty{SAVEENV}, falls \tty{SAVE} nicht bereits ein
Prozessorbefehl ist.}
\item{\tty{PAGE} bzw. \tty{PAGESIZE}, falls \tty{PAGE} bereits ein Prozessorbefehl
ist.}
\item{\tty{SWITCH} bzw. \tty{SELECT}, falls \tty{SWITCH} bereits ein Prozessorbefehl
ist.}
\end{itemize}
\input{../doc_COM/pscpu.tex}
%%===========================================================================
\cleardoublepage
\begin{center}\begin{longtable}{|l|l|l|l|}
Name & Datentyp & Definition & Bedeutung \\
\endhead
\tty{ARCHITECTURE} & String & vordef. & Zielplattform, f"ur die \asname{} \\
& & & "ubersetzt wurde, in der Form \\
& & & Prozesor-Hersteller-Betriebs- \\
& & & system \\
\tty{BIGENDIAN} & Boolean & normal & Konstantenablage mit MSB \\
& & & first ? \\
\tty{CASESENSITIVE} & Boolean & normal & Unterscheidung von Gro"s- \\
& & & und Kleinbuchstaben in \\
& & & Symbolnamen ? \\
\tty{CONSTPI} & Gleitkomma & normal & Kreiszahl Pi (3.1415.....) \\
\tty{DATE} & String & vordef. & Datum des Beginns der \\
& & & Assemblierung (1.Pass) \\
\tty{FALSE} & Boolean & vordef. & 0 = logisch ,,falsch'' \\
\tty{HASFPU} & Boolean & dynam.(0) & Koprozessor-Befehle \\
& & & freigeschaltet ? \\
\tty{HASPMMU} & Boolean & dynam.(0) & MMU-Befehle frei- \\
& & & geschaltet ? \\
\tty{INEXTMODE} & Boolean & dynam.(0) & XM-Flag f"ur 4 Gbyte \\
& & & Adre"sraum gesetzt ? \\
\tty{INLWORDMODE} & Boolean & dynam.(0) & LW-Flag f"ur 32-Bit-Befehle \\
& & & gesetzt ? \\
\tty{INMAXMODE} & Boolean & dynam.(0) & Prozessor im Maximum- \\
& & & Modus ? \\
\tty{INSUPMODE} & Boolean & dynam.(0) & Prozessor im Supervisor- \\
& & & Modus ? \\
\tty{INSRCMODE} & Boolean & dynam.(0) & Prozessor im Quellmodus ? \\
\tty{FULLPMMU} & Boolean & dynam.(0/1) & voller PMMU-Befehlssatz ? \\
\tty{LISTON} & Boolean & dynam.(1) & Listing freigeschaltet ? \\
\tty{MACEXP} & Boolean & dynam.(1) & Expansion von Makrokon- \\
& & & strukten im Listing \\
& & & freigeschaltet ? \\
\tty{MOMCPU} & Integer & dynam. & Nummer der momentan \\
& & (68008) & gesetzten Ziel-CPU \\
\tty{MOMCPUNAME} & String & dynam. & Name der momentan \\
& & (68008) & gesetzten Ziel-CPU \\
\tty{MOMFILE} & String & Spezial & augenblickliche Quelldatei \\
& & & (schlie"st Includes ein) \\
\tty{MOMLINE} & Integer & Spezial & aktuelle Zeilennummer in \\
& & & der Quelldatei \\
\tty{MOMPASS} & Integer & Spezial & Nummer des laufenden \\
& & & Durchgangs \\
\tty{MOMSECTION} & String & Spezial & Name der aktuellen Sektion \\
& & & oder Leerstring, fall au"ser- \\
& & & halb aller Sektionen \\
\tty{MOMSEGMENT} & String & Spezial & Name des mit \tty{SEGMENT} ein- \\
& & & gestellten Adre"sraumes \\
\tty{NESTMAX} & Integer & dynam.(256)& maximale Verschachtelungs- \\
& & & tiefe f"ur Makros \\
\tty{PADDING} & Boolean & dynam.(1) & Auff"ullen von Bytefeldern \\
& & & auf ganze Anzahl ? \\
\tty{RELAXED} & Boolean & dynam.(0) & Schreibweise von Integer-Kon- \\
& & & stanten in beliebiger Syntax \\
& & & erlaubt ? \\
\tty{PC} & Integer & Spezial & mom. Programmz"ahler \\
& & & (Thomson) \\
\tty{TIME} & String & vordef. & Zeit des Beginns der Assem- \\
& & & blierung (1. Pass) \\
\tty{TRUE} & Integer & vordef. & 1 = logisch ,,wahr'' \\
\tty{VERSION} & Integer & vordef. & Version von \asname{} in BCD-Kodie- \\
& & & rung, z.B. 1331 hex f"ur \\
& & & Version 1.33p1 \\
\tty{WRAPMODE} & Integer & vordef. & verk"urzter Programmz"ahler \\
& & & angenommen? \\
\verb!*! & Integer & Spezial & mom. Programmz"ahler \\
& & & (Motorola, Rockwell, \\
& & & Microchip, Hitachi) \\
. & Integer & Spezial & mom. Programmz"ahler \\
& & & (IM61x0) \\
\tty{\$} & Integer & Spezial & mom. Programmz"ahler (Intel, \\
& & & Zilog, Texas, Toshiba, NEC, \\
& & & Siemens, AMD) \\
\end{longtable}\end{center}
Boolean-Symbole sind eigentlich normale normale Integer-Symbole, mit
dem Unterschied, da"s ihnen von \asname{} nur zwei verschiedene Werte (0 oder
1, entsprechend FALSE oder TRUE) zugewiesen werden. Spezialsymbole
werden von \asname{} nicht in der Symboltabelle abgelegt, sondern aus
Geschwindigkeitsgr"unden direkt im Parser abgefragt. Sie tauchen daher
auch nicht in der Symboltabelle des Listings auf. W"ahrend vordefinierte
Symbole nur einmal am Anfang eines Passes besetzt werden, k"onnen sich
die Werte dynamischer Symbole w"ahrend der Assemblierung mehrfach "andern,
da sie mit anderen Befehlen vorgenommene Einstellungen widerspiegeln.
Die hier aufgelistete Schreibweise ist diejenige, mit der man die
Symbole auch im case-sensitiven Modus erreicht.
Die hier aufgef"uhrten Namen sollte man f"ur eigene Symbole meiden;
entweder kann man sie zwar definieren, aber nicht darauf zugreifen
(bei Spezialsymbolen), oder man erh"alt eine Fehlermeldung wegen eines
doppelt definierten Symboles. Im gemeinsten Fall f"uhrt die Neubelegung
durch \asname{} zu Beginn eines Passes zu einem Phasenfehler und einer
Endlosschleife...
%%===========================================================================
\cleardoublepage
Der Distribution von \asname{} liegen eine Reihe von Include-Dateien bei. Neben
Includes, die sich nur auf eine Prozessorfamilie beziehen (und deren
Funktion sich demjenigen unmittelbar erschlie"st, der mit dieser Familie
arbeitet), existieren aber auch ein paar Dateien, die prozessorunabh"angig
sind und die eine Reihe n"utzlicher Funktionen implementieren. Die
definierten Funktionen sollen hier kurz beschrieben werden:
Diese Datei definiert eine Reihe bitorientierter Operationen, wie man sie
bei anderen Assemblern vielleicht fest eingebaut sind. Bei \asname{} werden sie
jedoch mit Hilfe benutzerdefinierter Funktionen implementiert:
\begin{itemize}
\item{{\em mask(start,bits)} liefert einen Integer, in dem ab Stelle {\em
start} {\em bits} Bits gesetzt sind;}
\item{{\em invmask(start,bits)} liefert das Einerkomplement zu {\em mask()};}
\item{{\em cutout(x,start,bits)} liefert ausmaskierte {\em bits} Bits ab
Stelle {\em start} aus {\em x}, ohne sie auf Stelle 0 zu
verschieben;}
\item{{\em hi(x)} liefert das zweitniedrigste Byte (Bit 8..15) aus {\em
x};}
\item{{\em lo(x)} liefert das niederwertigste Byte (Bit 0..7) aus {\em
x};}
\item{{\em hiword(x)} liefert das zweitniedrigste Wort (Bit 16..31) aus
{\em x};}
\item{{\em loword(x)} liefert das niederwertigste Wort (Bit 0..15) aus
{\em x};}
\item{{\em odd(x)} liefert TRUE, falls {\em x} ungerade ist;}
\item{{\em even(x)} liefert TRUE, falls {\em x} gerade ist;}
\item{{\em getbit(x,n)} extrahiert das Bit {\em n} aus {\em x} und liefert
es als 0 oder 1;}
\item{{\em shln(x,size,n)} schiebt ein Wort {\em x} der L"ange {\em size}
Bits um {\em n} Stellen nach links;}
\item{{\em shrn(x,size,n)} schiebt ein Wort {\em x} der L"ange {\em size}
Bits um {\em n} Stellen nach rechts;}
\item{{\em rotln(x,size,n)} rotiert die untersten {\em size} Bits eines
Integers {\em x} um {\em n} Stellen nach links;}
\item{{\em rotrn(x,size,n)} rotiert die untersten {\em size} Bits eines
Integers {\em x} um {\em n} Stellen nach rechts;}
\end{itemize}
Dieser Include ist das Pendant zu dem bei C vorhandenen Header {\tt
ctype.h}, der Makros zur Klassifizierung von Zeichen anbietet. Alle
Funktionen liefern entweder TRUE oder FALSE:
\begin{itemize}
\item{{\em isdigit(ch)} ist TRUE, falls {\em ch} eine Ziffer (0..9)
ist;}
\item{{\em isxdigit(ch)} ist TRUE, falls {\em ch} eine g"ultige
Hexadezimal-Ziffer (0..9, A..F, a..f) ist;}
\item{{\em isascii(ch)} ist TRUE, falls {\em ch} sich im Bereich
normaler ASCII-Zeichen ohne gesetztes Bit 7 bewegt;}
\item{{\em isupper(ch)} ist TRUE, falls {\em ch} ein Gro"sbuchstabe
ist (Sonderzeichen ausgenommen);}
\item{{\em islower(ch)} ist TRUE, falls {\em ch} ein Kleinbuchstabe
ist (Sonderzeichen ausgenommen);}
\item{{\em isalpha(ch)} ist TRUE, falls {\em ch} ein Buchstabe ist
(Sonderzeichen ausgenommen);}
\item{{\em isalnum(ch)} ist TRUE, falls {\em ch} ein Buchstabe oder
eine Ziffer ist);}
\item{{\em isspace(ch)} ist TRUE, falls {\em ch} ein 'Leerzeichen'
(Space, Formfeed, Zeilenvorschub, Wagenr"ucklauf, Tabulator)
ist);}
\item{{\em isprint(ch)} ist TRUE, falls {\em ch} ein druckbares
Zeichen ist (also kein Steuerzeichen bis Code 31);}
\item{{\em iscntrl(ch)} ist das Gegenteil zu {\em isprint()};}
\item{{\em isgraph(ch)} ist TRUE, falls {\em ch} ein druckbares
und {\it sichtbares} Zeichen ist;}
\item{{\em ispunct(ch)} ist TRUE, falls {\em ch} ein druckbares
Sonderzeichen ist (d.h. weder Space, Buchstabe noch Ziffer);}
\end{itemize}
%%===========================================================================
\cleardoublepage
\begin{quote}{\it
''If I have seen farther than other men, \\
it is because I stood on the shoulders of giants.'' \\
\hspace{2cm} --Sir Isaac Newton}
\end{quote}
\begin{quote}{\it
''If I haven't seen farther than other men, \\
it is because I stood in the footsteps of giants.'' \\
\end{quote}
Es hei"st ja bisweilen, die Programme, die man schreibe, w"aren so
etwas wie eigene Kinder, die man in die Welt setzt. Ich arbeite an
diesem Assembler seit "uber 30 Jahren, und bin mittlerweile der
Ansicht, so ein Projekt ist viel mehr eine Reise, auf die man sich
begibt: Die Begegnungen mit Menschen, die man auf den Stationen
dieses Weges trifft, sind mindestens eben so wichtig wie das
vermeintliche Ziel selber. Man lernt Neues kennen, und versteht im
besten Falle, da"s man Dinge auch aus einer ganz anderen Warte sehen
kann. Wenn es gut l"auft, bringt das dann beide Seiten weiter.
Einige Menschen sind mir auf diesem Weg besonders in Erinnerung
geblieben, weil sie auf ihre Weise dazu beigetragen haben, dieses
Projekt dorthin zu bringen, wo es jetzt ist. Die folgende Aufz"ahlung
ist notwendigerweise unvollst"andig, einfach weil ich mich nach den
Jahren nicht mehr an jede Begebenheit erinnere. Der zuvorderste Dank
gent daher an all die Personen, deren Namen ich in diesem Kapitel
unabsichtlich unterschlagen habe. Die Reise geht immer noch weiter,
und vielleicht kreuzen sich die Wege wieder!
\asname{} als Universalassembler, wie er jetzt besteht, ist auf Anregung von
Bernhard (C.) Zschocke entstanden, der einen ,,studentenfreundlichen'',
d.h. kostenlosen 8051-Assembler f"ur sein Mikroprozessorpraktikum
brauchte und mich dazu bewegt hat, einen bereits bestehenden
68000-Assembler zu erweitern. Von dortan nahm die Sache ihren Lauf...
Das Mikroprozessorpraktikum an der RWTH Aachen hat auch immer die
eifrigsten Nutzer der neuesten \asname{}-Features (und damit Bug-Sucher)
gestellt und damit einiges zur jetzigen Qualit"at von \asname{} beigetragen.
Das Internet und FTP haben sich als gro"se Hilfe bei der Meldung von
Bugs und der Verbreitung von \asname{} erwiesen. Ein Dank geht daher an
die FTP-Administratoren (Bernd Casimir in Stuttgart, Norbert Breidohr
in Aachen und J"urgen Mei"sburger in J"ulich). Insbesondere letzterer
hat sich sehr engagiert, um eine praxisnahe L"osung im ZAM zu
finden.
Ach ja, wo wir schon im ZAM sind: Wolfgang E. Nagel hat zwar nichts
direkt mit \asname{} zu tun, immerhin war er aber mein Betreuer und
Vorgesetzter und warf
st"andig vier Augen auf das, was ich tue. Bei \asname{} scheint zumindest
ein lachendes dabei zu sein...
Ein Projekt wie \asname{} ist ohne Input und Informationen nicht zu
leisten, sei es zu den unterst"utzten Prozessoren selber, zu
Programmiertechniken oder wie Dinge implementiert werden sollten.
Ich habe von einer enormen Anzahl von Menschen R"uckmeldungen
bekommen, die von einem kleinen Tip bis zu ganzen Datenb"uchern
reichen. Hier eine Aufz"ahlung (wie wie oben gesagt, mit Sicherheit
unvollst"andig ist!):
Ernst Ahlers, Charles Altmann, Marco Awater, Len Bayles, Andreas
Bolsch, Rolf Buchholz, Bernd Casimir, Nils Eilers, Gunther Ewald,
Michael Haardt, Stephan Hruschka, Fred van Kempen, Peter
Kliegelh"ofer, Ulf Meinke, Udo M"oller, Matthias Paul, Norbert Rosch,
Curt J. Sampson, Steffen Schmid, Leonhard Schneider, Ernst Schwab,
Michael Schwingen, Oliver Sellke, Christian Stelter, Patrik
Str"omdahl, Tadashi G. Takaoka, Oliver Thamm, Thorsten Thiele,
Leszek Ulman, Rob Warmelink, Andreas Wassatsch, John Weinrich.
...und ein leicht ironischer Dank geht an Rolf-Dieter-Klein und Tobias Thiel, die
mich mit ihren ASM68K dazu angeregt haben, "uberhaupt einen eigenen
Assembler zu schreiben. einige Dinge darin funktionierten nicht so,
wie ich es mir vorgestellt hatte, und das war der Anlass, es besser
oder zumindest anders zu machen.
So ganz allein habe ich \asname{} auch nicht geschrieben. Die DOS-Version
von \asname{} enthielt die OverXMS-Routinen von Wilbert van Leijen,
um die Overlay-Module ins Extended Memory verlagern zu k"onnen. Eine
wirklich feine Sache, einfach und problemlos anzuwenden!
Die TMS320C2x/5x-Codegeneratoren sowie die Datei \tty{STDDEF2x.INC}
stammen von Thomas Sailer, ETH Z"urich. Erstaunlich, an einem Wochenende
hat er es geschafft, durch meinen Code durchzusteigen und den neuen
Generator zu implementieren. Entweder waren das reichliche Nachtschichten
oder ich werde langsam alt...gleiches Lob geb"uhrt Haruo Asano f"ur
die Targets MN1610/MN1613, IM6100, CP1600, Renesas RX und HP
NanoProcessor.
%%===========================================================================
\cleardoublepage
\chapter{"Anderungen seit Version 1.3}
\begin{itemize}
\begin{itemize}
\item{zus"atzlicher MCS-51-Prozessortyp 80515. Die Nummer wird
wiederum nur vom Assembler verwaltet. Die Datei STDDEF51.INC
wurde um die dazugeh"origen SFRs erweitert. \bb{ACHTUNG!}
Einige 80515-SFRs haben sich adre"sm"a"sig verschoben!}
\item{zus"atzlich Prozessor Z80 unterst"utzt;}
\item{schnellerer 680x0-Codegenerator.}
\end{itemize}}
\begin{itemize}
\item{Schreibweise von Zeropageadressen f"ur 65xx nicht mehr als
Adr.z, sondern wie beim 68xx als $<$Adr;}
\item{unterst"utzt die Prozessoren 6800, 6805, 6301 und 6811;}
\item{der 8051-Teil versteht jetzt auch \tty{DJNZ}, \tty{PUSH} und
\tty{POP} (sorry);}
\item{im Listing werden neben den Symbolen jetzt auch die definierten
Makros aufgelistet;}
\item{Befehle \tty{IFDEF}/\tty{IFNDEF} f"ur bedingte Assemblierung,
mit denen sich die Existenz eines Symboles abfragen l"a"st;}
\item{Befehle \tty{PHASE}/\tty{DEPHASE} zur Unterst"utzung von Code, der zur
Laufzeit auf eine andere Adresse verschoben werden soll;}
\item{Befehle \tty{WARNING}/\tty{ERROR}/\tty{FATAL}, um anwenderspezifische
Fehlermeldungen ausgeben zu k"onnen;}
\item{Die Datei STDDEF51.INC enth"alt zus"atzlich das Makro \tty{USING}
zur einfacheren Handhabung der Registerb"anke der MCS-51er;}
\item{Kommandozeilenoption \tty{u}, um Segmentbelegung anzuzeigen.}
\end{itemize}}
\begin{itemize}
\item{unterst"utzt den 6809;}
\item{zus"atzlich Stringvariablen;}
\item{Die Befehle \tty{TITLE}, \tty{PRTINIT}, \tty{PRTEXIT},
\tty{ERROR}, \tty{WARNING} und \tty{FATAL} erwarten jetzt
einen Stringausdruck als Parameter, Konstanten
m"ussen demzufolge nicht mehr in Hochkommas, sondern in
G"ansef"u"schen eingeschlossen werden. Analoges gilt f"ur \tty{DB},
\tty{DC.B} und \tty{BYT};}
\item{Befehl \tty{ALIGN} zur Ausrichtung des Programmz"ahlers bei Intel-
Prozessoren;}
\item{Befehl \tty{LISTING}, um die Erzeugung eines Listings ein- und
ausschalten zu k"onnen;}
\item{Befehl \tty{CHARSET} zur Definition eigener Zeichens"atze.}
\end{itemize}}
\begin{itemize}
\item{Wenn im ersten Pass Fehler auftreten, wird gar kein zweiter
Pass mehr durchgef"uhrt;}
\item{neues vordefiniertes Symbol \tty{VERSION}, welches die Version von
\asname{} enth"alt;}
\item{Befehl \tty{MESSAGE}, um Durchsagen und Meldungen programmgesteuert
zu erzeugen;}
\item{Formelparser "uber Stringkonstanten zug"anglich;}
\item{Bei Fehler in Makroexpansionen wird zus"atzlich die laufende
Zeile im Makro angezeigt;}
\item{Funktion \tty{UPSTRING}, um einen String in Gro"sbuchstaben zu
wandeln.}
\end{itemize}}
\begin{itemize}
\item{Funktion \tty{TOUPPER}, um ein einzelnes Zeichen in Gro"sbuchstaben
zu wandeln;}
\item{Befehl \tty{FUNCTION}, um eigene Funktionen definieren zu k"onnen;}
\item{Kommandozeilenoption \tty{D}, um Symbole von au"sen definieren zu
k"onnen;}
\item{Fragt die Environment-Variable \tty{ASCMD} f"ur h"aufig gebrauchte
Optionen ab;}
\item{bei gesetzter \tty{u}-Option wird das Programm zus"atzlich auf doppelt
belegte Speicherbereiche abgepr"uft;}
\item{Kommandozeilenoption \tty{C}, um eine Querverweisliste zu erzeugen.}
\end{itemize}}
\begin{itemize}
\item{unterst"utzt zus"atzlich die Familien PIC 16C5x und
PIC17C4x;}
\item{im Listing wird zus"atzlich die Verschachtelungsebene bei
Include-Dateien angezeigt;}
\item{in der Querverweisliste wird zus"atzlich die Stelle angezeigt,
an der ein Symbol definiert wurde;}
\item{Kommandozeilenoption \tty{A}, um eine kompaktere Ablage der
Symboltabelle zu erzwingen.}
\end{itemize}}
\begin{itemize}
\item{unterst"utzt zus"atzlich die Prozessoren 8086, 80186, V30,
V35, 8087 und Z180;}
\item{Befehle \tty{SAVE} und \tty{RESTORE} zur besseren Umschaltung
von Flags;}
\item{Operatoren zur logischen Verschiebung und Bitspiegelung;}
\item{Kommandozeilenoptionen k"onnen mit einem Pluszeichen negiert
werden;}
\item{Filter \tty{AS2MSG} zur bequemen Arbeit mit \asname{} unter Turbo-Pascal 7.0;}
\item{\tty{ELSEIF} darf ein Argument zur Bildung von
\tty{IF-THEN-ELSE}-Leitern haben;}
\item{Zur bequemeren bedingten Assemblierung zus"atzlich ein
\tty{CASE}-Konstrukt;}
\item{Selbst definierte Funktionen d"urfen mehr als ein Argument haben;}
\item{P2HEX kann nun auch Hexfiles f"ur 65er-Prozessoren erzeugen;}
\item{BIND, P2HEX und P2BIN haben jetzt die gleichen
Variationsm"oglichkeiten in der Kommandozeile wie \asname{};}
\item{Schalter \tty{i} bei P2HEX, um 3 Varianten f"ur den Ende-Record
einzustellen;}
\item{Neue Funktionen \tty{ABS} und \tty{SGN};}
\item{Neue Pseudovariablen \tty{MOMFILE} und \tty{MOMLINE};}
\item{Ausgabem"oglichkeit erweiterter Fehlermeldungen;}
\item{Befehle \tty{IFUSED} und \tty{IFNUSED}, um abzufragen, ob ein
Symbol bisher benutzt wurde;}
\item{Die Environment-Variablen \tty{ASCMD}, \tty{BINDCMD} usw. k"onnen auch
einen Dateinamen enthalten, in dem f"ur die Optionen mehr
Platz ist;}
\item{P2HEX erzeugt nun die von Microchip vorgegebenen Hex-Formate
(p4);}
\item{mit der Seitenl"angenangabe 0 k"onnen automatische
Seitenvorsch"ube im Listing vollst"andig unterdr"uckt werden
(p4);}
\item{neue Kommandozeilenoption \tty{P}, um die Ausgabe des Makroprozessors
in eine Datei zu schreiben (p4);}
\item{in der Kommandozeile definierte Symbole d"urfen nun auch mit
einem frei w"ahlbaren Wert belegt werden (p5).}
\end{itemize}}
\begin{itemize}
\item{Umstellung auf Mehrpass-Betrieb. Damit kann \asname{} auch bei
Vorw"artsreferenzen immer den optimalen Code erzeugen;}
\item{Der 8051-Teil kennt nun auch die Befehle \tty{JMP} und \tty{CALL};}
\item{unterst"utzt zus"atzlich die Toshiba TLCS-900-Reihe (p1);}
\item{Befehl \tty{ASSUME}, um dem Assembler die Belegung der
Segmentregister des 8086 mitzuteilen (p2);}
\item{unterst"utzt zus"atzlich die ST6-Reihe von SGS-Thomson (p2);}
\item{..sowie die 3201x-Signalprozessoren von Texas Instruments (p2);}
\item{Option \tty{F} bei P2HEX, um die automatische Formatwahl "ubersteuern
zu k"onnen (p2);}
\item{P2BIN kann nun auch durch Angabe von Dollarzeichen Anfang und
Ende des Adre"sfensters selbstst"andig festlegen (p2);}
\item{Der 8048-Codegenerator kennt nun auch die 8041/42-
Befehlserweiterungen(p2);}
\item{unterst"utzt zus"atzlich die Zilog Z8-Mikrokontroller(p3).}
\end{itemize}}
\begin{itemize}
\item{Definitionsm"oglichkeit von Sektionen und lokalen Labels;}
\item{Kommandozeilenschalter \tty{h}, um Hexadezimalzahlenausgabe mit
Kleinbuchstaben zu erzwingen;}
\item{Variable \tty{MOMPASS}, um die Nummer des augenblicklichen Durchganges
abfragen zu k"onnen;}
\item{Kommandozeilenschalter \tty{t}, um einzelne Teile des Assemblerlistings
ausblenden zu k"onnen;}
\item{kennt zus"atzlich die L-Variante der TLCS-900-Reihe von Toshiba
und die MELPS-7700-Reihe von Mitsubishi (p1);}
\item{P2HEX akzeptiert nun auch Dollarzeichen f"ur Start-und Endadresse
(p2);}
\item{unterst"utzt zus"atzlich die TLCS90-Familie von Toshiba (p2);}
\item{P2HEX kann Daten zus"atzlich im Tektronix- und 16-Bit
Intel-Hex-Format ausgeben (p2);}
\item{bei Adre"s"uberschreitungen gibt P2HEX Warnungen aus (p2);}
\item{Include-Datei STDDEF96.INC mit Adre"sdefinitionen f"ur die
TLCS-900-Reihe (p3);}
\item{Befehl \tty{READ}, um Werte w"ahrend der Assemblierung interaktiv
einlesen zu k"onnen (p3);}
\item{Fehlermeldungen werden nicht mehr einfach auf die
Standardausgabe, sondern auf den von DOS daf"ur vorgesehenen
Kanal (STDERR) geschrieben (p3);}
\item{Der beim 6811-Teil fehlende \tty{STOP}-Befehl ist nun da (scusi,p3);}
\item{unterst"utzt zus"atzlich die $\mu$PD78(C)1x-Familie von NEC (p3);}
\item{unterst"utzt zus"atzlich den PIC16C84 von Microchip (p3);}
\item{Kommandozeilenschalter \tty{E}, um die Fehlermeldungen in eine Datei
umleiten zu k"onnen (p3);}
\item{Die Unklarheiten im 78(C)1x-Teil sind beseitigt (p4);}
\item{neben dem MELPS-7700 ist nun auch das ,,Vorbild'' 65816
vorhanden (p4);}
\item{Die ST6-Pseudoanweisung \tty{ROMWIN} wurde entfernt und
mit in den \tty{ASSUME}-Befehl eingegliedert (p4);}
\item{unterst"utzt zus"atzlich den 6804 von SGS-Thomson (p4);}
\item{durch die \tty{NOEXPORT}-Option in der Makrodefinition
kann nun f"ur jedes Makro einzeln festgelegt werden, ob es
in der MAC-Datei erscheinen soll oder nicht (p4);}
\item{Die Bedeutung von \tty{MACEXP} f"ur Expansionen von Makros hat
sich wegen der zus"atzlichen \tty{NOEXPAND}-Option in der
Makrodefinition leicht ge"andert (p4);}
\item{Durch die \tty{GLOBAL}-Option in der Makrodefinition k"onnen nun
zus"atzlich Makros definiert werden, die durch ihren
Sektionsnamen eindeutig gekennzeichnet sind (p4).}
\end{itemize}}
\begin{itemize}
\item{unterst"utzt zus"atzlich den DSP56000 von Motorola;}
\item{P2BIN kann nun auch das untere bzw. obere Wort aus
32-Bit-W"ortern abtrennen;}
\item{unterst"utzt zus"atzlich die TLCS-870- und TLCS-47-Familie
von Toshiba(p1);}
\item{mit einem vorangestelltem ! kann man durch Makros
,,verdeckte'' Maschinenbefehle wieder erreichen(p1);}
\item{mit der \tty{GLOBAL}-Anweisung lassen sich Symbolnamen
nun auch qualifiziert exportieren(p1);}
\item{mit der \tty{r}-Option kann man sich nun eine Liste der
Stellen erzeugen lassen, die zus"atzliche Durchl"aufe
erzwangen(p1);}
\item{bei der \tty{E}-Option kann nun die Dateiangabe weggelassen werden,
so da"s ein passender Default gew"ahlt wird(p1);}
\item{mit der \tty{t}-Option kann nun die Zeilennumerierung im Listing
abgeschaltet werden(p1);}
\item{Escapesequenzen sind nun auch in in ASCII geschriebenen
Integerkonstanten zul"assig(p1);}
\item{Mit dem Pseudobefehl \tty{PADDING} kann das Einf"ugen
von F"ullbytes im 680x0-Modus ein- und ausgeschaltet
werden (p2);}
\item{\tty{ALIGN} ist nun f"ur alle Zielplattformen erlaubt (p2);}
\item{kennt zus"atzlich die PIC16C64-SFRs (p2);}
\item{unterst"utzt zus"atzlich den 8096 von Intel (p2);}
\item{Bei \tty{DC} kann zus"atzlich ein Wiederholungsfaktor angegeben
werden (r3);}
\item{unterst"utzt zus"atzlich die TMS320C2x-Familie von Texas
Instruments (Implementierung von Thomas Sailer, ETH Z"urich,
r3); P2HEX ist auch entsprechend erweitert;}
\item{statt \tty{EQU} darf nun auch einfach ein Gleichheitszeichen
benutzt werden (r3);}
\item{zur Definition von Aufz"ahlungen zus"atzlich ein
\tty{ENUM}-Befehl (r3);}
\item{\tty{END} hat jetzt auch eine Wirkung (r3);}
\item{zus"atzliche Kommandozeilenoption \tty{n}, um zu Fehlermeldungen
zus"atzlich die internen Fehlernummern zu erhalten (r3);}
\item{unterst"utzt zus"atzlich die TLCS-9000er von Toshiba (r4)};
\item{unterst"utzt zus"atzlich die TMS370xxx-Reihe von Texas
Instuments, wobei als neuer Pseudobefehl \tty{DBIT}
hinzukam (r5);}
\item{kennt zus"atzlich die DS80C320-SFRs (r5);}
\item{der Makroprozessor kann nun auch Includes aus Makros
heraus einbinden, wozu das Format von Fehlermeldungen
aber leicht ge"andert werden mu"ste. Falls Sie AS2MSG
verwenden, ersetzen Sie es unbedingt durch die neue
Version! (r5)}
\item{unterst"utzt zus"atzlich den 80C166 von Siemens (r5);}
\item{zus"atzlich eine \tty{VAL}-Funktion, um Stringausdr"ucke auswerten
zu k"onnen (r5);}
\item{Mithilfe von in geschweiften Klammern eingeschlossenen
Stringvariablen lassen sich nun selber Symbole definieren
(r5);}
\item{kennt zus"atzlich die Eigenheiten des 80C167 von Siemens (r6);}
\item{jetzt gibt es f"ur die MELPS740-Reihe auch die
special-page-Adressierung (r6);}
\item{mit eckigen Klammern kann man explizit Symbole aus einer
bestimmten Sektion ansprechen. Die Hilfskonstruktion mit dem
Klammeraffen gibt es nicht mehr (r6)!}
\item{kennt zus"atzlich die MELPS-4500-Reihe von Mitsubishi (r7);}
\item{kennt zus"atzlich die H8/300 und H8/300H-Prozessoren von
Hitachi (r7);}
\item{die mit \tty{LISTING} und \tty{MACEXP} gemachten Einstellungen
lassen sich nun auch wieder aus gleichnamigen Symbolen auslesen
(r7);}
\item{kennt zus"atzlich den TMS320C3x von Texas Instruments (r8);}
\item{kennt zus"atzlich den SH7000 von Hitachi (r8);}
\item{der Z80-Teil wurde um die Unterst"utzung des Z380 erweitert (r9);}
\item{der 68K-Teil wurde um die feinen Unterschiede der
683xx-Mikrokontroller erweitert (r9);}
\item{ein Label mu"s nun nicht mehr in der ersten Spalte beginnen,
wenn man es mit einem Doppelpunkt versieht (r9);}
\item{kennt zus"atzlich die 75K0-Reihe von NEC (r9);}
\item{mit dem neuen Kommandozeilenschalter o kann der Name
der Code-Datei neu festgelegt werden (r9);}
\item{der \verb!~~!-Operator ist in der Rangfolge auf einen
sinnvolleren Platz gerutscht (r9);}
\item{\tty{ASSUME} ber"ucksichtigt f"ur den 6809 jetzt auch das
DPR-Register und seine Auswirkungen (pardon, r9);}
\item{Der 6809-Teil kennt nun auch die versteckten
Erweiterungen des 6309 (r9);}
\item{Bin"arkonstanten k"onnen jetzt auch in C-artiger
Notation geschrieben werden (r9).}
\end{itemize}}
\begin{itemize}
\item{"uber das Symbol \tty{MOMSEGMENT} kann der momentan
gesetzte Adre"sraum abgefragt werden;}
\item{anstelle von \tty{SET} bzw. \tty{EVAL} kann jetzt auch
einfach \tty{:=} geschrieben werden;}
\item{mit der neuen Kommandozeilenoption \tty{q} kann ein ,,stiller''
Assemblerlauf erzwungen werden;}
\item{das Schl"usselwort \tty{PARENT} zum Ansprechen der
Vatersektion wurde um \tty{PARENT0...PARENT9} erweitert;}
\item{der PowerPC-Teil wurde um die Mikrokontroller-Versionen
MPC505 und PPC403 erweitert;}
\item{mit \tty{SET} oder \tty{EQU} definierte Symbole k"onnen
nun einem bestimmten Adre"sraum zugeordnet werden;}
\item{mit \tty{SET} oder \tty{EQU} definierte Symbole k"onnen
nun einem bestimmten Adre"sraum zugeordnet werden;}
\item{durch das Setzen der Environment-Variablen \tty{USEANSI}
kann die Verwendung von ANSI-Bildschirmsteuersequenzen
an-und ausgeschaltet werden (r1);}
\item{der SH7000-Teil kennt jetzt auch die SH7600-Befehlserweiterungen
(und sollte jetzt korrekte Displacements berechnen...) (r1).}
\item{im 65XX-Teil wird jetzt zwischen 65C02 und 65SC02 unterschieden
(r1);}
\item{neben der Variablen \tty{MOMCPU} gibt es jetzt auch den String
\tty{MOMCPUNAME}, der den Prozessornamen im Volltext enth"alt (r1).}
\item{P2HEX kennt jetzt auch die 32-Bit-Variante des
Intel-Hex-Formates (r1);}
\item{kennt jetzt auch die Einschr"ankungen des 87C750 (r2);}
\item{die Nummern f"ur fatale Fehlermeldungen wurden auf den Bereich
ab 10000 verschoben, um Platz f"ur normale Fehlermeldungen zu
schaffen (r2);}
\item{unbenutzte Symbole werden in der Symboltabelle jetzt mit einem
Stern gekennzeichnet (r2);}
\item{unterst"utzt zus"atzlich die 29K-Familie von AMD (r2);}
\item{unterst"utzt zus"atzlich die M16-Familie von Mitsubishi (r2);}
\item{unterst"utzt zus"atzlich die H8/500-Familie von Hitachi (r3);}
\item{die Anzahl von Datenbytes, die P2HEX pro Zeile ausgibt, ist
jetzt variierbar (r3);}
\item{der Pass, ab dem durch die \tty{-r}-Option erzeugte Warnungen
ausgegeben werden, ist einstellbar (r3);}
\item{der Makroprozessor kennt jetzt ein \tty{WHILE}-Statement,
mit dem ein Code-St"uck eine variable Anzahl wiederholt werden
kann (r3);}
\item{der \tty{PAGE}-Befehl erlaubt es nun auch, die Breite des
Ausgabemediums f"urs Listing anzugeben (r3);}
\item{Um neue Pseudo-Prozessortypen einf"uhren zu k"onnen, lassen
sich jetzt CPU-Aliasse definieren (r3);}
\item{unterst"utzt zus"atzlich die MCS/251-Familie von Intel (r3);}
\item{bei eingeschalteter Querverweisliste wird bei doppelt
definierten Symbolen die Stelle der ersten Definition
angezeigt (r3);}
\item{unterst"utzt zus"atzlich die TMS320C5x-Familie von Texas
Instruments (Implementierung von Thomas Sailer, ETH Z"urich,
r3);}
\item{die OS/2-Version sollte jetzt auch mit langen Dateinamen
klarkommen. Wenn man nicht jeden Mist selber kontrolliert...
(r3)}
\item{"uber den Befehl \tty{BIGENDIAN} kann im MCS-51/251-Modus
jetzt gew"ahlt werden, ob die Ablage von Konstanten im Big-
oder Little-Endian-Format erfolgen soll (r3);}
\item{es wird beim 680x0 jetzt zwischen dem vollen und eingeschr"ankten
MMU-Befehlssatz unterschieden; eine manuelle Umschaltung ist mit dem
\tty{FULLPMMU}-Befehl m"oglich (r3);}
\item{"uber die neue Kommandozeilenoption \tty{I} kann eine Liste
aller eingezogenen Include-Files mit ihrer Verschachtelung
ausgegeben werden (r3);}
\item{Beim \tty{END}-Statement kann jetzt zus"atzlich ein
Einsprungpunkt f"ur das Programm angegeben werden (r3).}
\item{unterst"utzt zus"atzlich die 68HC16-Familie von Motorola (r3);}
\item{P2HEX und P2BIN erlauben es jetzt, den Inhalt einer Code-Datei
adre"sm"a"sig zu verschieben (r4);}
\item{einem \tty{SHARED}-Befehl anh"angende Kommentare werden jetzt
in die Share-Datei mit "ubertragen (r4);}
\item{unterst"utzt zus"atzlich die 68HC12-Familie von Motorola (r4);}
\item{unterst"utzt zus"atzlich die XA-Familie von Philips (r4);}
\item{unterst"utzt zus"atzlich die 68HC08-Familie von Motorola (r4);}
\item{unterst"utzt zus"atzlich die AVR-Familie von Atmel (r4);}
\item{aus Kompatibilit"at zum AS11 von Motorola existieren zus"atzlich
die Befehle \tty{FCB}, \tty{FDB}, \tty{FCC} und \tty{RMB} (r5);}
\item{unterst"utzt zus"atzlich den M16C von Mitsubishi (r5);}
\item{unterst"utzt zus"atzlich den COP8 von National Semiconductor
(r5);}
\item{zwei neue Befehle zur bedingten Assemblierung: \tty{IFB} und
\tty{IFNB} (r5);}
\item{Mit dem \tty{EXITM}-Befehl ist es nun m"oglich, eine
Makroexpansion vorzeitig abzubrechen (r5);}
\item{unterst"utzt zus"atzlich den MSP430 von Texas Instruments
(r5);}
\item{\tty{LISTING} kennt zus"atzlich die Varianten
\tty{NOSKIPPED} und \tty{PURECODE}, um nicht assemblierten
Code aus dem Listing auszublenden (r5);}
\item{unterst"utzt zus"atzlich die 78K0-Familie von NEC (r5);}
\item{BIGENDIAN ist jetzt auch im PowerPC-Modus verf"ugbar (r5);}
\item{zus"atzlich ein \tty{BINCLUDE}-Befehl, um Bin"ardaten
einbinden zu k"onnen (r5);}
\item{zus"atzliche TOLOWER- und LOWSTRING-Funktionen, um
Gro"s- in Kleinbuchstaben umzuwandeln (r5);}
\item{es ist jetzt m"oglich, auch in anderen Segmenten als
CODE Daten abzulegen. Das Dateiformat wurde entsprechend
erweitert (r5);}
\item{der \tty{DS}-Befehl, mit dem man Speicherbereiche reservieren
kann, ist jetzt auch im Intel-Modus zul"assig (r5);}
\item{Mit der Kommandozeilenoption \tty{U} ist es jetzt
m"oglich, \asname{} in einen case-sensitiven Modus umzuschalten,
in dem Namen von Symbolen, selbst definierten Funktionen,
Makros, Makroparametern sowie Sektionen nach Gro"s-
und Kleinschreibung unterschieden werden (r5);}
\item{\tty{SFRB} ber"ucksichtigt jetzt auch die Bildungsregeln
f"ur Bitadressen im RAM-Bereich; werden nicht bitadressierbare
Speicherstellen angesprochen, erfolgt eine Warnung (r5);}
\item{zus"atzliche Pseudobefehle \tty{PUSHV} und \tty{POPV}, um
Symbolwerte tempor"ar zu sichern (r5);}
\item{zus"atzliche Funktionen \tty{BITCNT, FIRSTBIT, LASTBIT} und
\tty{BITPOS} zur Bitverarbeitung (r5);}
\item{bei den CPU32-Prozessoren ist jetzt auch der 68360
ber"ucksichtigt (r5);}
\item{unterst"utzt zus"atzlich die ST9-Familie von SGS-Thomson (r6);}
\item{unterst"utzt zus"atzlich den SC/MP von National Semiconductor
(r6);}
\item{unterst"utzt zus"atzlich die TMS70Cxx-Familie von Texas
Instruments (r6);}
\item{unterst"utzt zus"atzlich die TMS9900-Familie von Texas
Instruments (r6);}
\item{unterst"utzt zus"atzlich die Befehlssatzerweiterungen
des 80296 (r6);}
\item{die unterst"utzten Z8-Derivate wurden erweitert
(r6);}
\item{ber"ucksichtigt zus"atzlich die Maskenfehler des 80C504
von Siemens (r6);}
\item{zus"atzliche Registerdefinitionsdatei f"ur die C50x-Prozessoren
von Siemens (r6);}
\item{unterst"utzt zus"atzlich die ST7-Familie von SGS-Thomson (r6);}
\item{die Intel-Pseudobefehle zur Datenablage sind jetzt
auch f"ur 65816 bzw. MELPS-7700 zul"assig (r6);}
\item{f"ur 65816/MELPS-7700 kann die Adre"sl"ange jetzt durch
Pr"afixe explizit festgelegt werden (r6);}
\item{unterst"utzt zus"atzlich die 8X30x-Familie von Signetics
(r6);}
\item{\tty{PADDING} ist nur noch f"ur die 680x0-Familie defaultm"a"sig
eingeschaltet (r7);}
\item{"uber das neu eingef"uhrte, vordefinierte Symbol
\tty{ARCHITECTURE} kann ausgelesen werden, f"ur welche
Plattform \asname{} "ubersetzt wurde (r7);}
\item{Zus"atzliche Anweisungen \tty{STRUCT} und \tty{ENDSTRUCT} zur
Definition von Datenstrukturen (r7);}
\item{Hex- und Objekt-Dateien f"ur die AVR-Tools k"onnen jetzt
direkt erzeugt werden (r7);}
\item{\tty{MOVEC} kennt jetzt auch die 68040-Steuerregister (r7);}
\item{zus"atzliche \tty{STRLEN}-Funktion, um die L"ange eines
Strings zu ermitteln (r7);}
\item{M"oglichkeit zur Definition von Registersymbolen (r7, momentan
nur Atmel AVR);}
\item{kennt zus"atzlich die undokumentierten 6502-Befehle (r7);}
\item{P2HEX und P2BIN k"onnen jetzt optional die Eingabedateien
automatisch l"oschen (r7);}
\item{P2BIN kann der Ergebnisdatei optional zus"atzlich die
Startadresse voranstellen (r7);}
\item{unterst"utzt zus"atzlich die ColdFire-Familie von Motorola als
Variation des 680x0-Kerns (r7);}
\item{\tty{BYT/FCB, ADR/FDB} und \tty{FCC} erlauben jetzt auch den
von \tty{DC} her bekannten Wiederholungsfaktor (r7);}
\item{unterst"utzt zus"atzlich den M*Core von Motorola (r7);}
\item{der SH7000-Teil kennt jetzt auch die SH7700-Befehlserweiterungen
(r7);}
\item{der 680x0-Teil kennt jetzt auch die zus"atzlichen Befehle des
68040 (r7);}
\item{der 56K-Teil kennt jetzt auch die Befehlserweiterungen bis zum
56300 (r7).}
\item{Mit der neuen \tty{CODEPAGE}-Anweisung k"onnen jetzt auch
mehrere Zeichentabellen gleichzeitig verwaltet werden (r8);}
\item{Die Argumentvarianten f"ur \tty{CHARSET} wurden erweitert
(r8);}
\item{Neue String-Funktionen \tty{SUBSTR} und \tty{STRSTR} (r8);}
\item{zus"atzliches \tty{IRPC}-Statement im Makroprozessor (r8);}
\item{zus"atzlicher {\tt RADIX}-Befehl, um das Default-Zahlensystem
f"ur Integer-Konstanten festzulegen (r8);}
\item{statt {\tt ELSEIF} darf auch einfach {\tt ELSE} geschrieben
werden (r8);}
\item{statt $=$ darf als Gleichheitsoperator auch $==$ geschrieben
werden (r8);}
\item{\tty{BRANCHEXT} erlaubt es beim Philips XA jetzt, die
Sprungweite von kurzen Spr"ungen automatisch zu erweitern
(r8);}
\item{Debug-Ausgaben sind jetzt auch im NoICE-Format m"oglich (r8);}
\item{unterst"utzt zus"atzlich die i960-Familie von Intel (r8);}
\item{unterst"utzt zus"atzlich die $\mu$PD7720/7725-Signalprozssoren
von NEC (r8);}
\item{unterst"utzt zus"atzlich den $\mu$PD77230-Signalprozssor von
NEC (r8);}
\item{unterst"utzt zus"atzlich die SYM53C8xx-SCSI-Prozessoren von
Symbios Logic (r8);}
\item{unterst"utzt zus"atzlich den 4004 von Intel (r8);}
\item{unterst"utzt zus"atzlich die SC14xxx-Serie von National (r8);}
\item{unterst"utzt zus"atzlich die Befehlserweiterungen des PPC403GC
(r8);}
\item{zus"atzliche Kommandozeilenoption {\tt cpu}, um den
Zielprozessor-Default zu setzen (r8);}
\item{Key-Files k"onnen jetzt auch von der Kommandozeile aus
referenziert werden (r8);}
\item{zus"atzliche Kommandozeilenoption {\tt shareout}, um die
Ausgabedatei f"ur SHARED-Definitionen zu setzen (r8);}
\item{neuer Pseudobefehl {\tt WRAPMODE}, um AVR-Prozessoren mit
verk"urztem Programmz"ahler zu unterst"utzen (r8);}
\item{unterst"utzt zus"atzlich die C20x-Befehlsuntermenge im
C5x-Teil (r8);}
\item{hexadezimale Adre"sangaben der Hilfsprogamme k"onnen jetzt
auch in C-Notation gemacht werden (r8);}
\item{Das Zahlensystem f"ur Integerergebnisse in \verb!\{...}!-
Ausdr"ucken ist jetzt per \tty{OUTRADIX} setzbar (r8);}
\item{Die Registersyntax f"ur 4004-Registerpaare wurde korrigiert
(r8);}
\item{unterst"utzt zus"atzlich die F$^{2}$MC8L-Familie von Fujitsu
(r8);}
\item{f"ur P2HEX kann jetzt die Minimall"ange f"ur S-Record-Adressen
angegeben werden (r8);}
\item{unterst"utzt zus"atzlich die ACE-Familie von Fairchild (r8);}
\item{{\tt REG} ist jetzt auch f"ur PowerPCs erlaubt (r8);}
\item{zus"atzlicher Schalter in P2HEX, um alle Adressen zu
verschieben (r8);}
\item{Mit dem Schalter \tty{x} kann man jetzt zus"atzlich in einer
zweiten Stufe bie betroffene Quellzeile ausgeben (r8).}
\end{itemize}}
\begin{itemize}
\item{Die Default-Zahlensyntax f"ur Atmel AVR ist jetzt C-Syntax;}
\item{zus"atzliche Kommandozeilenoption {\tt olist}, um die
Listing-Ausgabedatei zu setzen;}
\item{unterst"utzt zus"atzlich die F$^{2}$MC16L-Familie von Fujitsu;}
\item{zus"atzlicher Befehl {\tt PACKING} f"ur die AVR-Familie;}
\item{zus"atzliche implizite Makroparameter {\tt ALLARGS} und
{\tt ARGCOUNT};}
\item{zus"atzlicher Befehl {\tt SHIFT} zum Abarbeiten variabler
Argumentlisten von Makros;}
\item{unterst"utzt tempor"are Symbole;}
\item{zus"atzlicher Befehl {\tt MAXNEST} zum Einstellen der
maximalen Verschachtelungstiefe von Makroexpansionen;}
\item{zus"atzliche Kommandozeilenoption {\tt noicemask}, um
die Menge der in einem NoICE-Debuginfofile gelisteten Segmente
zu steuern;}
\item{unterst"utzt zus"atzlich die 180x-Familie von Intersil;}
\item{unterst"utzt zus"atzlich das address windowing des 68HC11K4;}
\item{P2HEX kann jetzt die Adre"sfeldl"ange von AVR-Hex-Dateien
variieren;}
\item{mit der neuen Kommandozeilenoption {\tt -gnuerrors} k"onnen
Fehlermeldungen in einem GNU-C-artigen Format ausgegeben
werden;}
\item{unterst"utzt zus"atzlich die TMS320C54x-Familie von Texas
Instruments;}
\item{Neue Makro-Option {\tt INTLABEL};}
\item{die neuen Instruktionen und Register der MEGA-AVRs 8/16
wurden hinzugef"ugt;}
\item{{\tt ENDIF/ENDCASE} zeigen im Listing die Zeilennummer des
zugeh"origen "offnenden Befehls an;}
\item{der 8051-Teil unterst"utzt jetzt auch den erweiterten
Adre"sraum des Dallas DS80C390;}
\item{namenlose tempor"are Symbole hinzugef"ugt;}
\item{unterst"utzt zus"atzlich die undokumentierten 8085-Befehle;}
\item{verbesserte Behandlung von Strukturen;}
\item{Funktion EXPRTYPE() hinzugef"ugt;}
\item{Zeilenfortsetzungszeichen zulassen;}
\item{Unterst"utzung f"ur KCPSM/PicoBlaze von Andreass Wassatsch
integriert;}
\item{unterst"utzt zus"atzlich die 807x-Familie von National
Semiconductor;}
\item{unterst"utzt zus"atzlich den 4040 von Intel;}
\item{unterst"utzt zus"atzlich den eZ8 von Zilog;}
\item{unterst"utzt zus"atzlich die 78K2-Familie von NEC;}
\item{unterst"utzt zus"atzlich die KCPSM3-Variante von Xilinx;}
\item{unterst"utzt zus"atzlich den LatticeMico8;}
\item{unterst"utzt zus"atzlich die 12X-Befehlserweiterungen
und den XGATE-Kern der 68HC12-Familie;}
\item{unterst"utzt zus"atzlich den Signetics 2650;}
\item{unterst"utzt zus"atzlich die COP4-Familie von National
Semiconductor;}
\item{unterst"utzt zus"atzlich die HCS08-Erweiterungen von Freescale;}
\item{unterst"utzt zus"atzlich die RS08-Familie von Freescale;}
\item{unterst"utzt zus"atzlich den 8008 von Intel;}
\item{weitere Syntax f"ur Integer-Konstanten;}
\item{Funktion \tty{CHARFROMSTR} hinzugef"ugt;}
\item{Q f"ur Oktalkonstanten im Intel-Modus hinzugef"ugt;}
\item{weitere Variante f"ur tempor"are Symbole hinzugef"ugt;}
\item{der PowerPC-Teil wurde um Unterst"utzung f"ur den MPC821 erweitert
(Beitrag von Marcin Cieslak);}
\item{implizite Makro-Parameter sind immer case-insensitiv;}
\item{das \tty{REG}-Statement ist jetzt auch f"ur den MSP430
erlaubt;}
\item{unterst"utzt zus"atzlich den XS1 von XMOS;}
\item{zus"atzliche Parameter \tty{GLOBALSYMBOLS} und
\tty{NOGLOBALSYMBOLS} um zu steuern, ob Labels
in Makros lokal sind oder nicht;}
\item{kennt zus"atzlich die 75xx-Reihe von NEC;}
\item{kennt zus"atzlich die TMS1000-Controller von TI;}
\item{unterst"utzt zus"atzlich die 78K2-Familie von NEC;}
\item{alle neueren Anderungen werden nur noch in der
separaten changelog-Datei dokumentiert.}
\end{itemize}}
\end{itemize}
%%===========================================================================
\cleardoublepage
\chapter{Hinweise zum Quellcode von \asname{}}
Wie in der Einleitung erw"ahnt, gebe ich nach R"ucksprache den Quellcode
von \asname{} heraus. Im folgenden sollen einige Hinweise zu dessen Handhabung
gegeben werden.
%%---------------------------------------------------------------------------
Urspr"unglich war \asname{} ein in Turbo-Pascal geschriebenes Programm. F"ur
diese Entscheidung gab es Ende der 80er Jahre eine Reihe von Gr"unden:
Zum einen war ich damit wesentlich vertrauter als mit jedem C-Compiler,
zum anderen waren alle C-Compiler unter DOS verglichen mit der IDE von
Turbo-Pascal ziemliche Schnecken. Anfang 1997 zeichnete sich jedoch ab,
da"s sich das Blatt gewendet hatte: Zum einen hatte Borland beschlossen,
die DOS-Entwickler im Stich zu lassen (nochmals ausdr"ucklich keinen
sch"onen Dank, Ihr Pappnasen von Borland!), und Version 7.0 etwas namens
'Delphi' nachfolgen lie"sen, was zwar wohl wunderbar f"ur
Windows-Programme geeignet ist, die zu 90\% aus Oberfl"ache und zuf"allig
auch ein bi"schen Funktion bestehen, f"ur kommandozeilenorientierte
Progamme wie \asname{} aber reichlich unbrauchbar ist. Zum anderen hatte sich
bereits vor diesem Zeitpunkt mein betriebssystemm"a"siger Schwerpunkt
deutlich in Richtung Unix verschoben, und auf ein Borland-Pascal f"ur
Linux h"atte ich wohl beliebig lange warten k"onnen (an alle die, die
jetzt sagen, Borland w"urde ja an soetwas neuerdings basteln: Leute, das
ist {\em Vapourware}, und glaubt den Firmen nichts, solange Ihr nicht
wirklich in den Laden gehen und es kaufen k"onnt!). Von daher war also
klar, da"s der Weg in Richtung C gehen mu"ste.
Nach der Erfahrung, wohin die Verwendung von Inselsystemen f"uhrt, habe
ich bei der Umsetzung auf C Wert auf eine m"oglichst gro"se Portabilit"at
gelegt; da \asname{} jedoch z.B. Bin"ardateien in einem bestimmten Format
erzeugen mu"s und an einigen Stellen betriebssystemspezifische Funktionen
nutzt, gibt es einige Stellen, an denen man anpassen mu"s, wenn man \asname{} zum
ersten Mal auf einer neuen Plattform "ubersetzt.
\asname{} ist auf einen C-Compiler ausgelegt, der dem ANSI-Standard entspricht;
C++ ist ausdr"ucklich nicht erforderlich. Wenn Sie nur einen Compiler
nach dem veralteten Kernighan\&Ritchie-Standard besitzen, sollten Sie sich
nach einem neuen Compiler umsehen; der ANSI-Standard ist seit 1989
verabschiedet und f"ur jede aktuelle Plattform sollte ein ANSI-Compiler
verf"ugbar sein, zur Not, indem man mit dem alten Compiler GNU-C baut. Im
Quellcode sind zwar einige Schalter vorhanden, um den Code K\&R-n"aher zu
machen, aber dies ist ein nicht offiziell unterst"utztes Feature, das ich
nur intern f"ur ein ziemlich antikes Unix benutze. Alles weitere zum
'Thema K\&R' steht in der Datei {\tt README.KR}.
Der Sourcenbaum ist durch einige in der Pascal-Version nicht vorhandene
Features (z.B. dynamisch ladbare Nachrichtendateien, Testsuite,
automatische Generierung der Dokumentation aus {\em einem} Quellformat)
deutlich komplizierter geworden. Ich werde versuchen, die Sache Schritt
f"ur Schritt aufzudr"oseln:
%%---------------------------------------------------------------------------
\section{Abfangen von Systemabh"angigkeiten}
Wie ich schon andeutete, ist \asname{} (glaube ich jedenfalls...) auf
Plattformunabh"angigkeit und leichte Portierbarkeit getrimmt. Dies
bedeutet, da"s man die Platt\-form\-un\-ab\-h"an\-gig\-kei\-ten in
m"oglichst wenige Dateien zusammenzieht. Auf diese Dateien werde ich im
folgenden eingehen, und dieser Abschnitt steht ganz vorne, weil es sicher
eines der wichtigsten ist:
Die Generierung aller Komponenten von \asname{} erfolgt "uber ein zentrales {\tt
Makefile}. Damit dies funktioniert, mu"s man ihm ein passendes {\tt
Makefile.def} anbieten, das die plattformabh"angigen Einstellungen wie
z.B. Compilerflags vorgibt. Im Unterverzeichnis {\tt
Makefile.def-samples} finden sich eine Reihe von Includes, die f"ur
g"angige Plattformen funktionieren (aber nicht zwangsweise optimal sein
m"ussen...). Wenn die von Ihnen benutzte Plattform nicht dabei ist,
k"onnen Sie die Beispieldatei {\tt Makefile.def.tmpl} als Ausgangspunkt
verwenden (und das Ergebnis mir zukommen lassen!).
Ein weiterer Anlaufpunkt zum Abfangen von Systemabh"angigkeiten ist die
Datei {\tt sysdefs.h}. Praktisch alle Compiler definieren eine Reihe von
Pr"aprozessorsymbolen vor, die den benutzten Zielprozessor sowie das
benutzte Betriebsystem beschreiben. Auf einer Sun Sparc unter Solaris
mit den GNU-Compiler sind dies z.B. die Symbole \verb!__sparc! und
\verb!__SVR4!. In {\tt sysdefs.h} werden diese Symbole genutzt, um f"ur
die restlichen, systemunabh"angigen Dateien eine einheitliche Umgebung
bereitzustellen. Insbesondere betrifft dies Integer-Datentypen einer
bekannten L"ange, es kann aber auch die Nach- oder Redefinition von
C-Funktionen betreffen, die auf einer bestimmten Plattform nicht oder
nicht standardgem"a"s vorhanden sind. Was da so an Sachen anf"allt, liest
man am besten selber nach. Generell sind die \verb!#ifdef!-Statements in
zwei Ebenen gegliedert: Zuerst wird eine bestimmte Prozessorplattform
ausgew"ahlt, dann werden in diesem Abschnitt die Betriebssysteme
auseinandersortiert.
Wenn Sie \asname{} auf eine neue Plattform portieren, m"ussen Sie zwei f"ur diese
Plattform typische Symbole finden und {\tt sysdefs.h} passend erweitern
(und wieder bin ich an dem Ergebnis interessiert...).
%%---------------------------------------------------------------------------
\section{Systemunabh"angige Dateien}
...stellen den g"o"sten Teil aller Module dar. Alle Funktionen im Detail
zu beschreiben, w"urde den Rahmen dieser Beschreibung sprengen (wer hier
mehr wissen will, steigt am besten selbst in das Studium der Quellen ein,
so katastrophal ist mein Programmierstil nun auch wieder nicht...),
deshalb hier nur eine kurze Auflistung, welche Module vorhanden sind und
was f"ur Funktionen sie beinhalten:
Diese Datei ist die Wurzel von \asname{}: Sie enth"alt die {\em main()}-Funktion
von \asname{}, die Verarbeitung aller Kommandozeilenoptionen, die "ubergeordnete
Steuerung aller Durchl"aufe durch die Quelldateien sowie Teile des
Makroprozessors.
In diesem Modul werden all die Befehle bearbeitet, die f"ur alle Prozessoren
definiert sind, z.B. \tty{EQU} und \tty{ORG}. Hier findet sich auch der
\tty{CPU}-Befehl, mit dem zwischen den einzelnen Prozessoren hin- und
hergeschaltet wird.
In diesem Modul befindet sich die Verwaltung der Code-Ausgabedatei.
Exportiert wird ein Interface, mit dem sich eine Code-Datei "offnen
und schlie"sen l"a"st, und das Routinen zum Einschreiben (und
Zur"ucknehmen) von Code anbietet. Eine wichtige Aufgabe dieses Moduls
ist die Pufferung des Schreibvorgangs, die die Ausgabegeschwindigkeit
erh"oht, indem der erzeugte Code in gr"o"seren Bl"ocken geschrieben wird.
Optional kann \asname{} Debug-Informationen f"ur andere Tools wie Simulatoren
oder Debugger erzeugen, die einen R"uckbezug auf den Quellcode erlauben,
in diesem Modul gesammelt und nach Ende der Assemblierung in einem von
mehreren Formaten ausgegeben werden k"onnen.
Dieses Modul enth"alt lediglich Deklarationen von "uberall ben"otigten
Konstanten und gemeinsam benutzten Variablen.
Intern vergibt \asname{} f"ur jede benutzte Quelldatei eine fortlaufende Nummer,
die zur schnellen Referenzierung benutzt wird. Die Vergabe dieser Nummern
und die Umwandlung zwischen Nummer und Dateinamen passiert hier.
Hier befinden sich alle Routinen, die die bedingte Assemblierung steuern.
Exportiert wird als wichtigste Variable das Flag \tty{IfAsm}, welches
anzeigt, ob Codeerzeugung momentan ein- oder ausgeschaltet ist.
In diesem Modul ist die Listenstruktur definiert, "uber die \asname{} die
Verschachtelung von Include-Dateien im Listing ausgeben kann.
Wenn man in einer Code-Zeile das benutzende Mnemonic ermitteln will, ist
das einfache Durchvergleichen mit allen vorhandenen Befehlen (wie es noch
in vielen Codegeneratoren aus Einfachheit und Faulheit passiert) nicht
unbedingt die effizienteste Variante. In diesem Modul sind zwei
verbesserte Strukturen (Bin"arbaum und Hash-Tabelle) definiert, die eine
effizientere Suche erm"oglichen und die einfache lineare Suche nach und
nach abl"osen sollen...Priorit"at nach Bedarf...
In diesem Modul finden sich die Routinen zur Speicherung und Abfrage von
Makros. Der eigentliche Makroprozessor befindet sich (wie bereits
erw"ahnt) in {\tt as.c}.
Hier geht es ins Eingemachte: In diesem Modul werden die Symboltabellen
(global und lokal) in zwei Bin"arb"aumen verwaltet. Au"serdem findet sich
hier eine ziemlich gro"se Prozedur \tty{EvalExpression}, welche einen
(Formel-)ausdruck analysiert und auswertet. Die Prozedur liefert das
Ergebnis (Integer, Gleitkomma oder String) in einem varianten Record zur"uck.
Zur Auswertung von Ausdr"ucken bei der Codeerzeugung sollten allerdings eher
die Funktionen \tty{EvalIntExpression, EvalFloatExpression} und
\tty{EvalStringExpression} verwendet werden. "Anderungen zum Einf"ugen neuer
Prozessoren sind hier nicht erforderlich und sollten auch nur mit "au"serster
"Uberlegung erfolgen, da man hier sozusagen an ,,die Wurzel'' von \asname{} greift.
Hier finden sich gesammelt einige h"aufig gebrauchte Unterroutinen, welche
in erster Linie die Bereiche Fehlerbehandlung und 'gehobene'
Stringverarbeitung abdecken.
Wie am Anfang erw"ahnt, war \asname{} urspr"unglich ein in Borland-Pascal
geschriebenes Programm. Bei einigen intrinsischen Funktionen des
Compilers war es einfacher, diese zu emulieren, anstatt alle betroffenen
Stelle im Quellcode zu "andern. Na ja...
Dieses Modul definiert einen Datentyp, mit dem eine Liste von
Adre"sbereichen verwaltet werden kann. Diese Funktion wird von \asname{}
f"ur die Belegungslisten ben"otigt, au"serdem benutzten P2BIN und
P2HEX diese Listen, um vor "Uberlappungen zu warnen.
Dieses Modul implementiert den Mechanismus der Kommdozeilenparameter. Es
ben"otigt eine Spezifikation der erlaubten Parameter, zerlegt die
Kommadozeile und ruft die entsprechenden Callbacks auf. Der Mechanismus
leistet im einzelnen folgendes:
\begin{itemize}
\item{Mitbearbeitung von Optionen in einer Environment-Variablen oder
entsprechenden Datei;}
\item{R"uckgabe einer Menge, welche die noch nicht bearbeiteten
Kommandozeilenparameter beschreibt;}
\item{Trenunng von positiven und negativen Schaltern;}
\item{Eine Hintert"ur, falls die dar"uberliegende Entwicklungsumgebung die
Kommandozeile nur in Gro"s- oder Kleinschreibung "ubergibt.}
\end{itemize}
Dieses Modul wird nicht nur von \asname{}, sondern auch von den Hilfsprogrammen
\tty{BIND, P2HEX und P2BIN} verwendet.
Hier finden sich Pseudobefehle, die von mehreren Codegeneratoren verwendet
werden. Dies ist einmal die Intel-Gruppe mit der \tty{DB..DT}-Gruppe,
zum anderen die Pendants f"ur die 8/16-Bitter von Motorola oder Rockwell.
Wer in diesem Bereich um einen Prozessor erweitern will, kann mit einem
Aufruf den gr"o"sten Teil der Pseudobefehle erschlagen.
Aus Speicherersparnisgr"unden sind hier einige von diversen
Codegeneratoren benutzen Variablen gesammelt.
Doch noch ein bi"schen Maschinenabh"angigkeit, jedoch ein Teil, um den man
sich nicht zu k"ummern braucht: Ob eine Maschine Little- oder
Big-Endianess benutzt, wird in diesem Modul beim Programmstart automatisch
bestimmt. Weiterhin wird gepr"uft, ob die in {\tt sysdefs.h} gemachten
Typfestlegungen f"ur Integervariablen auch wirklich die korrekten L"angen
ergeben.
Gesammelt sind hier alle von \asname{} unterst"utzten Zielprozessorfamilien, die
daf"ur in Code-Dateien verwendeten Kennzahlen (siehe Kapitel
\ref{SectCodeFormat}) sowie das von P2HEX defaultm"a"sig zu verwendende
Ausgabeformat. Ziel dieser Tabelle ist es, Das Hinzuf"ugen eines neuen
Prozessors m"oglichst zu zentralisieren, d.h. es sind im Gegensatz zu
fr"uher keine weiteren Modifikationen an den Quellen der Hilfsprogramme
mehr erforderlich.
Hier ist die Umwandlung von Fehlernummern in Klartextmeldungen abgelegt.
Hoffentlich treffe ich nie auf ein System, auf dem die Nummern nicht als
Makros definiert sind, dann kann ich n"amlich dieses Modul komplett
umschreiben...
Die C-Version von \asname{} liest alle Meldungen zur Laufzeit aus Dateien, nachdem
die zu benutzende Sprache ermittelt wurde. Das Format der
Nachrichtendateien ist kein einfaches, sondern ein spezielles, kompaktes,
vorindiziertes Format, das zur "Ubersetzungszeit von einem Programm namens
'rescomp' (dazu kommen wir noch) erzeugt wird. Dieses Modul ist das
Gegenst"uck zu rescomp, die den korrekten Sprachenanteil einer Datei in ein
Zeichenfeld einliest und Zugriffsfunktionen anbietet.
In diesem Modul wird ermittelt, welche nationalen Einstellungen (Datums-
und Zeitformat, L"andercode) zur Laufzeit vorliegen. Das ist leider eine
hochgradig systemspezifische Sache, und momentan sind nur drei Methoden
definiert: Die von MS-DOS, die von OS/2 und die typische Unix-Methode
"uber die {\em locale}-Funktionen. F"ur alle anderen Systeme ist leider
\verb!NO_NLS! angesagt...
Zum einen ist hier eine spezielle open-Funktion gelandet, die die
Sonderstrings {\tt !0...!2} als Dateinamen kennt und daf"ur Duplikate der
Standard-Dateihandles {\em stdin, stdout} und {\em stderr} erzeugt, zum
anderen wird hier festgestellt, ob die Standardausgabe auf ein Ger"at oder
eine Datei umgeleitet wurde. Das bedingt auf nicht-Unix-Systemen leider
auch einige Speziall"osungen.
Dies ist nur ein kleiner ,,Hack'', der Routinen zur Verwaltung von linearen
Listen mit Strings als Inhalt definiert, welche z.B. im Makroprozessor von
\asname{} gebraucht werden.
Hier sind einige h"aufig genutzte String-Operationen gelandet.
Die momentan g"ultige Version ist f"ur \asname{} und alle anderen Hilfsprogramme
hier zentral gespeichert.
Dies Module bilden den Hauptteil der \asname{}-Quellen: jedes Modul beinhaltet
den Codegenerator f"ur eine bestimmte Prozessorfamilie.
\subsection{Zus"atzliche Module f"ur die Hilfsprogramme}
Ein kleines Modul zur Umwandlung von Integerzahlen in
Hexadezimaldarstellung. In C nicht mehr unbedingt erforderlich (au"ser
zur Wandlung von {\em long long}-Variablen, was leider nicht alle {\tt
printf()}'s unterst"utzen), aber es ist im Rahmen der Portierung eben auch
stehengeblieben.
Die Quellen von P2BIN.
Die Quellen von P2HEX.
Die Quellen von BIND.
Die Quellen von PLIST.
Hier sind gesammelt die Unterroutinen, die von allen Hilfsprogrammen
ben"otigt werden, z.B. f"ur das Lesen von Code-Dateien.
\section{W"ahrend der Erzeugung von \asname{} gebrauchte Module}
Dies ist ein Minimalfilter, das ANSI-C-Files in Kernighan-Ritchie
umwandelt. Um es genau zu sagen: es werden nur die Funktionsk"opfe
umgewandelt, und auch nur dann, wenn sie ungef"ahr so formatiert sind, wie
es mein Schreibstil eben ist. Es komme also keiner auf die Idee, das
w"are ein universeller C-Parser!
Ein kleiner Filter, der bei der Installation auf DOS- oder OS/2-Systemen
gebraucht wird. Da DOS und OS/2 den Zeilenvorschub mit CR/LF vornehmen,
Unix-Systeme jedoch nur mit LF, werden s"amtliche mitgelieferten
Assembler-Includes bei der Installation durch diesen Filter geschickt.
F"ur DOS und OS/2 "ubernimmt dieses Modul die Funktion die Funktion des
{\em cmp}-Befehls, d.h. den bin"aren Vergleich von Dateien w"ahrend des
Testlaufes. W"ahrend dies prinzipiell auch mit dem mitgelieferten {\em
comp} m"oglich w"are, hat {\em bincmp} keine l"astigen interaktiven
Abfragen (bei denen man erst einmal herausfinden mu"s, wie man sie auf
allen Betriebssystemversionen abstellt...)
Dies ist das Untermodul in {\em tex2doc}, da"s f"ur die Silbentrennung von
Worten sorgt. Der verwendete Algorithmus is schamlos von TeX
abgekupfert.
Die Definition der Silbentrennungsregeln f"ur die deutsche Sprache.
Dies ist der 'Resourcencompiler' von \asname{}, d.h. das Werkzeug, das die
lesbaren Dateien mit Stringresourcen in ein schnelles, indiziertes Format
umsetzt.
Ein Werkzeug, da"s die LaTeX-Dokumentation von \asname{} in ein ASCII-Format
umsetzt.
Ein Werkzeug, da"s die LaTeX-Dokumentation von \asname{} in ein HTML-Dokument
umsetzt.
Diese Progr"ammchen besorgen die Wandlung zwischen Sonderzeichenkodierung
im ISO-Format (alle \asname{}-Dateien verwenden im Auslieferungszustand die
ISO8859-1-Kodierung f"ur Sonderzeichen) und Sonderzeichenkodierung im
systemspezifischen Format. Neben einer Plain-ASCII7-Variante sind dies im
Augenblick die IBM-Zeichens"atze 437 und 850.
Die Definition der Silbentrennungsregeln f"ur die englische Sprache.
%%---------------------------------------------------------------------------
\section{Generierung der Nachrichtendateien}
Wie bereits erw"ahnt, verwendet der C-Quellenbaum von \asname{} ein dynamisches
Ladeverfahren f"ur alle (Fehler-)Meldungen. Gegen"uber den
Pascal-Quellen, in denen alle Meldungen in einem Include-File geb"undelt
waren und so in die Programme hinein"ubersetzt wurden, macht es dieses
Verfahren "uberfl"ussig, mehrere sprachliche Varianten von \asname{} zur
Verf"ugung zu stellen: es gibt nur noch eine Version, die beim
Programmstart die zu benutzende Variante ermittelt und aus den
Nachrichtendateien die entsprechende Komponente l"adt. Kurz zur
Erinnerung: Unter DOS und OS/2 wird dazu die gew"ahlte {\tt
COUNTRY}-Einstellung zu Rate gezogen, unter Unix werden die
Environment-Variablen {\tt LC\_MESSAGES, LC\_ALL} und {\tt LANG} befragt.
Eine Quelldatei f"ur den Message-Compiler {\em rescomp} hat "ublicherweise
die Endung {\tt .res}. Der Message-Compiler erzeugt aus dieser Datei ein
oder zwei Dateien:
\begin{itemize}
\item{eine bin"are Datei, die zur Laufzeit von \asname{} bzw. den Hilfsprogrammen
gelesen wird;}
\item{optional eine weitere C-Header-Datei, die allen vorhandenen
Nachrichten eine Indexnummer zuweist. "Uber diese Indexnummern und
eine Indextabelle in der bin"aren Datei kann zur Laufzeit schnell
auf einzelne Meldungen zugegriffen werden.}
\end{itemize}
Die Quelldatei f"ur den Message-Compiler ist eine reine ASCII-Datei, also
mit jedem beliebigen Editor bearbeitbar, und besteht aus einer Reihe von
Steueranweisungen mit Parametern. Leerzeilen sowie Zeilen, die mit einem
Semikolon beginnen, werden ignoriert. Das Inkludieren anderer Dateien ist
"uber das {\tt Include}-Statement m"oglich:
\begin{verbatim}
Include <Datei>
\end{verbatim}
Am Anfang jeder Quelldatei m"ussen zwei Statements stehen, die die im
folgenden definierten Sprachen beschreiben. Das wichtigere der beiden
Statements ist {\tt Langs}, z.B.:
\begin{verbatim}
Langs DE(049) EN(001,061)
\end{verbatim}
beschreibt, da"s zwei Sprachen im folgenden definiert werden. Der erste
Nachrichtensatz soll benutzt werden, wenn unter Unix die Sprache per
Environment-Variablen auf {\tt DE} gestellt wurde bzw. unter DOS bzw. OS/2
der Landescode 049 eingestellt wurde. Der zweite Satz kommt
dementsprechend bei den Einstellungen {\tt EN} bzw. 061 oder 001 zum
Einsatz. W"ahrend bei den 'Telefonnummern' mehrere Codes auf einen
Nachrichtensatz verweisen k"onnen, ist die Zuordnung zu den
Unix-Landescodes eineindeutig. Dies ist in der Praxis aber kein
Beinbruch, weil die {\tt LANG}-Variablen unter Unix Unterversionen einer
Sprache als Anh"angsel beschreiben, z.B. so:
\begin{verbatim}
de.de
de.ch
en.us
\end{verbatim}
\asname{} vergleicht nur den Anfang der Strings und kommt so trotzdem zur
richtigen Entscheidung.
Das {\tt Default}-Statement gibt vor, welcher Sprachensatz verwendet
werden soll, wenn entweder "uberhaupt keine Sprache gesetzt wurde oder
eine Kennung verwendet wird, die nicht in der Liste von {\tt Langs}
vorhanden ist. Typischerweise ist dies Englisch:
\begin{verbatim}
Default EN
\end{verbatim}
Nach diesen beiden Definitionen folgt eine beliebige Menge von {\tt
Message}-Statements, d.h. Definitionen von Meldungen:
\begin{verbatim}
Message ErrName
": Fehler "
": error "
\end{verbatim}
Wurden {\em n} Sprachen im {\tt Langs}-Statement angek"undigt, so nimmt
der Message-Compiler {\bf genau} die folgenden {\em n} Zeilen als die zu
speichernden Strings. Es ist also nicht m"oglich, bei einzelnen
Nachrichten bestimmte Sprachen fortzulassen, und eine auf die Strings
folgende Leerzeile ist keinesfalls als Endemarkierung f"ur die Liste
mi"szuverstehen; eingef"ugte Leerzeilen dienen einzig und allein der
besseren Lesbarkeit. Was allerdings erlaubt ist, ist, einzelne Meldungen
"uber mehrere Zeilen in der Quelldatei zu verteilen; alle Zeilen bis auf
die letzte m"ussen dann mit einem Backslash als Fortsetzungszeichen enden:
\begin{verbatim}
Message TestMessage2
"Dies ist eine" \
"zweizeilige Nachricht"
"This is a" \
"two-line message"
\end{verbatim}
Wie bereits erw"ahnt, handelt es sich bei den Quelldateien um reine
ASCII-Dateien; Sonderzeichen k"onnen in den Meldungstexten zwar
eingetragen werden (und der Compiler wird sie auch so durchreichen), der
gravierende Nachteil ist aber, da"s eine solche Datei nicht mehr voll
portabel ist: Wird sie auf ein anderes System gebracht, das z.B. eine
andere Kodierung f"ur Umlaute verwendet, bekommt der Anwender zur Laufzeit
nur merkw"urdige Zeichen zu sehen...Sonderzeichern sollten daher immer mit
Hilfe von speziellen Sequenzen geschrieben werden, die von HTML bzw. SGML
entlehnt wurden (siehe Tabelle \ref{TabSpecChars}). Zeilenvorsch"ube
k"onnen in eine Zeile wie von C her gewohnt mit \verb!\n! eingebracht
werden.
\begin{table*}[htb]
\begin{center}\begin{tabular}{|l|l|}
Sequenz... & ergibt... \\
\verb!ä ö ü! & "a "o "u (Umlaute)\\
\verb!Ä Ö Ü! & "A "O "U \\
\verb!ß! & "s (scharfes s) \\
\verb!à è ì ò ù! & \'a \'e \'i \'o \'u (Accent \\
\verb!À È Ì Ò Ù! & \'A \'E \'I \'O \'U grave) \\
\verb!á é í ó ú! & \`a \`e \`i \`o \`u (Accent \\
\verb!Á É Í Ó Ú! & \`A \`E \`I \`O \`U agiu) \\
\verb!â ê î ô û! & \^a \^e \^i \^o \^u (Accent \\
\verb!Â Ê Î Ô Û! & \^A \^E \^I \^O \^U circonflex) \\
\verb!ç Ç! & \c{c} \c{C}(Cedilla) \\
\verb!ñ Ñ! & \~n \~N \\
\verb!å Å! & \aa \AA \\
\verb!æ &Aelig;! & \ae \AE \\
\verb!¿ ¡! & umgedrehtes ! oder ? \\
\end{tabular}\end{center}
\caption{Sonderzeichenschreibweise des {\em rescomp}\label{TabSpecChars}}
\end{table*}
%%---------------------------------------------------------------------------
In einer Quellcodedistribution von \asname{} ist diese Dokumentation nur als
LaTeX-Dokument enthalten. Andere Formate werden aus dieser mit Hilfe von
mitgelieferten Werkzeugen automatisch erzeugt. Zum einen reduziert dies
den Umfang einer Quellcodedistribution, zum anderen m"ussen "Anderungen
nicht an allen Formatversionen eines Dokumentes parallel vorgenommen
werden, mit all den Gefahren von Inkonsistenzen.
Als Quellformat wurde LaTeX verwendet, weil...weil...weil es eben schon
immer vorhanden war. Zudem ist TeX fast beliebig portierbar und pa"st
damit recht gut zum Anspruch von \asname{}. Eine Standard-Distribution erlaubt
damit eine 'ordentliche' Ausgabe auf so ziemlich jedem Drucker; f"ur eine
Konvertierung in die fr"uher immer vorhandene ASCII-Version liegt der
Konverter {\em tex2doc} bei; zus"atzlich einen Konverter {\em tex2html},
so da"s man die Anleitung direkt ins Internet stellen kann.
Die Erzeugung der Dokumentation wird mit einem schlichten
\begin{verbatim}
make docs
\end{verbatim}
angesto"sen; daraufhin werden die beiden erw"ahnten Hilfstools erzeugt,
auf die TeX-Dokumentation angewandt und schlu"sendlich wird noch LaTeX
selber aufgerufen. Dies nat"urlich f"ur alle Sprachen nacheinander...
%%---------------------------------------------------------------------------
Da \asname{} mit bin"aren Daten von genau vorgegebener Struktur umgeht, ist er
naturgem"a"s etwas empfindlich f"ur System- und Compilerabh"angigkeiten.
Um wenigstens eine gewisse Sicherheit zu geben, da"s alles korrekt
durchgelaufen ist, liegt dem Assembler im Unterverzeichnis {\tt tests}
eine Menge von Test-Assemblerquellen bei, mit denen man den frisch
gebauten Assembler testen kann. Diese Testprogramme sind in erster Linie
darauf getrimmt, Fehler in der Umsetzung des Maschinenbefehlssatzes zu
finden, die besonders gern bei variierenden Wortl"angen auftreten.
Maschinenunabh"angige Features wie der Makroprozessor oder bedingte
Assemblierung werden eher beil"aufig getestet, weil ich davon ausgehe,
da"s sie "uberall funktionieren, wenn sie bei mir funktionieren...
Der Testlauf wird mit einem einfachen {\em make test} angesto"sen. Jedes
Testprogramm wird assembliert, in eine Bin"ardatei gewandelt und mit einem
Referenz-Image verglichen. Ein Test gilt als bestanden, wenn Referenz und
die neu erzeugte Datei Bit f"ur Bit identisch sind. Am Ende wird
summarisch die Assemblierungszeit f"ur jeden Test ausgegeben (wer will,
kann mit diesen Ergebnissen die Datei {\tt BENCHES} erg"anzen), zusammen
mit dem Erfolg oder Mi"serfolg. Jedem Fehler ist auf den Grund zu gehen,
selbst wenn er bei einem Zielprozessor auftritt, den Sie nie nutzen
werden! Es ist immer m"oglich, da"s dies auf einen Fehler hinweist, der
auch bei anderen Zielprozessoren auftritt, nur zuf"allig nicht in den
Testf"allen.
%%---------------------------------------------------------------------------
\section{Einh"angen eines neuen Zielprozessors}
Der mit Abstand h"aufigste Grund, im Quellcode von \asname{} etwas zu ver"andern,
d"urfte wohl die Erweiterung um einen neuen Zielprozessor sein. Neben der
Erg"anzung der Makefiles um das neue Modul ist lediglich eine Modifikation
der Quellen an wenigen Stellen erforderlich, den Rest erledigt das neue
Modul, indem es sich in der Liste der Codegeneratoren registriert. Im
folgenden will ich kochbuchartig die zum Einh"angen erforderlichen
Schritte beschreiben:
Der f"ur den Prozessor zu w"ahlende Name mu"s zwei Kriterien erf"ullen:
\begin{enumerate}
\item{Der Name darf noch nicht von einem anderen Prozessor belegt sein.
Beim Aufruf von \asname{} ohne Parameter erh"alt man eine Liste der bereits
vorhandenen Namen.}
\item{Soll der Prozessorname vollst"andig in der Variablen \tty{MOMCPU}
auftauchen, so darf er au"ser am Anfang keine Buchstaben au"serhalb
des Bereiches von A..F enthalten. In der Variablen \tty{MOMCPUNAME}
liegt aber zur Assemblierzeit immer der volle Name vor.
Sonderzeichen sind generell nicht erlaubt, Kleinbuchstaben
werden vom CPU-Befehl bei der Eingabe in Gro"sbuchstaben umgewandelt
und sind daher auch nicht im Prozessornamen sinnvoll.}
\end{enumerate}
Der erste Schritt der Registrierung ist die Eintragung des Prozessors oder
der Prozessorfamilie in der Datei {\tt headids.c}. Wie bereits erw"ahnt,
wird diese Datei von den Hilfsprogrammen mitbenutzt und spezifiziert die
einer Prozessorfamilie zugeordnete Kenn-ID in Codedateien sowie das zu
verwendende Hex-Format. Bei der Wahl der Kenn-ID w"urde ich mir etwas
Absprache w"unschen...
Das Modul, das f"ur den neuen Prozessor zust"andig sein soll, sollte einer
gewissen Einheitlichkeit wegen den Namen \tty{code....} tragen, wobei
\tty{.....} etwas mit dem Prozessornamen zu tun haben sollte. Den Kopf
mit den Includes "ubernimmt man am besten direkt aus einem bereits
vorhandenen Codegenerator.
Mit Ausnahme einer Initialisierungsfunktion, die zu Anfang der {\tt
main()}-Funktion im Modul {\tt as.c} aufgerufen werden mu"s, braucht das
neue Modul keinerlei Funktionen oder Variablen zu exportieren, da die
ganze Kommunikation zur Laufzeit "uber indirekte Spr"unge abgewickelt
wird. Die dazu erforderlichen Registrierungen m"ussen in der
Initialisierungsfunktion des Moduls vorgenommen werden, indem f"ur jeden
von der Unit zu behandelnden Prozessortyp
ein Aufruf der Funktion \tty{AddCPU} erfolgt:
\begin{verbatim}
CPUxxxx = AddCPU("XXXX", SwitchTo_xxxx);
\end{verbatim}
\tty{'XXXX'} ist dabei der f"ur den Prozessor festgelegte Name, der sp"ater
im Assemblerprogramm verwendet werden mu"s, um \asname{} auf diesen Zielprozessor
umzuschalten. \tty{SwitchTo\_xxxx} (im folgenden kurz als ,,Umschalter''
bezeichnet) ist eine parameterlose Prozedur, die von \asname{} aufgerufen wird,
sobald auf diesen Prozessor umgeschaltet werden soll. Als Ergebnis liefert
\tty{AddCPU} eine Zahlenwert, der als interne ,,Kennung'' f"ur diesen Prozessor
fungiert. In der globalen Variablen \tty{MomCPU} wird st"andig die Kennung
des momentan gesetzten Zielprozessors mitgef"uhrt. Der von \tty{AddCPU}
gelieferte Wert sollte in einer privaten Variable des Typs \tty{CPUVar} (hier
\tty{CPUxxxx} genannt) abgelegt werden. Falls ein Codegeneratormodul
verschiedene Prozessoren (z.B. einer Familie) verwaltet, kann es so
durch Vergleich von \tty{MomCPU} gegen diese Werte feststellen, welche
Befehlsuntermenge momentan zugelassen ist.
Dem Umschalter obliegt es, \asname{} auf den neuen Zielprozessor ,,umzupolen''.
Dazu m"ussen im Umschalter einige globale Variablen besetzt werden:
\begin{itemize}
\item{\tty{ValidSegs} : Nicht alle Prozessoren definieren alle von \asname{}
unterst"utzten Adre"sr"aume. Mit dieser Menge legt man fest,
welche Untermenge f"ur den jeweiligen Prozessor von \tty{SEGMENT}-Befehl
zugelassen wird. Im mindesten mu"s das Code-Segment freigeschaltet
werden. Die Gesamtmenge aller vorhandenen Segmenttypen kann in der
Datei \tty{fileformat.h} nachgelesen werden (\tty{Seg}.....-Konstanten).}
\item{\tty{SegInits} : Dieses Feld speichert die initialen (ohne \tty{ORG}-Befehl)
Startadressen in den einzelnen Segmenten. Nur in Ausnahmef"allen
(physikalisch "uberlappende, aber logisch getrennte Adre"sr"aume)
sind hier andere Werte als 0 sinnvoll.}
\item{\tty{Grans} : Hiermit kann f"ur jedes Segment die Gr"o"se des kleinsten
adressierbaren Elements in Bytes festgelegt werden, d.h. die
Gr"o"se des Elements, f"ur das eine Adresse um eins erh"oht wird.
Bei den allermeisten Prozessoren (auch 16 oder 32 Bit) ist dies
ein Byte, nur z.B. Signalprozessoren und die PICs fallen aus dem
Rahmen.}
\item{\tty{ListGrans} : Hiermit kann wieder f"ur alle Segmente getrennt
festgelegt werden, in was f"ur Gruppen die Bytes im Assemblerlisting
dargestellt werden sollen. Beim 68000 sind z.B. Befehle immer
ein mehrfaches von 2 Bytes lang, weshalb die entsprechende Variable
auf 2 gesetzt ist.}
\item{\tty{SegLimits} : Dieses Feld legt die h"ochste Adresse f"ur jedes
Segment fest, z.B. 65535 f"ur einen 16-Bit-Adre"sraum. Dieses Feld
braucht nicht ausgef"ullt zu werden, wenn der Codegenerator die {\tt
ChkPC}-Methode selber "ubernimmt.}
\item{\tty{ConstMode} : Diese Variable kann die Werte \tty{ConstModeIntel},
\tty{ConstModeMoto} oder \tty{ConstModeC} haben und bestimmt, in
welcher Form Zahlensysteme bei Integerkonstanten spezifiziert werden
sollen (sofern das Programm nicht vom Relaxed-Modus Gebrauch macht).}
\item{\tty{PCSymbol} : Diese Variable enth"alt den String, mit dem aus dem
Assembler-Programm heraus der momentane Stand des Programmz"ahlers
abgefragt werden kann. F"ur Intel-Prozessoren ist dies z.B. ein
Dollarzeichen.}
\item{\tty{TurnWords} : Falls der Prozessor ein Big-Endian-Prozessor sein
sollte und eines der Elemente von \tty{ListGrans} ungleich eins ist,
sollte dieses Flag auf True gesetzt werden, um korrekte Code-Dateien
zu erhalten.}
\item{\tty{SetIsOccupiedFnc} : Einige Prozessoren verwenden \tty{SET} als
Maschinenbefehl. Ist dieser Callback gesetzt, so kann der Codegenerator
dar"uber melden, da"s \tty{SET} nicht als Pseudo-Befehl interpretiert
werden soll. Der R"uckgabewert kann konstant \tty{True} sein, die
Entscheidung kann aber auch z.B. anhand der Anzahl der Argumente fallen.}
\item{\tty{HeaderID} : Dieses Byte enth"alt die Kennung, mit der in der Codedatei
die Prozessorfamilie gekennzeichnet wird (siehe Abschnitt
\ref{SectCodeFormat}). Um Zweideutigkeiten zu vermeiden,
bitte ich, den Wert mit mir abzusprechen. Bis auf weiteres sollten
keine Werte au"serhalb des Bereiches \$01..\$7f benutzt werden,
diese sind f"ur Sonderzwecke (wie z.B. eine zuk"unftige Erweiterung
um einen Linker) reserviert. Auch wenn dieser Wert in den meisten
"alteren Codegeneratoren hart gesetzt wird, ist es die heute
bevorzugte Methode, den Wert aus {\tt headids.h} per {\tt
FindFamilyByName} zu holen.}
\item{\tty{NOPCode} : In bestimmten Situationen kann es sein, da"s \asname{} unbenutzte
Bereiche im Code mit NOPs auff"ullen mu"s. Diese Variable beinhaltet
den dazu erforderlichen Code.}
\item{\tty{DivideChars} : Dieser String enth"alt all jene Zeichen, die als
Trennzeichen f"ur die Parameter eines Assemblerbefehls zugelassen
sind. Nur f"ur extreme Ausrei"ser (wie den DSP56) sollte sich in
diesem String etwas anderes finden als ein Komma.}
\item{\tty{HasAttrs} : Einige Prozessoren wie die 68k-Reihe teilen einen
Maschinenbefehl durch einen Punkt noch weiter in Mnemonic und
Attribut auf. Ist dies beim neuen Prozessor auch der Fall, so
ist dieses Flag auf True zu setzen. \asname{} liefert dann die Einzelteile
in den Variablen \tty{OpPart} und \tty{AttrPart}. Setzt man es
dagegen auf False, so bleibt der Befehl in \tty{OpPart} zusammen,
und \tty{AttrPart} ist immer leer. Sofern der Prozessor keine
Attribute verwendet, sollte man \tty{HasAttrs} auf jeden Fall auf False
setzen, da man sich sonst die M"oglichkeit nimmt, Makros mit einem
Punkt im Namen (z.B. zur Emulation anderer Assembler) zu definieren.}
\item{\tty{AttrChars} : Falls \tty{HasAttrs} gesetzt wurde, m"ussen in diesem
String alle Zeichen eingetragen werden, die das Attribut vom Befehl
trennen k"onnen. Meist ist dies nur der Punkt.}
\end{itemize}
Gehen Sie nicht davon aus, da"s eine dieser Variablen einen vordefinierten
Wert hat, sondern besetzen Sie \bb{ALLE} Felder neu!!
Neben diesen Variablen m"ussen noch einige Funktionszeiger besetzt wird,
mit denen der Codegenerator sich in \asname{} einbindet:
\begin{itemize}
\item{\tty{MakeCode} : Diese Routine wird nach der Zerlegung einer Zeile
in Mnemonic und Parameter aufgerufen. Das Mnemonic liegt in der
Variablen \tty{OpPart}, die Parameter in dem Feld \tty{ArgStr}.
Die Zahl der Parameter kann aus der Variablen \tty{ArgCnt} ausgelesen
werden. Das bin"are Ergebnis mu"s in dem Byte-Feld \tty{BAsmCode}
abgelegt werden, dessen L"ange in der Variablen \tty{CodeLen}. Falls
der Prozessor wortorientiert wie der 68000 oder viele Signalprozessoren
ist, kann Feld auch wortweise als \tty{WAsmCode} adressiert werden.
F"ur ganz extreme F"alle gibt es auch noch \tty{DAsmCode}... Die
Codel"ange wird ebenfalls in solchen Einheiten angegeben.}
\item{\tty{SwitchFrom}: Diese parameterlose Prozedur erlaubt dem
Codegeneratormodul, noch ,,Aufr"aumarbeiten'' durchzuf"uhren,
wenn auf einen anderen Zielprozessor umgeschaltet wird. So
kann man an dieser Stelle z.B. Speicher freigeben, der im
Umschalter belegt wurde und nur ben"otigt wird, w"ahrend dieses
Codegeneratormodul aktiv ist. Im einfachsten Fall zeigt diese
Prozedurvariable auf eine leere Prozedur. Ein Beispiel f"ur die
Anwendung dieser Prozedur finden Sie im Modul \tty{CODE370}, das
seine Codetabellen dynamisch erzeugt und wieder freigibt.}
\item{\tty{IsDef} : Bestimmte Prozessoren kennen neben \tty{EQU} noch weitere
Pseudobefehle, bei denen ein in der ersten Spalte stehender
Symbolname kein Label darstellt, z.B. \tty{BIT} beim 8051. Diese
Funktion mu"s TRUE zur"uckliefern, falls ein solcher, zus"atzlicher
Befehl vorliegt. Im einfachsten Fall braucht nur FALSE
zur"uck geliefert zu werden.}
\end{itemize}
Optional kann ein Codegenerator auch noch folgende weitere Funktionszeiger
besetzen:
\begin{itemize}
\item{\tty{ChkPC} : Obwohl \asname{} die Programmz"ahler intern durchg"angig mit
32 oder 64 Bit verwaltet, benutzen die meisten Prozessoren nur einen
kleineren Adre"sraum. Diese Funktion liefert \asname{} Informationen, ob
der momentane Programmz"ahler den erlaubten Bereich "uberschritten
hat. Bei Prozessoren mit mehreren Adre"sr"aumen kann diese Routine
nat"urlich deutlich komplizierter ausfallen. Ein Beispiel daf"ur
findet sich z.B. im Modul \tty{code16c8x.c}. Falls alles in Ordnung ist,
mu"s die Funktion TRUE zur"uckliefern, ansonsten FALSE.
Diese Funktion mu"s ein Codegenerator nur implementieren, wenn er
das Feld {\tt SegLimits} nicht belegt. Das kann z.B. notwendig
werden, wenn der g"ultige Adre"sbereich eines Segments nicht
zusammenh"angend ist.}
\item{\tty{InternSymbol} : Manche Prozessoren, z.B. solche mit einer
Registerbank im internen RAM, defineren diese 'Register' als Symbole
vor, und es w"urde wenig Sinn machen, diese in einer separaten
Include-Datei mit 256 oder m"oglicherweise noch mehr {\tt EQU}s
zu definieren. Mit dieser Funktion erh"alt man Zugang zum Formel-
Parser von \asname{}: Sie erh"alt den Ausdruck als ASCII-String, und wenn
sie eines der 'eingebauten Symbole' erkennt, besetzt sie die
"ubergebene Struktur des Typs {\em TempResult} entsprechend. Falls
die "Uberpr"ufung nicht erfolgreich war, mu"s deren Element {\tt
Typ} auf {\tt TempNone} gesetzt werden. Die Routine sollte im
Falle eines Mi"serfolges {\em keine} Fehlermeldungen ausgeben, weil
dies immer noch anderweitig g"ultige Symbole sein k"onnen. Seien
Sie extrem vorsichtig mit dieser Routine, da sie einen Eingriff in
den Parser darstellt!}
\item{\tty{DissectBit} : Falls die Zielplattform Bit-Objekte unterst"utzt,
d.h. Objekte, die sowohl eine Register/Speicheradresse als auch eine
Bitposition in einer einzelnen Integer-Zahl gepackt abspeichern, ist
dies der Callback, "uber den solche gepackten Objekte f"urs Listing
wieder in eine Quellcode-artige Form r"uck"ubersetzt werden.}
\item{\tty{DissectReg} : Falls die Zielplattform Registersymbole unterst"utzt,
ist dies der Callback, "uber den Registernummer und -l"ange f"urs Listing
wieder in eine Quellcode-artige Form r"uck"ubersetzt werden.
Falls Registersymbole unterst"utzt werden, ist "ublicherweise auch
der \tty{InternSymbol}-Callback auszuf"ullen.}
\item{\tty{QualifyQuote} : "Uber diesen optionalen Callback kann f"ur
eine bestimmte Zielplattform von Fall zu Fall festgelegt werden, da"s
ein einzelnes Hochkomma {\em keine} Zeichenkette einleitet. Ein
Beispiel daf"ur ist die als \tty{AF'} geschriebene alternative
Registerbank beim Z80, oder die Hexadezimal-Syntax \tty{H'...} bei
manchen Hitachi-Prozessoren.}
\end{itemize}
Wer will, kann sich "ubrigens auch mit einem Copyright-Eintrag verewigen,
indem er in der Initialisierung des Moduls (bei den \tty{AddCPU}-Befehlen)
einen Aufruf der Prozedur \tty{AddCopyright} einf"ugt, in der folgenden
Art:
\begin{verbatim}
AddCopyright("Intel 80986-Codegenerator (C) 2010 Hubert Simpel");
\end{verbatim}
Der "ubergebene String wird dann nach dem Programmstart zus"atzlich zu
der Standardmeldung ausgegeben.
Bei Bedarf kann sich das Modul im Initialisierungsteil noch in die
Kette aller Funktionen eintragen, die vor Beginn eines Durchlaufes
durch den Quelltext ausgef"uhrt werden. Dies ist z.B. immer dann der
Fall, wenn die Code-Erzeugung im Modul abh"angig vom Stand bestimmter,
durch Pseudobefehle beeinflu"sbarer Flags ist. Ein h"aufig auftretender
Fall ist z.B., da"s ein Prozessor im User- oder Supervisor-Modus
arbeiten kann, wobei im User-Modus bestimmte Befehle gesperrt
sind. Im Assembler-Quelltext k"onnte dieses Flag, das angibt, in welchem
Modus der folgende Code ausgef"uhrt wird, durch einen Pseudobefehl
umgeschaltet werden. Es ist aber dann immer noch eine Initialisierung
erforderlich, die sicherstellt, da"s in allen Durchl"aufen ein identischer
Ausgangszustand vorliegt. Der "uber die Funktion \tty{AddInitPassProc}
angebotene Haken bietet die M"oglichkeit, derartige Initialisierungen
vorzunehmen. Die "ubergebene Callback-Funktion wird vor Beginn
eines Durchgangs aufgerufen.
Analog zu \tty{AddInitPassProc} funktioniert die "uber \tty{AddCleanUpProc}
aufgebaute Funktionsliste, die es den Codegeneratoren erlaubt, nach dem
Abschlu"s der Assemblierung noch Aufr"aumarbeiten (z.B. das Freigeben von
Literaltabellen o."a.) durchzuf"uhren. Dies ist sinnvoll, wenn mehrere
Dateien mit einem Aufruf assembliert werden, sonst h"atte man noch
,,M"ull'' aus einem vorigen Lauf in den Tabellen. Momentan nutzt kein
Modul diese M"oglichkeit.
Nach diesen Pr"aliminarien ist nun endlich eigene Kreativit"at gefragt:
Wie Sie es schaffen, aus dem Mnemonic und den Argumenten die Code-Bytes zu
erzeugen, ist weitgehend Ihnen "uberlassen. Zur Verf"ugung stehen daf"ur
nat"urlich "uber den Formelparser die Symboltabellen sowie die Routinen
aus
\tty{asmsub.c} und \tty{asmpars.c}. Ich kann hier nur einige generelle
Hinweise geben:
\begin{itemize}
\item{Versuchen Sie, die Prozessorbefehle in Gruppen aufzusplitten, die
gleiche Operanden erwarten und sich nur in einigen Kennbits
unterscheiden. Alle argumentlosen Befehle kann man z.B. so in einer
Tabelle abhandeln.}
\item{Die meisten Prozessoren haben ein festes Repertoire von
Adressierungsarten. Verlagern Sie das Parsing eines Adre"sausdrucks
in eine getrennte Unterroutine.}
\item{Die Routine \tty{WrError} definiert eine Vielzahl von m"oglichen
Fehlermeldungen und ist bei Bedarf leicht erweiterbar. Nutzen Sie
das! Bei allen Fehler nur lapidar einen ,,Syntaxfehler'' zu melden,
n"utzt niemandem!}
\end{itemize}
Mit Sicherheit wird auch das Studium der vorhandenen Module weiterhelfen.
Eine winzige "Anderung ist auch noch an den Quellen der Dienstprogramme
n"otig, und zwar in der Routine {\tt Granularity()} in {\tt toolutils.c}:
Falls eines der Adre"sr"aume dieses Prozessors eine andere Granularit"at
als 1 hat, mu"s dort die Abfrage passend erg"anzt werden, sonst verz"ahlen
sich PLIST, P2BIN und P2HEX...
%%---------------------------------------------------------------------------
\section{Lokalisierung auf eine neue Sprache}
Sie haben Interesse an diesem Thema? Wunderbar! Das ist eine Sache, die
von Programmierern gerne au"sen vor gelassen wird, insbesondere, wenn sie
aus dem Land der unbegrenzten M"oglichkeiten kommen...
Die Lokalisierung auf eine neue Sprache gliedert sich in zwei Teile: Die
Anpassung der Programmmeldungen sowie die "Ubersetzung der Anleitung.
Letzteres ist sicherlich eine Aufgabe herkulischen Ausma"ses, aber die
Anpassung der Programmeldungen sollte in ein bis zwei Nachmittagen "uber
die B"uhne zu bekommen sein, wenn man sowohl die neue als auch eine der
bisher vorhandenen Sprachen gut kennt. Leider ist die "Ubersetzung auch
nichts, was man St"uck f"ur St"uck machen kann, denn der
Ressourcencompiler kann im Moment nicht mit einer variablen Zahl von
Sprachen in den verschiedenen Meldungen umgehen, es hei"st also 'alles
oder nichts'.
Als erstes erg"anzt man in {\tt header.res} die neue Sprache. Die f"ur
die Sprache passende zweibuchstabige Abk"urzung holt man sich vom
n"achsten Unix-System (wenn man nicht ohnehin darauf arbeitet...), die
internationale Vorwahl aus dem n"achsten DOS-Handbuch.
Im zweiten Schritt geht man jetzt durch alle anderen {\tt .res}-Dateien
und erg"anzt die {\tt Message}-Statements. Nocheinmal sei darauf
hingewiesen, Sonderzeichen in der HTML-artigen Schreibweise und nicht
direkt einzusetzen!
Wenn dies geschafft ist, kann man mit einem {\em make} alle betroffenen
Teile neu bauen und erh"alt danach einen Assembler, der eine Sprache mehr
schickt. Bitte nicht vergessen, die Ergebnisse an mich weiterzuleiten,
damit mit der n"achsten Release alle etwas davon haben :-)
%%===========================================================================
\cleardoublepage
\begin{thebibliography}{99}
\input{../doc_COM/biblio.tex}
\end{thebibliography}
\cleardoublepage
\begin{quote}{\it
''Ich schlage vor, dem Parlament ein Gesetz vorzulegen, \\
das einem Autor, der ein Buch ohne Index publiziert, \\
das Copyright entzieht und ihn au"serdem f"ur sein Vergehen \\
mit einer Geldstrafe belegt.''\\
\hspace{2cm} --Lord John Campbell}\end{quote}
\printindex
\end{document}