% Content-encoding: UTF-8
\documentclass[ngerman]{article}
\usepackage[utf8]{inputenc}
\usepackage{multicol,babel}
\setcounter{secnumdepth}{0}
\setcounter{tocdepth}{0}

\begin{document}
\renewcommand{\figurename}{Tabelle}

\title{Bootmanager und FAT–Reparatur: Dritter Fort(h)schritt (LBA)}
\ifx\shorttitle\undefined\else
\shorttitle{Bootmanager 3 — LBA}
\fi
\author{Fred Behringer}
\maketitle


Im vorliegenden Artikel werden einige Forth--Worte entwickelt, mit deren Hilfe
man bei Bedarf von der CHS--Adressierung zur LBA--Adressierung übergehen kann.

\begin{multicols}{2}
\section{Ein Wort vorweg über Turbo--Forth und \texttt{ANSI.SYS}}

Noch unter DOS 6.2 gab es den Geräte--Treiber \texttt{ANSI.SYS}, der in der \texttt{CONFIG.SYS}
per \texttt{DEVICE=ANSI.SYS} eingebunden wurde und der System--Attribute über
\emph{Escape--Sequenzen} zu steuern gestattete. Im Laufe der Zeit bin ich immer wieder
dazu übergegangen, Turbo--Forth auch unter FreeDOS oder DOS 7.0 (Win 95) oder
DOS 8.0 (Win 98) oder in der DOS--Box von Windows ME zu verwenden, und ich habe
mich immer wieder über die Meldung \emph{Falsche DOS--Version} geärgert und darüber,
dass das \texttt{ANSI.SYS} aus DOS 6.2 nicht akzeptiert wurde. Turbo--Forth läuft dann
trotzdem, aber die Escape--Sequenzen werden nicht mehr ausgeführt, sondern am
Bildschirm in nicht verständlichen Buchstaben direkt angezeigt. Noch im ersten
Teil meiner Artikelserie habe ich für solche Fälle empfohlen, die \texttt{ATTRIBUTS OFF} zu schalten. Das wiederum kann ZF nicht vertragen: ZF kennt keine \texttt{ATTRIBUTS}. Also empfahl ich, \texttt{ATTRIBUTS OFF} im Listing per \verb|\| 
auszukommentieren.

In Turbo--Forth wird von \texttt{ANSI.SYS} hauptsächlich das \emph{fettgedruckte} OK oder die
\emph{fettgedruckte} Fehlermeldung hinter \verb|ABORT"| verwendet. An sich kein großes
Problem: Man kann ja ohne Weiteres auch darauf verzichten. Aber schade ist es
eben doch. Und auch auf reiner DOS--Ebene (außerhalb von Turbo--Forth) verwende
ich ANSI.SYS zur Angabe der Uhrzeit oben rechts auf dem Bildschirm und auf
Windows--DOS--Box--Ebene zur individuellen Gestaltung des Prompt--Zusatzes der Art
von \emph{Zurück zu Windows über EXIT}.

Ich hätte mir immer wieder mal ein ANSI.COM gewünscht, einen 
Escape--Sequenzen--Treiber, der an beliebiger Stelle (auch nachträglich)
aufgerufen werden kann (beispielsweise in der \texttt{AUTOEXEC.BAT}) und der das
Turbo--Forth--System, an das ich mich gewöhnt habe, nicht verstümmelt. Ich wurde
nie das Gefühl los, irgendwo mal etwas über ein solches \texttt{ANSI.COM} gelesen zu haben. Das ständige Halbwissen, das man mit sich herumschleppt, und der gelegentliche Drang, in den eigenen bisherigen Arbeiten herumzustöbern, hat mir (auch bei diesem Problem wieder) geholfen. (Schade, dass ich dazu im vorliegenden Fall ein geschlagenes Jahr gebraucht habe.) Also:

\texttt{ANSI.COM} von Michael J.\ Mefford aus dem PC Magazine des Jahres 1988 heißt die
Lösung, entwickelt 1988 (als von Turbo--Forth und ZF noch kaum die Rede war)! Sie
funktioniert prima! Und damit sind meine Bemerkungen aus dem ersten Artikel
dieser Serie über \texttt{ATTRIBUTS OFF} hinfällig: Man google sich zu den ersten 10
Eintragungen (von 13 Millionen!) durch und beschaffe sich \texttt{ANSI.COM}! (Googlen ist eine schöne Sache, wenn man erst einmal genau weiß, was man eigentlich sucht.)

