% Content-encoding: UTF-8 \documentclass[ngerman]{article} \usepackage[utf8]{inputenc} \usepackage{multicol,babel} \usepackage{xspace} \setcounter{secnumdepth}{0} \setcounter{tocdepth}{0} %\newcommand{\code}[1]{\texttt{#1}} %\newcommand{\ret}{\textsf{$<$ret$>$}\xspace} \newcommand{\ret}{$\hookleftarrow$\xspace} \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} \renewcommand{\figurename}{Abbildung} \begin{document} \title{Delister \\ Aus dem Listing des Assemblers die assemblierbare Quelle zurückgewinnen.} \shorttitle{Delister} \author{Michael Kalus} \begin{document} \maketitle Bei der Arbeit mit dem amforth an meiner privaten Heizungs- und Solaranlagensteuerung entstand die Situation, dass durch Änderungen im Forthkern (core words) die Versionsverwaltung sehr unübersichtlich geworden war. Weil amforth aus hunderten von kleinen Einzeldateien besteht, die in die Anwendung geladen werden (include files), ist es praktisch unmöglich, mit einem Werkzeug wie DIFFMERGE oder Ähnlichem die Unterschiede der einen zu der anderen Version zu finden. Solche Vergleiche kann man bequem nur zwischen zwei Dateien stattfinden lassen, aber nicht zwischen hunderten eingeschlossener Dateien. Also muss die komplette Quelle der Anwendung in nur eine Datei versammelt werden. Die kann dann mit der nächsten Version davon verglichen werden. \begin{multicols}{2} \section{Das AVRA-Listing heizung.lst} Der Assembler AVRA ist schon so nett und versammelt alles Assemblierte in einer einzigen Datei. Dateien, die nicht includiert worden sind, werden auch nicht gelistet, von IF .. ELSE .. ENDIF werden auch nur die Teile eingeschlossen, die für die Version benutzt werden, usw. Also genau das, was man braucht, ist im Listing schon drin --- siehe Beispiel--1. Aber das Listing dient vor allem dazu, dass ein prüfender Leser erkennen kann, an welchen Adressen der Assembler welchen Code erzeugt hat. Das Listing kann daher in dieser Form nicht erneut durch den Assembler geschickt werden. Es muss befreit werden von den Adress- und Codeangaben. Und auch die .include--Directiven dürfen nicht noch mal ausgeführt werden, es ist ja schon alles in der Datei versammelt, was dazu gehört. Auch die Macros dürfen kein zweites Mal expandiert werden. Dann ist da noch eine kleine Hässlichkeit des Listings zu beachten. Die Instruktionen im Code--Segment cseg werden etwas anders gelistet als das, was an Daten ins EEPROM--Segment geschrieben worden ist. Im meinem Beispiel entsteht aus dem amforth schließlich ein Listing von 17102 Zeilen, heizung.lst genannt. Und da möchte man nicht mehr von Hand ran gehen und es in eine 1--Datei--Quelle zurückverwandeln, obwohl für das menschliche Auge leicht zu erkennen ist, was zu dem Zweck wegmüsste. \section{parsen in gforth} So ist es also an der Zeit, diesen Text maschinell zu parsen. Im Prinzip ganz einfach. Man öffne die Datei heizung.lst, lese eine Zeile, prüfe deren Aufbau und entscheide, was damit geschehen soll, und schreibe das Ergebnis hin. Und so ist es auch ein one--pass delister geworden. Die Regeln werden vom checktype durchgeführt, das als Eingang die Adresse und Länge der zu prüfenden Zeichenkette erhält. Je nachdem wird die Zeile einfach verworfen, gekürzt, oder in einen Kommentar verwandelt. Zur Hilfe kam mir, dass im gforth ein passender parser schon da ist. Das Forthwort search sucht nach einem Ausdruck in einer Zeichenkette. Damit waren schon viele typische Zeilen zu erkennen und damit behandelbar. Lediglich das parse--bl musste neu erfunden werden, um eine Kommentarzeile am ; zu erkennen, das auf Leerzeichen des Zeilenanfangs folgt. Hilfreich war es, dass gforth konsequent alle Zeichenketten über ( adr u --\/-- ) auf dem Stack handhabt. Da konnte ich mich ganz gut reinfinden und somit diese parse areas handhaben. \section{file handling in gforth} Zentral ist es dabei, den folgenden Teil verstanden zu haben, den man aber glücklicherweise nicht erfinden, sondern nur abzuschreiben braucht. \begin{verbatim} 0 Value fid-in : open-input ( addr u -- ) r/o open-file throw to fid-in ; mk : close-input ( -- ) fid-in close-file throw ; : getline ( -- adr u f ) linebuffer maxline fid-in read-line throw ( -- u f ) linebuffer -rot ; \end{verbatim} Hat man im Handbuch des gforth erst einmal diese Stelle \footnotetext{Gforth Manual; 5.17.2 General files; Seite 112.}gefunden, kommt man zurecht, finde ich. Auch dabei ist das Prinzip eingehalten worden, alle Daten per Adresse und Längenangabe zu handhaben. Womit parsen in Text--Dateien schließlich recht einfach wird. \section{Zum Gebrauch des Delister} An einer Stelle ist noch etwas Handarbeit nötig. AVRA schreibt Sätze in das Listing, die nicht in das Schema der ganzen Auswertung passen, eine Überschrift und vier Schlusssätze. Da diese Sätze ganz am Anfang und am Ende des Listings stehen, kommentiere ich die einfach von Hand aus, und fertig. Dieses heizung.lst genannte Listing wird dann vom delister in die Datei heizung.re.asm umgeschrieben. Nun kann dieses frisch gewonnene heizung.re.asm assembliert werden. Und AVRA gab das ersehnte ``Assembly complete with no errors''. Den schlüssigen Beweis liefert dann der Vergleich der Images mit DIFFMERGE, ein Programm zum Vergleich von Dateien. Die von AVRA erzeugten Images, das originale heizung.hex und unser heizungs.re.hex, waren identisch. \\ Möge es nützlich sein.\\ \end{multicols} \section{Links} \url{http://dl.dropbox.com/u/1170761/delister.fs}\\ \url{http://www.jwdt.com/~paysan/gforth.html}\\ \url{http://avra.sourceforge.net/}\\ \url{http://www.atmel.com/}\\ \section{Beispiel--1: Auszug aus dem vom Assembler erzeugten Listing.} \begin{quote} \begin{small} \begin{multicols}{2} \listinginput[1]{1}{2011-02/delister-1.fs} \end{multicols} \end{small} \end{quote} Dem gegenüber das originale create.asm \begin{quote} \begin{small} \begin{multicols}{2} \listinginput[1]{1}{2011-02/create.asm} \end{multicols} \end{small} \end{quote} \section{delist.fs forth source code} \begin{quote} \begin{small} \listinginput[1]{1}{2011-02/delist.fs} \end{small} \end{quote} \end{document}