% Content-encoding: UTF-8 \documentclass[ngerman]{article} \usepackage[utf8]{inputenc} \usepackage{multicol} % \usepackage{babel} \usepackage{xspace} \setcounter{secnumdepth}{0} \setcounter{tocdepth}{0} \usepackage{german} %\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{\reftextfaraway}[1]{auf Seite \pageref{#1}} \renewcommand{\figurename}{Listing} \title{Bootmanager und FAT--Reparatur: Achter Fort(h)schritt (Rawwrite/Diskcopy)} \ifx\shorttitle\undefined\else \shorttitle{Bootmanager Teil 8} \fi \author{Fred Behringer} \begin{document} \maketitle Es wird ein Programm (mit Namen \texttt{getdiskimage}) entwickelt, mit dessen Hilfe man ein Abbild einer (weitestgehend beliebigen) 3.5-HD--Diskette (nicht unbedingt DOS) ins RAM schreiben kann. Die Darstellung benutzt das übliche \texttt{dump} --- hier \emph{leicht} erweitert zum 32--bittigen \texttt{dump-32}, mit dem auf das gesamte RAM linear zugegriffen werden kann. Das Programm arbeitet auch da, wo \texttt{Rawwrite} oder/und \texttt{Diskcopy} versagen. Ein Pendant (ich werde es \texttt{putdiskimage} nennen) zum Zurückschreiben (wieder auf Diskette) ist für später vorgesehen. \begin{multicols}{2} \section{Ziel (für jetzt und für eventuell weitere Artikel)} In Teil 4 dieser Artikelserie habe ich über eine Verlagerung des BIOSes (mit Veränderungsmöglichkeiten) ins RAM berichtet [FB09]. Dazu hatte ich vor dem eigentlichen Booten eine Hilfsdiskette mit präpariertem Bootsektor verwendet. Ich wollte mit Diskcopy schnell eine Kopie dieser Hilfsdiskette herstellen --- und erlebte eine Überraschung: Weder Diskcopy noch \texttt{Rawwrite} kamen mit dieser Aufgabe zurecht --- wenn die Disketten nicht bestimmte Merkmale von DOS-- oder DOS--ähnlichen Disketten aufwiesen. Da es mir seinerzeit bei der \emph{Hilfsdiskette} nur um den Bootsektor ging, genügte es zunächst, nur den Bootsektor zu übertragen --- und das war mit den davor entwickelten Mitteln meiner Serie bereits zu erreichen. Ich möchte aber nicht aufgeben und habe nun vor, per Forth eine ganze Diskette sektorweise zu kopieren, also das, was bei DOS--Disketten üblicherweise über Diskcopy erreicht werden kann. Die Diskette soll sich aber nicht vollständig dem DOS--System unterwerfen, sondern zudem auch weitestgehende Strukturfreiheit zulassen. Gleichzeitig möchte ich die Möglichkeit bieten, in den Kopierprozess einzugreifen: Der Disketteninhalt wird (sektorweise) erst ins RAM kopiert, dort nach Wunsch verändert und dann erst auf eine neue Diskette (darf auch dieselbe sein) zurückgeschrieben. Die Veränderung des Disketten--Abbildes könnte man, nebenbei gesagt, zumindest bei DOS--Disketten \section{auch per PCTOOLS} erreichen: Quelldiskette ins Laufwerk legen, \emph{Quelldiskette wird eingelesen} arbeiten lassen und dann nach \emph{Zieldiskette einlegen} das Laufwerk einfach unbelegt lassen und aber trotzdem zur vorgetäuschten Bestätigung die Eingabe--Taste drücken. (Vorsichtshalber sei gesagt, dass ich dabei davon ausgehe, dass nur ein einziges Disketten--Laufwerk vorhaben ist.) PCTOOLS speichert das Disketten--Abbild in einer ganze normalen temporären Datei, die dann aber nach der Betätigung der Eingabe--Taste gelöscht wird. Beim Löschen einer DOS--Datei wird bekanntlich nichts anderes gemacht, als dass in der Datei--Zuordnungstabelle (in der FAT) das erste Zeichen im Dateinamen durch ein hexadezimales e5 ersetzt wird. Die betreffende Datei kann dann also (z.$\,$B.\ auch per PCTOOLS) durch Ersetzen des \texttt{e5}--Bytes sofort wieder zum Leben erweckt werden. Die bisher entwickelten Hilfsmittel der vorliegenden Artikelserie können bei dieser Reanimierungs--Aktion ebenfalls gut eingesetzt werden. \section{Das Versagen von Rawwrite und andere Motive} Ein wichtiges Motiv für das Nachempfinden eines Programms in Forth, eines Programms, das man bei mehr oder weniger langem Suchen vielleicht auch schon im Internet findet, ist die immer wieder zu machende Erfahrung, dass man ein Programm erst dann richtig versteht, wenn man es selbst entworfen hat. Dann fällt einem das Verändern und Anpassen an eigene Vorgaben besonders leicht --- und ganz besonders besonders leicht fällt einem das in Forth. Ich hatte aber noch ein weiteres Motiv: Bei der im vorigen Abschnitt erwähnten \emph{Hilfsdiskette} aus [FB09] wollte ich schnell mit dem Alleskönner \texttt{Rawwrite} ans Werk gehen. Aber ach! Von wegen RAW--writen! Man kann nicht davon ausgehen, dass bei beliebiger Quelldiskette alles roh (Sektor für Sektor) übertragen wird. Bei der \emph{Hilfsdiskette} aus Teil 4 meiner Artikelserie hatte ich es mit dem RAWWRITE 0.7 (für Windows) von John Newbigin [JN00] versucht und war bass erstaunt: Unmittelbar nach dem Einlegen der \emph{Hilfsdiskette} lieferte \texttt{rawwritewin.exe} die Meldung \emph{Error reading disk}. Und das bei einem so einfachen Vorgang wie dem Kopieren einer Diskette, bei der es zudem sogar auf nichts weiter ankam als auf den Bootsektor! Allerdings hatte ich gerade diesen Bootsektor total verändert und insbesondere alle Parameter--Angaben zur Struktur der Diskette (weil für mich überflüssig) ausgenullt. \section{Nicht nur für Hilfsdiskette aus Teil 4} Das im vorliegenden Artikel entwickelte Programm schafft die Aufgabe mit der \emph{Hilfsdiskette} aus Teil 4 meiner Artikelserie sehr wohl! Und nicht nur das! Allerdings muss sich die Diskette an meine Vorgaben (80 Spuren, 2 Seiten, je 18 Sektoren pro Spur, 512 Bytes pro Sektor --- siehe gleich) halten. (Ich wollte das Programm (zunächst einmal) so einfach wie möglich gestalten.) Das heißt aber auch, dass die zu lesende Diskette FAT--formatiert sein muss. (Für die \emph{Hilfsdiskette} aus Teil 4 wäre das nicht unbedingt nötig gewesen. Die könnte man aber auch, wie in Teil 4 geschehen, schon per \verb|mbr>bak| und \verb|bak>mbr| bearbeiten.) \section{Voraussetzungen} Ich möchte keinen unnötigen Ballast mit mir herumschleppen und begnüge mich mit 3.5--HD--Disketten. Sie sollen aber die vom DOS--Befehl Format (und auch von anderen gängigen Dateisystemen) erzeugte Aufteilung in Sektoren, Spuren und Seiten aufweisen. (Im Zweifelsfall gilt: Ich gehe von DOS 6.2 aus.) Das heißt, ich lege 80d Spuren (80d tracks), pro Spur 2 Seiten (2 heads) und 18d Sektoren pro Spur zugrunde. Dabei sollen 512d Bytes auf einen Sektor gehen. Abgesehen von dieser Formatiervorschrift braucht aber (und das bereitet eben den \emph{professionellen} Programmen offensichtlich \emph{Kopfzerbrechen}\/) auf der Diskette keinerlei Informationen verzeichnet zu sein, die es dem Kopierprogramm erlaubt, das jeweils vorliegende und in meinem Fall fest vorgegebene Strukturformat abzulesen. Insbesondere lasse ich zu, dass im Bootsektor alle nicht benötigten Parameter ausgenullt werden --- so wie ich es in meinem Programm aus Teil 4 getan hatte. (Nebenbei gesagt, gibt es bei Disketten keinen MBR und die CHS--Zählung der Sektoren beginnt bei 1 --- die Zählung von Seite und Spur beginnt bei 0.) \section{Dinge, die einen zur Verzweiflung treiben können} In Wikipedia und überall sonstwo liest man, dass eine 3.5--HD--Diskette eine Kapazität von 1,44 Megabyte hat. Meist steht übertrieben anglophil dann auch noch an der Stelle des Kommas ein Punkt. Meine Berechnung liefert (dezimal): 80*2*18*512 = 1.474.560 Bytes an Disketten--Kapazität. Aufklärung habe ich dann (ganz versteckt) im Internet gefunden (siehe [v511]): 1,00 Kilobyte = 1.024 Bytes 1,44 Megabyte = 1.440 Kilobytes = 1.474.560 Bytes ! \emph{Klar}\/, werden die Wissenden sagen. Aber ist das auf Anhieb wirklich so klar? Ich hatte schon gedacht, mein Programm liefert mir falsche Ergebnisse oder, was noch schlimmer gewesen wäre, \texttt{um*} funktioniert in Turbo--Forth nicht richtig. \section{Was geht nicht?} Bei der Hilfsdiskette aus Teil 4 kam es nur auf den Bootsektor an. Der allein schon enthielt das veränderte Bootprogramm, mit welchem ein Abbild des ROM--BIOSes ins RAM gelegt wird, um die Arbeit des ROM--BIOSes zu übernehmen. Das Programm des vorliegenden Artikels verlangt mehr: Die Struktur der gesamten Diskette (und nicht nur die des Bootsektors) muss stimmen. Und da nimmt es nicht wunder, dass eine \emph{Hilfsdiskette} im Sinne von Teil 4 mit dem vorliegenden Programm nicht funktioniert, wenn der abgeänderte Bootsektor auf eine 3.5--Diskette der Bauart DD geschrieben wurde. --- Das Einlegen einer (beliebigen) 3.5--DD--Diskette ist übrigens eine schöne Methode, die Meldung auf dem Bildschirm für den Fall zu überprüfen, dass zwar eine Diskette im Laufwerk liegt, dass diese Diskette aber mit einem \emph{Fehler} behaftet ist. Im Übrigen ist das Funktionieren \section{nicht vom Dateisystem abhängig.} Nur die \emph{richtige} Sektor--Spur--Seiten--Einteilung zählt. Ausprobiert habe ich das Funktionieren mit Not-- oder Boot--Disketten von: OS/2--Warp, FreeDOS, GRUB--0.94, Windows--95, Windows--98, Windows--ME, Tom Oehsers Linux auf Diskette [TO02] und anderen mehr. \section{Zur Überprüfung einer \emph{Hilfsdiskette} des Formats DD} kann man wie folgt vorgehen: Das Forth--Wort \texttt{diskbootcopy} aus Teil 6 meiner Artikelserie [FB10] aufrufen und die Anweisungen auf dem Bildschirm befolgen. \section{Hauptlast im vorliegenden Artikel} trägt das Zubringer--Wort \texttt{(getdiskimage)}, die Klammern gehören zum Forth--Wort, das vollständig in Forth--Assembler geschrieben ist. Das High--Level--Wort getdiskimage ruft \texttt{(getdiskimage)} auf und nutzt die im Forth--System schon vorhandene Organisationsgewalt aus. Ich darf meine weiteren Erklärungen in Form von Beispielen (mit konkreten Eingabewerten) aufziehen. \section{200000. \texttt{getdiskimage}} legt ein Disketten--Abbild nach Adresse 200000. --- der Punkt gehört zum Forth--Wort. Das zugrunde gelegte Turbo--Forth ist ein 16--Bit--System. Eine 3.5--HD--Diskette fasst 1.44 Megabyte. Mit (einfachgenauen) 16--Bit--Zahlen für die Adressen komme ich also (auch schon wegen des begrenzten PC--RAM--Bereichs) nicht durch. Punktzahlen, wie die eben genannte, sind doppeltgenau (32 Bit breit). Über mögliche RAM--Organisationen (wie beim Aufbau von Dateisystemen) habe ich hier nicht weiter nachgedacht. Ich bewege mich mit Turbo--Forth in einem DOS--System und agiere nach dem Motto: Mein RAM gehört mir und ich kann damit treiben, was ich will. (Übrigens befolgt ja DOS ein solches Motto mit \texttt{.com}-Dateien, die bei Aufruf (zunächst einmal) den gesamten RAM--Speicher zur Verfügung gestellt bekommen) auch. Wo nötig, habe ich bei meinen Experimenten während der Entwicklung neben dem \emph{runden} Wert \texttt{200000.} auch \texttt{400000.}, \texttt{600000.}, \texttt{800000.}, \texttt{a00000.} usw.\ verwendet. (Der Eingabe--Parameter ist eine Punktzahl, doppeltgenau, also 32 Bit breit. Den Punkt nicht vergessen!) \section{Nachträgliche Veränderungen am Disk--Image} lassen sich mit den über \texttt{dump-32} gewonnenen Adress--Informationen per \texttt{!-32}, \texttt{@-32} etc.\ gezielt vornehmen. Über ein Zurückschreiben auf Diskette werde ich später berichten. \texttt{5 200003. c!-32} legt das Byte \texttt{5} an die Adresse \texttt{200003.}, wobei alle anderen Bytes in der Umgebung dieser Adresse unberührt bleiben. \texttt{4711 300100. cc!-32} legt das Byte \texttt{11} nach \texttt{300100.} und das Byte \texttt{47} nach \texttt{300101} (little--endian). \texttt{12345678. 400200. !-32} legt \texttt{78} nach \texttt{400200.}, \texttt{56} nach \texttt{400201.}, \texttt{34} nach \texttt{400202.} und \texttt{12} nach \texttt{400203} (wiederum streng little--endian). Etwas anderes hätte in einer gemischten 16/32--Bit--Umgebung kaum einen Sinn. Man achte aber darauf, dass bei der üblichen Eingabe von 32--Bit--Zahlen in Turbo--Forth in der 16--Bit--Version 32--Bit--Zahlen als Punktzahlen geschrieben werden, welche auf dem Stack und in den 2Variablen Lo-- und Hi--Anteil, im Gegensatz zur Little--Endian--Platzierung, vertauschen. Achtung: Will man die eben gemachten Angaben per \texttt{dump-32} überprüfen, dann achte man darauf, vorher (oder zumindest zwischenzeitlich) \texttt{fs} = 0 zu setzen (zu erreichen über \texttt{0 fs!}), da \texttt{dump-32} mit einem nullgesetzten Segment \texttt{fs} arbeitet. \section{Alle Angaben im Listing sind hexadezimal} zu interpretieren. Selbstverständlich gilt das besonders für \texttt{dump-32}. Ich habe Möglichkeiten vorgesehen (siehe Listing \vref{listing8}), im ASCII--Teil des Ausdrucks von \texttt{dump-32} solche Zeichen, die nicht dargestellt werden können, in verschiedener Weise auf den Bildschirm zu bringen (als Punkt oder anderswie). \section{Das Programm ist autark} Außer dem Listing des vorliegenden Artikels und einem 16--Bit--Turbo--Forth als System wird nichts weiter benötigt. Bisherige Artikel dieser Serie helfen dem Leser, können aber zunächst auch ebenso gut unberücksichtigt bleiben. Turbo--Forth findet man beispielsweise auf dem amerikanischen FTP--Server \url{taygeta.com} (mit Mirror in Bremen; siehe auch weiter unten). \section{Einen 32--Bit--Assembler} braucht man zum Überprüfen des im Vorliegenden Gesagten nicht. Der 16--Bit--Assembler aus dem 16--Bit--Turbo--Forth reicht. Ein paar zusätzliche Forth--Worte zur Erweiterung auf 32 Bit machen es möglich. Mit der Makro--Definition \texttt{: ebx opsize: bx ;} und dem 32--Bit--Präfix \texttt{: opsize: 66 c, ;} erreiche ich in Code--Definitionen beispielsweise einen leicht einprägsamen Zugriff auf das 32--Bit--Register gleichen Namens. Ähnliches gilt für 32--Bit--Adressen, mit dem Präfix \texttt{: adrsize: 67 c, ;} . Bei (linearem) Zugriff auf 32--Bit--Adressen beziehe ich mich auf \texttt{: fs: 64 c, ;} als Segment. (Sollte jemals eine ZF--Version meines Programms zustande kommen, so achte man auf die 64--Falle in ZF, auf welche uns Martin Bitter seinerzeit aufmerksam gemacht hat, und schreibe \texttt{064} statt \texttt{64}. Bei der Darstellung per \texttt{dump-32} wird von mir grundsätzlich \texttt{fs} = 0 gesetzt. Das erreicht man per \texttt{0 fs!} (im Real--Mode sind auch die Segmente \texttt{fs} und \texttt{gs} nur 16 Bit breit einstellbar). \section{Ich verwende eine 16/32-Bit--Mischung} An Stellen mit 16--Bit--Zugängen halte ich mich an die übliche PC--Segmentierung (Adressangaben als xxxx:yyyy). Das Segment xxxx kann in Turbo--Forth über das Wort \texttt{dsegment} bezogen werden. Die unselige Methode der IBM/Intel--Segmentierung musste ich beibehalten, da sich ja das Turbo--Forth--System auf das Segment xxxx bezieht und jedes Wackeln daran zu unnützem Zusatzaufwand führen würde. Das kann aber auch leicht zu Verwirrung führen: Will ich mir den Inhalt des Zwischenspeichers \texttt{trackbuf} ansehen, so kann ich beispielsweise \texttt{trackbuf 100 dump} schreiben. (\texttt{dump} ist das \texttt{dump} aus Turbo--Forth.) \texttt{trackbuf} liegt ja im Anwender--Teil des Forth--Systems, also unterhalb der 1--MB--Grenze. Will ich aber mein komfortableres \texttt{dump-32} (das auf die ganze Maschine zugreifen und über die Plus-- oder Minus--Taste ganze RAM--Bereiche ganz schnell durchkämmen kann) ausnutzen, dann muss ich wie folgt vorgehen. \section{Trackbuf über das komfortable \texttt{dump-32} ansehen} Ich muss dazu beachten, dass das Turbo--Forth--System in einem bestimmten DOS--Segment (von 64 KB) liegt und dass der Zwischenspeicher \texttt{trackbuf} (etwa 9 KB) im Turbo--Forth--System (etwa 26 KB) eingebettet ist. Es müssen also die DOS--Adressen xxxx:yyyy in lineare 32--Bit--Adressen (als reine Offset--Werte) mit vernünftigerweise \emph{Segment-Wert} 0. umgewandelt werden. Konkret: \texttt{trackbuf 100 dump} läuft bei Betrachtung per \texttt{dump-32} auf folgende Sequenz hinaus: \texttt{trackbuf s>d dsegment 10 um* d+ 100. dump-32} Es ist immer wieder interessant zu beobachten, dass auch Forth zwar \emph{kinderleicht} in der Anwendung ist, dass man aber auch da erst richtig loslegen kann, wenn man weiß, was man tut. \verb|s>d| arbeitet \emph{vorzeichenrichtig}\/. Das heißt aber, dass man erwartungsgemäß \texttt{2000 s>d d. $\rightarrow$ 2000} angezeigt bekommt (alles in Hexwerten gesehen), dass aber \texttt{9000 s>d d. $\rightarrow$ -7000} liefert. Es nützt auch nichts, wenn man meint, mit \texttt{ud.} besser zu liegen: \texttt{9000 s>d ud. $\rightarrow$ ffff9000} Abhilfe schafft ein Sichbesinnen auf die (durchaus sinnvolle) Konstruktion von \verb|s>d|, die man sich in Turbo--Forth per \verb|help s>d| (oder natürlich auch mit einem schnellen Blick in den Quelltext \texttt{kernel.txt} von 82 KB oder aber über \verb|see s>d|) beschaffen kann: \texttt{9000 0 d. $\rightarrow$ 9000} \verb|s>d| liefert eben nicht die vorzeichenUNabhängige Erweiterung einer einfach genauen zu einer doppeltgenauen Zahl! \section{Zugriffe auf beliebige DOS--Segmente per dump--32} An sich hat man keine Veranlassung, irgendetwas aus dem Turbo--Forth--System mit \texttt{dump-32} zu betrachten. dump aus Turbo--Forth tut es ja auch. \texttt{dump-32} mit seiner 100h--Byte--Fortschaltung ist aber komfortabler --- und man könnte das ausnutzen wollen. (Aufgabe: Man konstruiere ein Forth--Wort, das den Zugriff auf ein vorgegebenes DOS--Segment so automatisiert, dass man sich keine komplizierte Adress--Arithmetik zu merken braucht!) Wie schon in [FB98], so auch hier betrachte ich die Forth--Worte \section{\texttt{@-32} und \texttt{!-32} als echte 32--Bit--Erweiterungen} so, als ob sie einem 32--Bit--Forth--System entstammen. Mir erschien das schon in der Arbeit [FB98] als vernünftig. Ich halte mich aber Gegenargumenten gegenüber offen. Einen Überblick verschafft man sich wohl am ehesten, wenn man sich eine RAM--Stelle im Forth--Segment vorgibt (\texttt{pad} ist gut dazu geeignet) und \texttt{@-32} und \texttt{!-32} einerseits mit andererseits den \emph{üblichen} (Turbo--)Forth--Worten \texttt{2@} und \texttt{2!} (ich rede hier ja vorwiegend über 32--Bit--Zahlen) vergleicht. Es gilt (alles hexadezimal): \begin{small} \begin{alltt} 12345678. swap pad 2! pad 2@ swap d. \begin{math}\rightarrow\end{math} 12345678 pad 40 dump \begin{math}\rightarrow\end{math} 78 56 34 12 (im RAM strikt little-endian!) 12345678. pad 2! pad 2@ d. \begin{math}\rightarrow\end{math} 12345678 pad 40 dump \begin{math}\rightarrow\end{math} 34 12 78 56 (little-endian mit Hi-Lo-Vertauschung) 0 fs! (Bei dump-32 nicht vergessen!) 12345678. swap pad 2! pad 0 dsegment 10 um* d+ @-32 d. \begin{math}\rightarrow\end{math} 12345678 pad 0 dsegment 10 um* d+ 40. dump-32 \begin{math}\rightarrow\end{math} 78 56 34 12 12345678. pad 0 dsegment 10 um* d+ !-32 pad 2@ swap d. \begin{math}\rightarrow\end{math} 12345678 pad 0 dsegment 10 um* d+ @-32 d. \begin{math}\rightarrow\end{math} 12345678 pad 40 dump \begin{math}\rightarrow\end{math} 78 56 34 12 \end{alltt} \end{small} Damit sind, meine ich, alle Überkreuzbeziehungen erfasst. Ich betrachte das Einbringen einer Punktzahl (32 Bit) ins RAM in Form eines strikten Little--Endian--Wertes als ein natürliches Vorgehen --- zumindest bei meinen Vorhaben aus [FB98] und im Umfeld des vorliegenden Artikels. \texttt{pad} lag bei mir an Adresse 2680:93c7 und lieferte \begin{small} \begin{alltt} pad s>d ud. \begin{math}\rightarrow\end{math} ffff93c7 . \end{alltt} \end{small} Erwartet hatte ich 000093c7, also \begin{small} \begin{alltt} pad s>d ud. \begin{math}\rightarrow\end{math} 93c7 als 32-Bit-Zahl \end{alltt} \end{small} (Vergleiche das zwei Abschnitte weiter vorn Gesagte.) Solche \emph{Kleinigkeiten} der eigenen Unzulänglichkeit kosten enorm viel Zeit! \section{\texttt{dump-32} ist eine leicht aufpolierte Version} des Forth--Wortes gleichen Namens aus meinem VD--Artikel \emph{Real--Mode--32--Bit--Erweiterung für Turbo--Forth} aus dem Jahre 1998 [FB98] Auch die anderen turbo--forth--erweiternden Worte, wie \texttt{@-32} und \texttt{!-32}, stammen aus derselben Quelle. Die Plus--Taste schaltet den am Bildschirm angezeigten Bereich in Schritten zu je 100h Bytes weiter. Das macht sich sehr bezahlt: Lässt man den Finger auf der Plus--Taste, dann kann man verhältnismäßig schnell zig Kilobytes durchkämmen. Ist die gesuchte Information dabei zu schnell am Auge vorbeigerauscht, dann leistet ein Innehalten und anschließendes Drücken der Minus--Taste den entsprechenden Korrekturdienst in Rückwärts--Richtung (je 100h Adress--Bytes weniger per Druck auf die Minus--Taste). Raus geht es aus \texttt{dump-32}, wenn man die Return--Taste drückt. \section{Die Last des Protected--Modes} wollte ich mir nicht aufbürden. Ich wollte unbedingt im Real--Modus bleiben. Mit den Hilfsmitteln aus [FB98] wäre das ja ohne Weiteres möglich. Sehr zu meinem Erstaunen habe ich dann aber bemerkt, dass das Aufbohren des Systems auf einen 4--Gigabyte--Zugang gar nicht nötig ist. Adressen lassen sich über die erweiterten Register \texttt{exx} selbstverständlich schon im üblichen Real--Mode (sprich Sofort--Mode) gleich 32--Bit--weit ansprechen --- und vom eigentlichen Turbo--Forth--Programm liegt nichts oberhalb 1 MB im RAM. (Ich werde mir das für eine Inangriffname der Entwicklung einer Forth--RAM--Disk für später vormerken!) \section{Für die Einbeziehung einer RAM--Disk} gäbe es einen triftigen Grund: Man könnte dann in begrifflich direkter Weise das Disketten--Abbild in eine Datei legen und die Datei beispielsweise als E-Mail--Anhang verschicken (die Diskette \emph{nach Amerika beamen} --- Teleportation durch Übertragung der Träger--Information). Ob dabei die RAM--Disk eine Forth--Sonderanfertigung ist oder beispielsweise als \texttt{XMSDSK} [FU98] vorliegt, tut nichts zur Sache (Aufgabe für später oder für den interessierten Leser). \section{Tritt im vorliegenden Programm ein Lesefehler auf,} dann wird der Leseversuch für die anstehende Disketten--Spur wiederholt. Nach drei hintereinander aufgetretenen Lesefehlern wird das Programm abgebrochen. Am Bildschirm wird beim Aussprung dann die erreichte Seite, die erreichte Spur, die Adresse des zuletzt eingelesenen Bytes und die Angabe, ob ein Fehler vorliegt oder nicht, angezeigt. \section{Turbo--Forth, und kein ZF?} Turbo--Forth liegt in verschiedenen Versionen auf dem amerikanischen FTP--Server \url{taygeta.com}. Auch ZF ist dort zu finden. Beide Systeme fußen auf F83 von Laxen and Perry [LP84] aus dem Jahre 1984 ff. und haben das Ziel, neben der Block--Orientierung (auch) eine Anbindung an die DOS--Datei--Organisation zur Verfügung zu stellen (1987 ff.) Offensichtlich gab es bei den Entwicklungen keine Absprachen, was dazu führte, dass viele wichtige Elemente für Forth als System unterschiedlich definiert wurden. Manche lassen sich ganz schnell 1:1 anpassen. Beispiel: \texttt{l@} in Turbo--Forth und \texttt{@l} in ZF. Andere würden bei der Anpassung einen tieferen Eingriff in das System erfordern. Beispiel: \texttt{include} in Turbo--Forth und \texttt{fload} in ZF. Ich habe im vorliegenden Artikel nach längerem Zögern ZF beiseitegeschoben und mich nur auf Turbo--Forth konzentriert. Das Thema Anpassung an ZF könnte man später gesondert behandeln. \section{Die Reihenfolge der Sektoren: Eine Hiobsbotschaft} Die einzige unverrückbare Einheit bei der Abspeicherung der Bytes auf die Diskette scheint die des \emph{Sektors} zu sein: Der Sektor wird vom Controller als ein bestimmtes Maß von hintereinanderliegenden Bytes auf ein und derselben Spur betrachtet (bei 3.5--HD--Disketten üblich: 512d Bytes). Für die Durchnummerierung der Sektoren ist es eigentlich egal, auf welche Weise sie geschieht. Sie muss halt eindeutig sein (eine lineare Ordnung ergeben, d.$\,$h., es darf kein Sektor ausgelassen und keiner doppelt nummeriert werden). Als \emph{natürliche Ordnung} hatte ich in meinem Programm ursprünglich die Einteilung [Seite:Spur:Sektor] betrachtet. Zur Überprüfung habe ich vorwiegend die drei Disketten--Editoren diskedit.exe von Martin Kalisch [MK92], \texttt{cwdskedt.exe} von Christoph Walter [CW99] und \texttt{pctlsdlx.exe} von Central Point [CP88] verwandt. Dabei fiel mir ganz zum Schluss, als es für Änderungen im Programm fast schon zu spät war (der Artikel sollte noch ins anstehende VD--Heft), auf, dass \texttt{diskedit.exe} die Nummerierung der Sektoren nach [Spur:Seite:Sektor] vornimmt. Daher (oder umgekehrt) wohl auch die Bezeichnung CHS (und nicht HCS) --- und das scheint auch beim Begriff LBA (Logical Block Addressing) mitzuspielen. Sehr zu meiner Freude konnte ich feststellen, dass die nötige Umstellung im Programm keinen großen Aufwand erforderte. Aber wohl auch nur deshalb, weil ich inzwischen praktisch mit meinem Programm verschmolzen war (\emph{Welt am Draht}\/). Ich habe bei dieser Beschäftigung wieder enorm viel gelernt! --- Learning by doing. \section{Zur Überprüfung der Nummerierung} habe ich eine DOS--Diskette genommen und sie mit \texttt{diskedit.exe} analysiert: Die erste Datei--Zuordnungs--Tabelle (the File Allocation Table FAT) liegt ab Sektor 19d. Das Disketten--Abbild im RAM meines Experimentes hatte ich nach 200000h gelegt. 38d--mal auf die Plus--Taste gedrückt (100h Bytes = ein halber Sektor), lieferte das erhoffte Ergebnis: Voilá, das Datei--Verzeichnis aus der FAT! Im Datei--Abbbild, im RAM! \section{Fehler--Überprüfung} Und schließlich habe ich noch Nutzen aus meiner \emph{konservierenden} Haltung gezogen, alles im Leben aufzuheben, wie unnütz es auch geworden sein mag: Ich habe das Programm aus dem vorliegenden Artikel auch noch auf eine DOS--Diskette angesetzt, von welcher ich wusste, dass sie Stellen aufweist, die nicht gelesen werden können (feststellbar bespielsweise (auch) über PCTOOLS). Am Bildschirm erschien die Meldung: \begin{small} \begin{verbatim} ================================================= Fehler beim Einlesen des Disketten-Abbildes ------------------------------------------------- Erstes eingelesenes Byte an RAM-Adresse : 200000 Letztes eingelesenes Byte an RAM-Adresse : 3453FF Letzte Seite; oder erste, die Fehler hat : 1 Letzte Spur; oder erste, die Fehler hat : 48 ------------------------------------------------- Falls Sp/S = 0/0 : Wirklich Diskette im Laufwerk? ================================================= \end{verbatim} \end{small} Das heißt aber unter anderem auch, dass ich diese Diskette ohne Weiteres bis zu der Stelle, die der Image--Adresse 3453ffh in Spur 48h, Seite 1 entspricht, \emph{ganz normal} verwenden kann, z.B. auch für die Anfertigung einer \emph{Hilfsdiskette im Sinne von [FB09] zur Verpflanzung des BIOS} ins RAM. Und um noch zu zeigen, wie ich im vorliegenden Programm den nicht ganz abwegigen Fall aufgefangen habe, dass vergessen wurde, eine Diskette ins Laufwerk zu legen, schnell noch den dann erhaltenen Bildschirm--Ausdruck: \begin{small} \begin{verbatim} ================================================= Fehler beim Einlesen des Disketten-Abbildes ------------------------------------------------- Erstes eingelesenes Byte an RAM-Adresse : 200000 Letztes eingelesenes Byte an RAM-Adresse : 1FFFFF Letzte Seite; oder erste, die Fehler hat : 0 Letzte Spur; oder erste, die Fehler hat : 0 ------------------------------------------------- Falls Sp/S = 0/0 : Wirklich Diskette im Laufwerk? ================================================= \end{verbatim} \end{small} \section{Interpretation von Fehlermeldungen} Ich will es am Beispiel erklären: Bei einer meiner Disketten, die Fehler enthielt, bekam ich die Meldung, dass das letzte eingelesene Byte an der Adresse 9463ffh liegt und dass die letzte erreichte Spur 48h und die letzte erreichte Seite 1 ist. Pro Spurdurchgang verarbeitet das Programm 2400h Bytes. Will man also (zu Überprüfungszwecken) an den Anfang desjenigen Spurdurchgangs gelangen, an welchem das Programm mit der Fehlermeldung ausgestiegen ist, dann muss man 9463ffh + 1 - 2400h = 944000h bilden. Die Anfangs--Adresse des Abbildes der Diskette hatte ich zu 800000h gewählt. Die Differenz beträgt 144000h. Das entspricht aber genau der Formel 48*2*12*200h, wenn man statt der möglichen 50h Spuren die gemeldeten 48h Spuren bis zur fehlerhaften Stelle berücksichtig. \end{multicols} \section{Literatur} \begin{tabular}{lp{15cm}} [CP98] & PC--Tools--Deluxe R4.21. pctlsdlx.exe. Central Point Software, Inc.(1988).\\ [CW99] & Walter, Christoph: cwdskedt.exe 2.22. Für DOS. Freeware.\\ [FB98] & Behringer, Fred: Real--Mode--32--Bit--Erweiterung für Turbo--Forth. Vierte Dimension 2/1998.\\ [FB08] & Behringer, Fred: Erster Teil meiner VD--Artikel--Serie. Vierte Dimension 3/2008.\\ [FB09] & Behringer, Fred: Vierter Teil meiner VD--Artikel--Serie. Vierte Dimension 2/2009.\\ [FB10] & Behringer, Fred: Sechster Teil meiner VD--Artikel--Serie. Vierte Dimension 1/2010.\\ [FU98] & Uberto, Franck: XMSDSK, eine RAM--Disk, deren beliebige Länge auch während des Betriebs noch verändert werden kann.\\ [JN00] & Newbigin, John: http://www.chrysocome.net/rawwrite ... (2000).\\ [LP84] & Laxen, Henry, and Mike Perry: Public--Domain--Implementation von F83. Auf dem amerikanischen FTP--Server taygeta.com\\ [MK92] & Kalisch, Martin: Disk--Editor 1.2. diskedit.exe, (1992).\\ [TO02] & Oehser, Tom: http://www.toms.net/rb/~ (Version 1.7.361). Heute, im Jahre 2011, liegt die Version 2.0.103 im Internet. Das erhältliche Paket besteht aus Dateien für DOS, Linux und CD aus den Jahren 2001 und 2002.\\ [v511] & http://www.dm17.com/~/Programmcodes/v5PROT. \end{tabular} \section{Listing}\label{listing8} \begin{quote} \listinginput[1]{1}{2011-01/Listing8.fs} \end{quote} \end{document}