Ganz nebenbei wird mit \texttt{ANSI.COM} noch ein weiteres Problem gelöst: Wie will man
denn beispielsweise unter Windows ME einen DOS--Geräte--Treiber einbauen? In der
CONFIG.SYS? Darauf reagiert doch ME gar nicht! Aber \texttt{ANSI.COM}, als ganz
gewöhnliches DOS--Programm nachträglich eingebracht (von XP rede ich ja nicht), wird in der DOS--Box von ME sauber ausgeführt. Allerdings muss man \texttt{ANSI.COM} bei jedem Abstecher zur DOS--Box erneut aufrufen!

Von XP habe ich hier nicht gesprochen! Aber die Welt besteht ja nicht nur aus
XP. Und die Forth--Welt schon gar nicht.

Eine ASM--Fassung von \texttt{ANSI.SYS} oder \texttt{ANSI.COM}, also den Quelltext, habe ich bei meiner Übung im Googlen auch gefunden! Mal sehen, vielleicht mache ich mir eine Forth--Fassung daraus. Übung macht den Meister!


\section{Eigentliche Einleitung}

Im ersten und zweiten Teil dieser Artikelserie habe ich über die
Hauptpartitionstabelle (den Master--Boot--Record: MBR) nachgedacht, über die
Partitionstabellen der logischen Laufwerke der erweiterten Partition und über
die zu den primären Partitionen und den logischen Laufwerken gehörigen
Bootsektoren. (Jedes logische Laufwerk hat neben dem \emph{Bootsektor} auch eine
eigene \emph{Partitionstabelle}. Das System hangelt sich zum gewünschten logischen
Laufwerk von Partitionstabelle zu Partitionstabelle durch.) Ich durfte mich
darüber wundern, dass die (bei mir) jenseits der DOS--8GB--Grenze liegende primäre
Partition mit Windows ME etwas aus der Reihe fiel: Ihre Adresse (man prüfe das
nach) ließ sich mit den von mir angebotenen Forth--Worten (getsect) und (putsect)
nicht ermitteln.

Im vorliegenden Artikel gehe ich der Frage nach, warum nicht: Mit der bis zu
einer Plattenkapazität von 8 GB funktionierenden CHS--Adressierung der
(physikalischen) Sektoren lässt sich das nicht machen. Da müssen \emph{logische}
Sektoren her, da muss die LBA--Adressierung angreifen. Natürlich muss bei alldem
gesichert sein, dass das BIOS die \emph{erweiterten Interrupt--13h--Funktionen}
(41h--48h) überhaupt verarbeiten kann. (Die ganz frühen PCs können das nicht.)
Auf meiner hier zu besprechenden Experimentieranlage ist der erweiterte Int13h
vorhanden, schon deshalb, weil ich ja sonst die (bei mir) 5 GB große (primäre)
ME--Partition beim Installieren von Windows ME gar nicht so weit nach hinten,
nämlich ans Ende der (ansonsten für meine Experimente ausreichend großen)
20--GB--Platte, hätte legen können.

Was mich im vorliegenden Teil 3 meiner Serie über Festplattenpartitionen (über
das FAT--Dateisystem und dergleichen) interessiert, ist also die
LBA--Adressierung. Das ist insbesondere der \emph{erweiterte Interrupt 13h} mit den
Funktionen AH=41h bis AH=48h, und da ganz besonders die beiden Funktionen AH=42h
(extended reading) und AH=43h (extended writing). (Feinheiten der Absicherung
gegen mögliche Eingabe--, Lese-- oder Schreibfehler lasse ich weg. Es geht mir um
das Gerüst. Alles Fehlende lässt sich in Forth ja leicht nachträglich einbauen.)

Die LBA--Sektoren werden über die gesamte Festplatte hinweg von 0 bis zum
Höchstsektor der Platte hochgezählt (\emph{logische} oder \emph{lineare} 
Block--Adressierung). Ich will versuchen, den Zusammenhang zwischen der (älteren)
CHS--Adressierung (über den Interrupt 13h mit vor allen Dingen den Funktionen
AH=2 und AH=3) und der LBA--Adressierung plausibel zu machen. Im vorliegenden
Artikel soll dementsprechend über den Einbau der Funktionen 42h und 43h des
erweiterten Interrupts 13h in eine Forth--Umgebung (ausprobiert mit Turbo--Forth
und ZF) gesprochen werden.


