High Memory Area
Der Begriff High Memory Area (HMA) bezeichnet bei einem x86-kompatiblen Prozessor die ersten 65520 Byte oberhalb der 1-MiB-Grenze. Die deutsche Übersetzung hoher Speicherbereich ist inzwischen ungebräuchlich geworden.
Entstehungsgeschichte
Unter DOS wird ein x86-kompatibler Prozessor im Real Mode betrieben, wodurch sich dieser aus Softwaresicht wie die 8086er/8088er CPU der ersten IBM PCs verhält. Damit ist nur das erste MiB des RAM ansprechbar (Adressen: 00000hex … FFFFFhex). Durch die im Real Mode übliche Adressierung im Segment-Offset-Format lassen sich jedoch auch physische Speicheradressen generieren, die jenseits von 1 MiB liegen, nämlich bis 10FFEFhex. Zur binären Darstellung dieser Adressen sind 21 Adressleitungen nötig. Da der 8086 jedoch nur 20 Adressleitungen (A0 bis A19) hat, werden die vom Prozessor ausgegebenen Adressen entsprechend abgeschnitten. Die Adressen von 100000hex bis 10FFEFhex werden also als 00000hex bis 0FFEFhex ausgegeben.
Mit Erscheinen der 80286er Prozessoren änderte sich dieses Verhalten, da dieser 24 Adressleitungen besaß und so die korrekten Adressen an den Speicher weitergeben konnte. Dies führte zu Problemen, denn das BIOS sowie einige DOS-Programme verwendeten diesen „wrap around“ und verließen sich darauf, dass die Adressen bei 1 MiB abgeschnitten würden. Um nun weiterhin möglichst kompatibel zum 8086 zu sein, wurde auf den Hauptplatinen eine zusätzliche Schaltung hinzugefügt, welche die 21. Adressleitung (A20, da ab 0 gezählt wird) deaktiviert. Diese Schaltung wird als „A20-Gate“ bezeichnet. Wenn der Rechner startet, ist die 21. Adressleitung deaktiviert, das „A20-Gate“ ist geschlossen. Über bestimmte Hardware-Befehle lässt sich das „A20-Gate“ öffnen und die 21. Adressleitung aktivieren. Damit werden die Adressen nicht mehr auf 20 Bit abgeschnitten, und man erhält Zugriff auf den Speicher über 1 MiB.
Obwohl das Öffnen des „A20-Gates“ nur für den Protected Mode vorgesehen war, funktionierte dies auch im Real Mode, wobei im Real Mode jedoch nur die ersten 65520 Byte (also knapp 64 KiB) jenseits der 1-MiB-Grenze ansprechbar sind. Einige Gerätetreiber machten von diesem Trick Gebrauch und platzierten sich in diesem Speicherbereich.
HIMEM.SYS / HIDOS.SYS
Da DOS nur das erste Mebibyte des Hauptspeichers verwaltete, traten Probleme auf, sobald mehr als ein Programm oder Treiber die HMA nutzen wollten. Um dieses Problem zu lösen, wurden in den Speichermanager (z. B. HIMEM.SYS
), der den Zugriff auf den Erweiterten Speicher regelte, Funktionen aufgenommen, die die Reservierung und Freigabe der HMA regelten.
Nutzung der HMA
Ab DR DOS Version 5.0 (1990) und MS-DOS Version 5.0 (1991) war DOS in der Lage, seinen eigenen Systemkern in die HMA zu verlagern, wenn HIDOS.SYS bzw. HIMEM.SYS geladen war. Dies wurde durch die Option HIDOS=ON
bzw. DOS=HIGH
in der Konfigurationsdatei CONFIG.SYS erreicht. Damit wurde weniger „konventioneller Speicher“, also Speicher unterhalb der 640-KiB-Grenze, vom DOS-Kern belegt, was bei der chronischen Speicherknappheit unter DOS vorteilhaft war.
Bei DR DOS konnte nicht nur ein Teil des Systemkerns selbst in die HMA verschoben werden, sondern auch der residente Teil des Kommandozeileninterpreters COMMAND.COM (mit Option /MH), Teile der Pufferverwaltung (HIBUFFERS
) und ab DR DOS 6.0 eine ganze Reihe von speziell dafür ausgelegten Treibern wie KEYB, NLSFUNC und SHARE (jeweils mit Option /MH), wodurch weiterer konventioneller Speicher für Anwendungen und normale Treiber frei wurde.
Ab DR-DOS 7.02 erlaubte der Parameter SIZE=xxxx
der Konfigurationsdirektive SHELLHIGH=
eine Feineinstellung der Präallokation für den residenten Teil des Kommandozeilenprozessors, womit insbesondere bei der Verwendung von alternativen Kommandozeilenprozessoren wie 4DOS einer Fragmentierung der HMA vorgebeugt werden konnte (etwa mit SHELLHIGH SIZE=20 c:\4dos.com ...
in CONFIG.SYS), so dass insgesamt noch mehr zusammenhängender freier Speicherplatz für HMA-fähige Treiber nutzbar wurde.
Obwohl eine möglichst weitreichende Nutzung der HMA durch Treiber erstrebenswert war, machten insgesamt nur vergleichsweise wenige Treiber davon Gebrauch und wenn, dann in der Regel nur exklusiv, ohne dass dann gleichzeitig auch noch Teile des Betriebssystems oder andere Treiber in die HMA hochgeladen werden konnten.
Aufgrund der Tatsache, dass die Adressleitung A20 über das A20-Gate jederzeit von anderen laufenden Prozessen maskiert werden konnte, wodurch die HMA temporär nicht mehr erreichbar war, konnten nur Programmteile in die HMA verlagert werden, die über kurze Funktionen (sogenannte stubs) im konventionellen Speicher angesprungen wurden, in denen sichergestellt wurde, dass die A20-Leitung temporär wieder aktiviert wurde, bevor Code oder Daten in der HMA angesprochen wurden, also z. B. keine Interruptroutinen. Auch der Aufruf von externen Unterroutinen (mit nicht immer vollständig bekannten Seiteneffekten durch TSRs) aus der HMA heraus oder die Unterbrechung durch Interrupts war nicht unkritisch und erforderte besondere Vorsorgemaßnahmen in der Implementierung, da sich dabei sonst der Zustand des A20-Gates „scheinbar zufällig“ ändern konnte. Da von Seiten des Betriebssystems hierfür nur rudimentäre APIs zur Verfügung gestellt wurden und für eine sichere Implementierung etliche nicht sofort offensichtliche Race Conditions zu beachten waren, war eine Hochlademöglichkeit für manche Treiber je nach Aufgabe technisch prinzipiell nicht erreichbar, für andere zumindest aufwendig zu realisieren. Erst 386-Speichermanager wie EMM386, die unautorisierte Zugriffe auf das A20-Gate abfangen und softwaretechnisch entsprechend verarbeiten konnten, schafften hier betriebssystemseitig mehr Sicherheit in der Verwendung der HMA. Auch auf Rechnern, bei denen die A20-Leitung nicht maskierbar ist, war man vor solchen Problemen gefeit.
Ein weiterer Punkt war jedoch die Adressierung des Codes innerhalb der HMA selbst. Bei einer Relokation in die Upper Memory Area (UMA), wie sie für normale Treiber möglich war, wurde normalerweise die Segmentadresse an das Zielsegment angepasst, im Falle der HMA stand die Segmentadresse jedoch fest auf FFFEhex oder FFFFhex, so dass, wenn mehrere Software-Komponenten gleichzeitig in die HMA geladen werden sollten, sich stattdessen die Offset-Adressen ändern mussten, da zum Zeitpunkt der Kompilierung noch nicht feststand, an welcher Stelle innerhalb des HMA-Segments gerade noch Platz für den hochzuladenden Code sein würde. Diese Intra-Segment-Offset-Relokation erforderte jedoch spezielle Ladetechniken, bei denen alle Offsetbezüge innerhalb des Codes beim Laden entsprechend angepasst wurden, und die Anwendung verschiedener Programmiertricks, die nur wenige Programmierer beherrschten.[1]
Begriffsverwirrung
In den deutschsprachigen MS-DOS-Versionen, die die HMA unterstützten, wurde diese als „oberer Speicherbereich“ bezeichnet. Als die Unterstützung für Upper Memory Blocks hinzukam, verwendete man dann für diese den Namen „hoher Speicherbereich“. Die Benennung war also im Deutschen gerade umgekehrt gehandhabt wie im Englischen, was zusammen mit der insgesamt schweren Verständlichkeit der MS-DOS-Speicherverwaltung zu viel Verwirrung bei den Anwendern führte. Erst unter Windows 95 wurden die deutschen Begriffe vertauscht, so dass sie nun den Englischen direkt entsprachen.
Einzelnachweise
- Matthias Paul: Treiber dynamisch nachladen (Intra-Segment-Offset-Relokation zum Laden von TSRs in die HMA). In: de.comp.os.msdos. 2. Februar 2002, abgerufen am 2. Juli 2017.