% Content-encoding: UTF-8 \documentclass[ngerman]{article} \usepackage[utf8]{inputenc} \usepackage{multicol,babel} \setcounter{secnumdepth}{0} \setcounter{tocdepth}{0} \renewcommand{\reftextbefore}{auf der vorherigen Seite} \renewcommand{\reftextfacebefore}{auf der gegenüberliegenden Seite} \renewcommand{\reftextafter}{auf der nächsten Seite} \renewcommand{\reftextfaceafter}{auf der gegenüberliegenden Seite} \begin{document} % \renewcommand{\figurename}{Tabelle} \title{{\sf g4} — Ein Forth–nach–Assembler–Converter} \ifx\shorttitle\undefined\else \shorttitle{Forth–nach–Assembler–Converter} \fi \author{Michael Kalus} \maketitle Bei der Arbeit mit dem \texttt{amforth} von Matthias Trute entstand der Wunsch, den in Forth verfassten Code auch als Assemblerquelle zu haben. So brauchen ausgetestete Forth--Programmteile nicht mehr über die serielle Schnittstelle in das Board nachgeladen zu werden, sondern können mit dem Kern des \texttt{amforth}s zusammen assembliert und dann in den Prozessor hochgeladen werden. Das Tool heißt\footnote{{\sf g4} ist benannt in Anlehnung an den \texttt{m4}--Macro--Prozessor, der aber für diesen Zweck unbrauchbar ist. So war es einfacher, einen eigenen Konverter in \texttt{gforth} zu verfassen, eben den {\sf g4}.} {\sf g4} und ist freie Software und \emph{work in progress} --- Fehlerhinweise bitte an mich. Das {\sf g4} kann vom Server der FG geladen werden, siehe Links weiter unten. \begin{multicols}{2} \section{Wie funktioniert das {\sf g4}?} Das {\sf g4} ist ein \texttt{amforth}--Code--Interpreter und in \texttt{gforth} verfasst. Es wird in \texttt{gforth} geladen und nimmt dann entweder Kommandozeilen oder Textdateien an. Ein Beispiel zeigt, wie es geht. Die Zeile \begin{verbatim} : zoo ." hallo" s" tach" ; \end{verbatim} wird dann expandiert zu: \begin{verbatim} VE_ZOO: .dw $FF03 .db "zoo",0 .dw VE_HEAD .set VE_HEAD = VE_ZOO XT_ZOO: .dw DO_COLON PFA_ZOO: .dw XT_SLITERAL .dw $5 .db "hallo" .dw XT_ITYPE .dw XT_SLITERAL .dw $4 .db "tach" .dw XT_EXIT \end{verbatim} In diesem Beispiel ist zu sehen, dass Header und Struktur der \texttt{amforth}--Quellen von dem {\sf g4}--Interpreter nachgebildet werden. Und sofern alles geklappt hat, kann die resultierende Datei in die eigene \texttt{amforth}--Quelle als Applikation eingebunden werden. \section{Features des {\sf g4} Interpreters} Forth--Definitionen werden in \texttt{amforth}--Quellen expandiert (colon definitions). Das geschieht mit Hilfe eines \texttt{polyForth}--ähnlichen Compilers. Einfache \texttt{amforth}--Worte werden z.~B.\ so konvertiert: \begin{verbatim} _: swap _cr _." .dw XT_SWAP " _; \end{verbatim} Defining words wie \texttt{:} (colon) \texttt{VARIABLE CONSTANT USER} legen zunächst im Wörterbuch des \texttt{gforth} neue Definitionen an, die dann zur Laufzeit ihren Namen als Macro für den Assembler ergeben. Die defered words \texttt{RDEFER} und \texttt{EDEFER} werden ebenso unterstützt wie \texttt{CREATE} \ldots\ \texttt{DOES>}--Konstrukte. Dabei können auch \texttt{,} (comma) \texttt{ALLOT} und \texttt{CELLS} verwendet werden. In Definitionen funktionieren auch Forthworte wie \verb|." s"| und \texttt{POSTPONE} inzwischen. Die Kontrollstrukturen wie \texttt{DO LOOP} oder \texttt{IF ELSE THEN} und \texttt{BEGIN UNTIL} werden in Label aufgelöst, die der \texttt{amforth}--Quellen--Syntax entsprechen. Da \texttt{amforth} ab der Version 3.1 Strings und Namen im Wörterbuch des Flash mit ganzen 16--Bit--Längeninformation ablegt, statt nur mit 8 Bit wie bis dahin, kann nun zwischen beiden Versionen mit einem Schalter ausgewählt werden. Um auch Steueranweisungen aus der Forthquelle heraus an den Assembler schicken zu können, wurde ein Sonderbefehl eingefügt. Mit \verb|>>>| lassen sich nun ganze Textzeilen schicken; z.~B.: \begin{verbatim} >>> .set pc = pc + $10 \end{verbatim} Um Adress--Token in den \texttt{amforth}--Quellen angeben zu können, wurde der Befehl \texttt{\_lit}: geschaffen. Ist zum Beispiel irgendwo im \texttt{amforth} eine Adresse definiert, kann diese damit auch im Forth definiert und benutzt werden. Beispiel: Registeradressen wie Timer. \begin{verbatim} _lit: TIMSK1 _lit: TIMSK2 : OSCCAL_CALIBRATE ( -- ) \ Make sure all clock division \ is turned off (8MHz RC clock) 1 7 lshift 61 c! 0 61 c! \ Disable timer interrupts 0 TIMSK1 c! 0 TIMSK2 c! \end{verbatim} (usw) \texttt{;}\medskip wird damit passend übersetzt. \texttt{TIMSK1} expandiert dabei zu \ldots \begin{verbatim} .dw XT_DOLITERAL .dw TIMSK1 \end{verbatim} \ldots\medskip Auch Forth--Code folgender Art wird verarbeitet: \begin{verbatim} variable x1 10 allot create y2 10 cells allot \end{verbatim} Dabei werden die Variablen angelegt und die Assembleranweisung \begin{alltt} ; allot ram .set heap = heap + \(nn\) \end{alltt} wird generiert, wobei $nn$ die passende Anzahl Bytes angibt. Um innerhalb einer Forthdefinition auch kalkulieren zu können, wird \texttt{[ ]} wie gewöhnlich benutzt. \medskip \begin{verbatim} hex : test ... [ 11 22 + ] literal ... ; \end{verbatim} erzeugt dann\medskip \ldots \begin{verbatim} .dw XT_DOLITERAL .dw $33 \end{verbatim} \ldots\medskip Einschränkung dabei ist, dass \texttt{[ ]} in {\sf g4} auf eine Zeile Forth--Code begrenzt ist. Eine Besonderheit sind immediate words. Dazu muss die Anweisung \texttt{g4-immediate-on} vor der Forth--Definition angegeben werden, statt wie sonst üblich dahinter. Am Ende prüft {\sf g4}, ob irgendetwas auf dem Stack liegen geblieben ist, denn falls das der Fall ist, ist was schiefgegangen bei der Erzeugung der Assemblerquelle. OK wäre so etwas: \begin{verbatim} ; Items on stack: <0> mk 2008.11.16 21:40:35 \end{verbatim} \section{Wie wird {\sf g4} aufgerufen?} So gehts mit Apple OSX: \begin{verbatim} PowerBook:~/michael$ gforth g4.fs \end{verbatim} Oder das {\sf g4} gleich in die zu übersetzende Datei einbinden: \begin{alltt} PowerBook:~/michael$ gforth {\sf [datei.fs]} >{\sf[datei.asm]} \textrm{,} \end{alltt} wobei {\sf [datei.fs]} die Forth--Quelle ist, die mit einem darin untergebrachten \texttt{include} {\sf g4} befähigt wird, das Ergebnis sogleich in die {\sf [datei.asm]} auszugeben --- das ist sehr komfortabel. Mit \texttt{gforth} auf Windows XP läuft das {\sf g4} ebenfalls. Dort läuft \texttt{gforth} in der Unix Shell \texttt{sh.exe}. Bitte darauf achten das der Punkt und Schrägstrich auf der Kommandozeile mit angegeben werden und die Dateien in den gleichen Verzeichnissen liegen. \begin{alltt} sh-3.00$ ./gforth {\sf [datei.fs]} >{\sf[datei.asm]} \end{alltt} \section{Nutzanwendungen bisher} Bisher habe ich nur eigene \texttt{amforth}--Quellen in Assembler--Quellen konvertiert, und so in mein \texttt{amforth} 2.9 eingebunden. Es waren dies der Forth--Assembler von Lubos Pekny (\texttt{assembler.asm}) , eine Reihe Dump--Utilities (\texttt{dump.asm}, \texttt{idump.asm}, \texttt{edump.asm}), alle Zahlenausgabeworte in der doppeltgenauen Form sowie \texttt{key} und \texttt{emit} in der pollenden Form. Bisher bin ich mit den Ergebnissen zufrieden. Ulrich Hoffmann und Matthias Trute gebührt mein Dank für die ermunternden Worte und Hinweise. Ich hoffe, es ist dem einen oder anderen ebenfalls ein nützliches Tool auf dem Wege zu seiner Applikation. \section{Quellen} \url{http://www.forth-ev.de/trac/browser/g4}\\ \url{http://amforth.sourceforge.net/} \end{multicols} \vfill \begin{center} \includegraphics[width=0.6\textwidth]{2009-01/transformator} {\sf g4} transformiert High-Level--Forth in amForth--Assembler--Text \end{center} %\vfill \end{document}