\section{Eine Lanze brechen für Turbo--Forth}

Alle Entwicklungsarbeiten (in den VD--Artikeln 1 bis 3 zum vorliegenden Thema)
habe ich in Turbo--Forth (TF) durchgeführt und mit ZF überprüft. TF und ZF haben
den Vorteil, dass man das System nicht erst um Erlaubnis zu bitten braucht, wenn
man den vollen Zugriff (\emph{Administrator--Rechte}) auf die eigene Maschine haben
möchte. TF und ZF haben aber den Nachteil, dass sie nur in 16--Bit--Breite
arbeiten. Bei der LBA--Adressierung reicht das nicht, so dass mit \emph{doppelter
Genauigkeit} gearbeitet werden muss.


\section{Konvertierung von CHS nach LBA (Logical Block Addressing)}

Für den Fall, dass es interessieren sollte, von welcher Art von \emph{Festplatte} ich
rede: Meine Betrachtungen beziehen sich auf IDE--Platten. Eine vereinfachte
Darstellung derer Wirkungsweise läuft wie folgt:

Eine Festplatte besteht aus einer oder mehreren Scheiben. Jede Scheibe hat zwei
Seiten. Jeder Scheibenseite (die zu 0/1 der ersten Scheibe, 0/1 der zweiten
Scheibe usw. durchnummeriert werden) ist genau ein Schreib/Lese--Kopf (head)
zugeordnet. Bei der Festplattenverwaltung zur eindeutigen Adressierung der
einzelnen Sektoren (siehe gleich) wird nur von \emph{Kopf} gesprochen, auch wenn in
der bildlichen Vorstellung eigentlich \emph{Scheibe} (oder zumindest \emph{Scheibenseite})
gemeint ist. Die Köpfe (also eigentlich die Scheibenseiten) werden vom BIOS in
konzentrisch angeordnete \emph{Spuren} (tracks) unterteilt. Jede Spur enthält eine
bestimmte Anzahl von \emph{Sektoren} (sectors), eine Zahl, die von Spur zu Spur
gleich bleibt. Jeder Sektor enthält eine bestimmte Zahl von Bytes. Üblich sind
512 Bytes pro Sektor. Die Daten werden sektorweise gelesen oder geschrieben.

Die auftretenden Zahlen für Köpfe, Spuren und Sektoren geben nicht unbedingt die
wirklichen Verhältnisse wieder. Sie sind bei der Festplatte nur für die
Verwaltung wichtig. Die eigentliche \emph{Geometrie} der Festplatte kann (vom
Hersteller) durch (interne) Umrechnungs--Vorrichtungen angepasst worden sein.
(Man braucht es also nicht wörtlich zu nehmen, wenn man vom BIOS--Setup erfährt,
dass die Platte 255 Köpfe hat --- und man braucht die Platte auf gar keinen Fall
auseinanderzunehmen, um nachzuprüfen, ob das wirklich stimmt ;-)

