Artikel
Jörg Matthaei
Speicherengpaß
entschärft
64 KByte mehr Speicher für den AT
AT-Anwender verschenken kostbaren Arbeitsspeicher; denn über einen Treiber kann die 80286-CPU unter DOS zusätzliche 64 KByte adressieren. Von Microsoft wurde dieser Speicher als high memory area (HMA) spezifiziert. Auch selbstgeschriebene Programme können von HMA profitieren.
Die
Prozessoren 8086 und 8088 von Intel können über ihre 20
Adreßleitungen bis zu 1 MByte
Arbeitsspeicher adressieren. Dagegen kann eine 80286-CPU auf
einen wesentlich größeren Speicher zugreifen:
16 MByte – allerdings nicht unter
DOS.
Hier bleibt es immer noch bei dem einen Megabyte
(Bild 1).
Aber mit einem Trick adressiert die 80286-CPU auch
unter DOS mehr als 1 MByte
RAM.
Die letzte Adresse, auf die
eine 8086-CPU oder 8088 zugreifen kann, ist FFFFFh. In der
Zwei-Komponentenform, bestehend aus Segment
und Offset, heißt
genau dieselbe Adresse FFFF:000Fh. Würde der Adreßzeiger
um eins erhöht, kommt es zu einem Überlauf auf Adresse
0000:0000h, den Anfang des Arbeitsspeichers. Dieser Überlauf
wird auch als address wrap around bezeichnet. Wenn man bei einem
80286-Prozessor die 21. Adreßleitung (A20) aktivieren würde,
käme es nicht zu einem Überlauf und der Speicher von
FFFF:0010h bis FFFF:FFFFh könnte für Daten und Programme
von DOS genutzt werden. Durch diesen kleinen Trick erhält man
einen zusätzlichen Speicherbereich – nur 16 Byte
kleiner als 64 KByte
– der als HMA (high memory area)
bezeichnet wird.
1988 hat Microsoft die Extended-Memory-Spezifikation (XMS) entwickelt,
die genau festlegt, wie Programmierer extended memory und HMA nutzen
sollen. Der XMS-Treiber von Microsoft HIMEM.SYS wird mit der
Version 4.0 von DOS oder mit MS-Windows geliefert. Wenn man den
HMA-Treiber mit der Anweisung DEVICE = HIMEM.SYS in die Datei CONFIG.SYS
eingebunden hat, kann man diesen Speicher über bestimmte Funktionen
anfordern oder freigeben.
Das Programm HMA.ASM (Bild 2)
gibt einige Beispiele, wie man HMA-Funktionen
anwendet. Zuerst prüft es, ob bereits ein
XMS-Treiber installiert ist.
Anschließend holt es sich die Einsprungadresse für die
XMS-Funktionen. Danach wird der HMA-Treiber aufgerufen, wobei im
Register DX
die Anzahl der anzufordernden Bytes stehen muß. Zum
Schluß aktiviert das Programm die Adreßleitung A20. Nun
kann man den zusätzlichen Speicherbereich verwenden. Es ist
sinnvoll, möglichst viel Programmcode und Daten in diesem
Bereich unterzubringen, um die unteren 640 KByte zu entlasten. Wie
wird ein schon vorhandenes speicherresidentes
Programm in den HMA-Bereich gelegt? Ganz einfach –
der Programmcode, die Daten und die Installationsroutine bleiben bis
auf die Funktion terminate and stay resident (TSR) unverändert
(Bild 3).
Der Interrupt 27h oder die DOS-Funktion 31h wird durch die
Programmende-Funktion (DOS-Funktion 4Ch) ersetzt. Sodann wird die
HMA-Laderoutine
(Bild 4) an den bestehenden Quellcode
angefügt und vor dem ersten Befehl ein direkter Sprung auf die
HMA-Laderoutine eingefügt. Die HMA-Laderoutine, im Programm mit
HMA_LOADER bezeichnet, fordert zuerst 64 KByte HMA an und verschiebt
das gesamte Programm in diesen Speicherbereich. Anschließend
wird das Programm ab dem ursprünglichen Beginn der alten
speicherresidenten Routine ausgeführt,
und die Interruptvektoren werden verbogen.
Sie zeigen jetzt auf das Programm im hohen Speicherbereich.
Übersicht der HMA-Funktionen | |
---|---|
AH-Register | HMA-Funktionen |
00h | XMS-Versionsnummer |
01h | HMA anfordern |
02h | HMA freigeben |
03h | A20 global ermöglichen |
04h | A20 global sperren |
05h | A20 lokal ermöglichen |
06h | A20 lokal sperren |
07h | A20 abfragen |
Tips für den Umgang mit HMA
In Programmen, die im hohen Speicherbereich laufen, müssen alle Segmentregister auf das gleiche Segment zeigen. Bei Programmen, die mit dem Speicherüberlauf bei 1 MByte arbeiten, muß vor Verlassen der speicherresidenten Routine die Adreßleitung A20 deaktiviert werden. Programme, die den unteren Bereich des extended memory wie alte VDISK-Versionen benutzen, dürfen nicht gleichzeitig verwendet werden. Wer keinen AT mit extended memory besitzt, kann auch den RAM-Bereich einer EGA oder VGA im Textmodus nutzen. Doch dann darf kein Programm mehr die Videoschnittstelle in den Grafikmodus umschalten. Beim HMA-Lader muß die Adresse, zu der die speicherresidente Routine verschoben werden soll, geändert werden. Bei EGA und VGA ist das Adresse B900h.
Literatur
- [1] Chip, Anderson: 64 KByte mehr Speicher adressieren unter DOS,
MS-System-Journal 1989, März/April. - [2] NCR-DOS Programmers Guide 1985.
- Bild 1. Speicherbelegung eines AT unter DOS
;---------------------------------------------------
; HMA.ASM
;
; Programm zur Veranschaulichung der HMA-Funktionen
; des Microsoft Himem.sys Drivers.
;
; Datum: 06.06.89
; Autor: Jörg Matthaei
;---------------------------------------------------
; Macros
display macro string
lea dx,string
mov ah,09
int 21h
endm
cseg segment 'code'
assume cs:cseg,ds:cseg,es:cseg
org 80h
parms equ this byte
org 100h
begin:
mov ax,4300h
int 2Fh ; ist ein HMA Treiber instaliert ?
cmp al,80h
jz hmada
display msgnohma ; nein !
fin: mov ah,4Ch ; Programmende
int 21h
; ja hole Einsprungadresse für HMA-
hmada: push es ; Funktionen.
mov ax,4310h
int 2Fh
mov word ptr[hmaofs],bx ; speichere Einsprungadressen
mov word ptr[hmaseg],es
pop es
cmp byte ptr [parms],0 ; prüfe auf Parameter
jne anf0
display msgsyntx ; Anzeige von gültigen Parametern
jmp fin
anf0: cmp byte ptr [parms+3],'a' ; verzweige je nach Parametern
je alloc
cmp byte ptr [parms+3],'f'
je free
cmp byte ptr [parms+3],'s'
je status
jmp fin
; Die Funktion alloc reserviert 64KB HMA
alloc: mov dx,0FFFFh ; reserviere FFFF Bytes HMA
mov ah,01
call dword ptr hmaofs
dec ax
jz enab_himem ; HMA reseviert
display msgused ; Reservierung nicht möglich !
jmp fin
enab_himem:
mov ah,03 ; A20 global ermöglichen
call dword ptr hmaofs
display msgresv
jmp fin
; Die Funktion free gibt den mit alloc reservierten
; HMA Bereich wieder frei
free: mov ah,04 ; A20 global sperren
call dword ptr hmaofs
mov ah,02 ; HMA freigeben
call dword ptr hmaofs
display msgfree
jmp fin
; Die Funktion status versucht HMA anzufordern,
; gelingt dies gibt sie die Meldung HMA wird nicht benutzt aus.
; Ist eine Reservierung nicht möglich, so ist der HMA Bereich
; bereits von einem anderen Programm benutzt.
status:
mov dx,0FFFFh ; versuche FFFFh Bytes
mov ah,01 ; HMA anzufordern
call dword ptr hmaofs
dec ax
jz stat1
display msgused ; HMA bereits genutzt
jmp fin
stat1: mov ah,02 ; von Funktion status reservierte
call dword ptr hmaofs ; HMA wieder freigeben
display msgnouse
jmp fin
hmaofs dw 0 ; HMA-DRIVER OFFSET
hmaseg dw 0 ; HMA-DRIVER SEGMENT
msgnohma db 13,10,'Himem Driver ist nicht installiert',13,10,'$'
msgnouse db 13,10,'HMA wird nicht benutzt',13,10,'$'
msgresv db 13,10,'64KB HMA sind reserviert.',13,10,'$'
msgused db 13,10,'HMA wird schon benutzt',13,10,'$'
msgfree db 13,10,'HMA wieder freigegeben.',13,10,'$'
msgsyntx db 13,10,'Die Syntax für HMA lautet :',13,10
db 'hma /a für anfordern von 64KB HMA',13,10
db 'hma /f für freigeben von belegter HMA',13,10
db 'hma /s für Status HMA',13,10,'$'
cseg ends
end begin
- Bild 3. Speicherresidente Routinen in HMA
;-------------------------------------------------
; Dieses Programm wird an Ihre bestehende
; TSR-Routine angefügt und mit einem JMP-Befehl
; an erster Stelle in Ihrer TSR-Routine aktiviert.
;
; Datum : 03.06.89
; Autor : Jörg Matthaei
;-------------------------------------------------
himem proc near
begin: call hmada ; Teste ob Himem-Driver aktiv ist
jnz fin
mov cx,pgende-pganf ; pgende ist die End-Adresse Ihrer
mov dx,-1 ; TSR-Routine bzw.
mov ah,01 ; pganf ist die Start-Adresse
; cx enthält somit die Anzahl der
; Bytes die in die HMA zu kopieren
; sind
call dword ptr hmaofs ; reserviere HMA
dec ax
jz him1
ret ; Reservierung nicht möglich
him1: mov ah,03
call dword ptr hmaofs ; A20 global ermöglichen
dec ax
jnz him2
; kopiere PSP ab 10h in
push cx ; den HMA Bereich
mov ax,0FFFFh
mov es,ax
mov di,10h
mov si,10h
mov cx,0F0h
rep movsb
pop cx
mov di,offset pganf ; verschiebe TSR Routine
mov si,di ; in den HMA Bereich
rep movsb
cli
mov ds,ax ; ds=0FFFFh
db 0EAh
dw 103h,0FFFFh ; JMP FAR auf TSR Routine
sti ; die sich nun selbst im
ret ; HMA Bereich installiert !
him2: mov ah,04 ; A20 sperren
call dword ptr hmaofs
mov ah,02 ; HMA Bereich wieder freigeben
call dword ptr hmaofs
ret
hmada: mov ax,4300H ; Teste ob Himem.sys aktiv ist
int 2Fh
cmp al,80H
jz alloc
mov dx,offset msgins ; Himem.sys nicht aktiv
mov ah,09
int 21h
ret
alloc: push es
mov ax,4310H ; hole HMA Einsprungadresse
int 2Fh
mov hmaofs,bx
mov hmaseg,es
pop es
and al,0
ret
fin: mov ah,4Ch
int 21h
msgins db 10,13,9,'XMS - Driver nicht installiert !',10,13,'$'
hmaofs dw 0 ; HMA-Driver Offset
hmaseg dw 0 ; HMA-Driver Segment
himem endp
aus mc 03/90 – Seite 77-80