Man hätte sich auch vorstellen können, dass bei der Zählung der Sektoren erst
alle Spuren einer Scheibenseite durchlaufen werden, dann die nächste Seite, dann
die nächste Scheibe usw. Das ist nicht der Fall. Es wird eine neue
Einteilungs--Einheit eingeführt, die des \emph{Zylinders} (cylinder): Alle
(übereinanderliegenden) Spuren derselben (auf die jeweilige Scheibenseite
bezogenen) Nummer gehören zu ein und demselben Zylinder. Bei der Zählung (dem
Durchnummerieren) der Sektoren werden erst die Sektoren der ersten Spur der
ersten Scheibenseite drangenommen, dann die der ersten Spur der zweiten
Scheibenseite, dann die der ersten Spur der ersten Seite der zweiten Scheibe und
so weiter, bis der erste Zylinder durch ist. Dann dasselbe Zählverfahren in
Bezug auf den zweiten Zylinder. Und so weiter. (Wenn man liest, dass ein \emph{Kopf}
63 Sektoren hat, dann ist das entsprechend zu verstehen: Ich komme in meiner
Vorstellung gut durch, wenn ich bei Ordinalzahlen (bei Nummern) von \emph{Kopf} rede,
bei Kardinalzahlen (bei Anzahlen) aber von \emph{Spur}: Sektor 5 bei Kopf 4, aber 63
Sektoren pro Spur. Warum aber, so frage ich, hätte man nicht gleich von Spuren
statt von Köpfen reden können? \emph{Spur 4} nimmt sich bestimmt nicht schlechter
aus als \emph{Kopf 4}. Aber über \emph{63 Sektoren pro Kopf} stolpert natürlich jeder. Die
\emph{Spuren} müssten eben von oben nach unten gezählt werden, und nicht in
konzentrischer Reihenfolge. Und wäre das schlimm? Bei den \emph{Köpfen} kommt ja noch
hinzu, dass sie alle gleichzeitig auf die Festplatte zugreifen (können), in der
Zählung aber sequentiell eingeordnet werden müssen.

Lange Rede, kurzer Sinn: Es ist letztendlich völlig egal, wie man sich den
Aufbau einer Festplatte vorstellt, wichtig sind die Zahlen, die den fest
eingebürgerten Begriffen \emph{Zylinder}, \emph{Kopf} und \emph{Sektor} (engl. (C)ylinder,
(H)ead, (S)ector) zugeordnet sind. Und wenn man nun mal beim Begriff \emph{Kopf}
(head) bleibt, braucht man nicht mehr über den Begriff \emph{Spur} zu philosophieren.
Der ist (für die Plattenverwaltung) überflüssig. Dann hat eben beispielsweise
\emph{jeder Kopf 63 Sektoren} --- und beim Begriff SPT (sector per track) im Wikipedia
wäre eben nicht, wie dort geschehen, \emph{Track} gleich \emph{Zylinder} zu setzen,
sondern gleich \emph{Kopf}.

(Mir geht es bei der Entwicklung eines Forth--Wortes zur Umrechnung von CHS nach
LBA (siehe Listing) um ein Verstehen der zugehörigen Formel --- und da ist die
Angabe \emph{SPT : Sektoren/Track (Track \^{ }= Zylinder)} im Artikel \emph{Cylinder Head
Sector} \url{http://de.wikipedia.org/wiki/Cylinder_Head_Sector} aus der freien
Enzyklopädie Wikipedia nicht sehr hilfreich. Eben nicht 
SPT = Sektoren pro Zylinder! SPT = Sektoren pro Spur! Und das heißt SPT = Sektoren pro Kopf!)

Zu beachten ist bei der CHS--Zählweise (und das ist sehr wichtig!), dass Zylinder
und Kopf bei 0 beginnen, die Sektor--Zählung aber bei 1. Der Master--Boot--Record
(MBR) hat also die Adresse C--H--S = 0--0--1 (und nicht etwa 0--0--0). In der
LBA--Zählweise dagegen (siehe gleich) hat der MBR tatsächlich die Nummer 0. (Man
versuche, mit dem ehrwürdigen DEBUG aus DOS an den MBR heranzukommen, nicht
durch Nachbilden der im Vorliegenden entwickelten Assembler--Befehle, sondern
über den DEBUG--Load--Befehl \texttt{l} (kleines l)!)

Bei den frühen Festplatten stieß man mit der CHS--Adressierung bald an Grenzen:
Unter Beibehaltung der Kompatibilität musste etwas Neues eingeführt werden, ohne
das \emph{Alte} deshalb gleich aufgeben zu müssen. Dieses Neue heißt LBA (Logical
oder Linear Block Addressing). Dabei gibt es nur noch \emph{Sektoren} (keine Köpfe
und Zylinder mehr), und die werden die ganze Platte hindurch durchnummeriert,
auch über eventuell bestehende Platten--Partitionen hinweg. Zur besseren
Unterscheidung werden Sektoren der CHS--Betrachtungsweise auch \emph{physikalische}
Sektoren genannt, Sektoren der LBA--Betrachtungsweise \emph{logische} Sektoren.

Die Zählung der logischen Sektoren beginnt bei 0 ! Der MBR hat also die
LBA--Nummer 0.

Zum besseren Verständnis möchte ich die folgenden Bezeichnungen einführen:

\begin{tabular}{lcl}
    C    &=& Zylindernummer\\
    H    &=& Kopfnummer\\
    S    &=& Sektornummer (phys.\ Sektor)\\
    s    &=& Sektornummer (log.\ Sektor)\\
    S/K  &=& Sektoren pro Kopf\\
    K/Z  &=& Köpfe pro Zylinder\\
\end{tabular}

Bei gegebener Zylindernummer C, Kopfnummer H und Nummer S des physikalischen
Sektors berechnet sich die Nummer s des zugeordneten logischen Sektors zu:

$$
    s    = ((C*K/Z + H) * S/K) + S - 1
$$

Dabei liefert

\begin{footnotesize}
\begin{tabular}{llcrl}
    Zylinder    $\!\!\!$&$C$$\!\!\!$&:&$\!\!\!$$C * K/Z * S/K$&$\!\!\!$logische Sektoren,\\
    Kopf        $\!\!\!$&$H$$\!\!\!$&:&$\!\!\!$$H * S/K$&$\!\!\!$logische Sektoren und\\
    Phys. Sektor$\!\!\!$&$S-1$$\!\!\!$&:&$\!\!\!$$s$&$\!\!\!$logische Sektoren.\\
\end{tabular}
\end{footnotesize}

(Bei $s$ zählt 0 mit, bei $S$ nicht.)


\section{Der zugrundegelegte Computer als Beispiel}

Das BIOS meiner (hier besprochenen) Anlage gibt beim Aufrufen des BIOS--Setups
für die in Frage stehende Festplatte 2491 Zylinder, 255 Köpfe und 63 Sektoren
aus. Das weiter unten erwähnte Programm \emph{Partition Table Doctor} liefert als
Anzahl logischer (also LBA--) Sektoren den Wert 40017915 (alle Angaben dezimal).
Geht man von der üblichen Zahl von 512 Bytes pro Sektor aus, dann entspricht der
Wert 40017915 * 512 in etwa einer Festplatten--Kapazität von 20 Gigabyte. Das
BIOS--Setup liefert für \emph{size} den Wert 20490 MB . Geht man die Nummerierung der
LBA--Sektoren durch, dann erhält man:

\begin{center}
\begin{tabular}{rrrr}
    Cyl.    & Head   & Sector  & LBA--Sector\\
    0--2490  & 0--254  &   1--63  & 0--40017914\\

         0  &      0 &       1 &    0       \\
         0  &      0 &       2 &    1 \\
         .  &      . &      .. &   .. \\
         0  &      0 &      63 &   62 \\
         0  &      1 &       1 &   63 \\
         0  &      1 &       2 &   64 \\
         .  &      . &      .. &  ... \\
         0  &      1 &      63 &  125 \\
         0  &      2 &       1 &  126 \\
         0  &      2 &       2 &  127 \\
         .  &      . &      .. &  ... \\
         0  &      2 &      63 &  188 \\
         0  &      3 &       1 &  189 \\
         .  &      . &      .. &..... \\
         0  &    254 &       1 &16002 \\
         0  &    254 &       2 &16003 \\
         .  &    ... &      .. &..... \\
         0  &    254 &      63 &16064 \\
         1  &      0 &       1 &16065 \\
         1  &      0 &       2 &16066 \\
         .  &      . &      .. &..... \\
         1  &      0 &      63 &16127 \\
         .  &      . &      .. &..... \\
\end{tabular}
\end{center}

Der \emph{erste} logische Sektor hat die Nummer 0 und entspricht dem CHS--Wert 0--0--1.
Das geht dann die Reihe der physikalischen Sektoren entlang so durch bis zum
logischen Sektor 62, der dem CHS--Wert 0--0--63 entspricht. Dann wird (bei gleichem
Zylinder) zum nächsten Kopf übergegangen: Der logische Sektor 63 (also der 64.
LBA--Sektor) entspricht dem CHS--Wert 0--1--1 (Der CHS--Sektor beginnt wieder bei 1,
und nicht etwa bei 0). Und wieder alle physikalischen Sektoren durch bis zum
logischen Sektor 125, der dem CHS--Wert 0--1--63 entspricht. Der logische Sektor
126 entspricht dem CHS--Wert 0--2--1. Und so weiter und so fort. Wenn alle
Kopfnummern ausgeschöpft sind, wird zum nächsten Zylinder übergegangen. Der
logische Sektor 16127 entspricht dem CHS--Wert 1--0--63, usw.

Ich möchte nicht verschweigen, dass mir bei der Ermittlung und Überprüfung der
hier wiedergegebenen Werte das Programm \emph{Partition Table Doctor} der PTDD Group
at \url{http://www.ptdd.com} (selbstgebrannte Live--CD aus einer ganz kleinen ISO--Datei
der Begleit--DVD von c't 24/2008) eine große Hilfe war. Allerdings habe ich auch
hier wieder für meine FAT--Reparatur--Absichten einige Dinge schmerzlich vermisst.
Aber gerade dieser Umstand zeigt mir erneut, eine wie sehr viel noch größere
Hilfe mir ein Forth--Werkzeugkasten voller entsprechender Hilfsmittel zur eigenen
Gestaltung wäre. Ich befinde mich auf dem besten Wege, mir einen solchen selbst
zusammenzustellen, und habe vor, diesen Gedanken zügig weiterzuverfolgen.

Nebenbei bemerkt: Im VD--Heft 4/2008 wurde in einem der dortigen Artikel über die
Suche nach einer geeigneten DOS--Emulation für ein DOS--freies System nachgedacht.
Die ebenerwähnte Live--CD baut auf einer abgespeckten FreeDOS--Version auf.
FreeDOS kann man sich beispielsweise von \url{http://www.freedos.org} besorgen. Es
liefert dem PC eine vollwertige, der MS--DOS--Version 6.2 mehr als ebenbürtige
DOS--Umgebung mit \texttt{a:} als Laufwerk. Ein eventuell schon vorhandenes reales
(Disketten--)Laufwerk \texttt{a:} wird dann nach \texttt{b:} verbannt.

Noch nebenbeier bemerkt: Traue nie einem Programm, das du nicht selbst vermurkst
hast! Das Laufwerk b: (5,25") lasse ich normalerweise als im BIOS abgemeldet
mitlaufen. Es lag auf der Hand, dass ich mal schnell wissen wollte, was
passiert, wenn ich b: im BIOS wieder einschalte. Wird dann \texttt{a:} nach \texttt{b:} und
daraufhin \texttt{b:} nach --- ja wohin eigentlich --- verschoben? Nichts passiert! Die
FreeDOS--basierte Partition--Table--Doctor--Live--CD bootet dann einfach nicht. Und
wenn ich beide Disketten--Laufwerke im BIOS abhänge? Dann erhält die
DOS--Emulation wie gehabt den Laufwerkbuchstaben \texttt{a:}. Man lernt nie aus! Schöner
wäre es gewesen, und es hätte mir Arbeit erspart, wenn ich diese Informationen
gleich zu Anfang hätte nachlesen können. Man stelle mir nicht die Frage: \emph{Wozu
willst du das eigentlich wissen?} Ich will es halt wissen! Und mit Forth als
schnell anpassbares Analyse--Werkzeug darf ich mir eine solche Haltung auch
erlauben.


\section{Konvertierung von LBA nach CHS}

Natürlich kann man die ganze Angelegenheit auch umkehren: Von LBA nach CHS.
Damit könnte man --- aus welchem Grund auch immer --- ein mit den INT13h--Funktionen
42h und 43h in Assembler erstelltes Sektoren--Lese/Schreib--Programm über die
Funktionen 2h und 3h von INT13h neu fassen --- soweit die CHS--Grenze hier nicht
eine Schranke setzt. Wie man (durch Vergleich mit der obigen Formel für die
Berechnung der logischen Sektornummer LBA aus den CHS--Angaben heraus) leicht
nachprüft, lautet die \emph{Umkehrformel}:

\begin{eqnarray*}
    (s+1)/(S/K * K/Z) &=& C + Rest1\\
    Rest1/(S/K)       &=& H + Rest2\\
    Rest2             &=& S\\
\end{eqnarray*}

\section{Links}

\begin{small}
\url{http://de.wikipedia.org/wiki/Cylinder_Head_Sector} \\
\url{http://www.ptdd.com}\\
\url{http://www.freedos.org} 
\end{small}

\end{multicols}


\section{Listing}

\begin{quote}
\listinginput[1]{1}{2009-01/BOOTMA-3.FTH}
\end{quote}

\vfill
\begin{center}
\includegraphics[width=0.4\textwidth]{2009-01/Bootsector}\\
nach einer Idee von Jessica Ledbetter (jledbetter@acm.org)
\end{center}
\vfill

\end{document}
