home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Power-Programmierung
/
CD1.mdf
/
assemblr
/
library
/
lib4a86
/
demo
/
bheap.dem
next >
Wrap
Text File
|
1992-02-16
|
43KB
|
1,342 lines
; ----------------------------
; BHEAP.DEM - Demoprogramm für die Routinen aus BHEAP.LIB
; (für den A86)
;
; (c) Bernd Schemmer 1992
; Letzter Update: 15.02.1992
;
; Übersetzen:
; A86 BHEAP.DEM DEMOS.INC TO BHEAP.COM
;
; Hinweis: Die Environment-Variable 'A86' muß den Dateinamen 'MACROS.MAC'
; enthalten und die .LIB-Dateien müssen über die Datei A86.LIB
; erreichbar sein.
;
; ---------------------------
jmp start
; ----------------------------
; Meldungen und Fehlermeldungen
logo db CR,LF
db 'BHEAP.DEM - Demoprogramm für die Routinen aus BHEAP.LIB' ,CR,LF
db '--------------------------------------------------------' ,CR,LF
db 'Das Programm führt folgende Arbeitsschritte aus:' ,CR,LF
db '1. Einlesen der Eingabe-Datei auf den BasedHeap' ,CR,LF
db '2. Entfernen aller Zeilen, die mit einem Semikolon' ,CR,LF
db ' beginnen und Ersetzen aller Leerzeilen durch '';;''' ,CR,LF
db '3. Verkleinern des BasedHeaps auf die kleinst mögliche' ,CR,LF
db ' Größe und Sichern des BasedHeaps in die Datei DEMO.BHP',CR,LF
db '4. Löschen des BasedHeaps' ,CR,LF
db '5. Neuanlage des BasedHeaps in einem anderen Segment' ,CR,LF
db '6. Lesen des BasedHeaps aus der Datei DEMO.BHP und ver-' ,CR,LF
db ' größern des BasedHeaps auf die maximal mögliche Größe.',CR,LF
db '7. Ausgeben des BasedHeaps in die Ausgabe-Datei' ,CR,LF
db CR,LF
db 'Das Demo muß folgendermaßen aufgerufen werden:' ,CR,LF
db ' BHEAP.COM eingabedatei ausgabedatei' ,CR,LF
db CR,LF,CR,LF
db 'Bitte eine Taste drücken (ESC = Programm-Abbruch) ...' ,CR,LF
db CR,LF
GETLENGTH logo
; Fehlermeldungen
; ------------------------------------------
MakeMsg ParamError, '*** Fehlerhaften Parameter oder zuwenig Parameter angegeben.'
MakeMsg MemoryError, '*** Zuwenig freier Speicher.'
MakeMsg OFileError, '*** Fehler beim Öffnen der Ausgabe-Datei'
MakeMsg IFileError, '*** Fehler beim Lesen der Eingabe-Datei'
MakeMsg IFileError1, '*** Eingabe-Datei ist zu groß'
MakeMsg WriteFileError, '*** Fehler beim Schreiben der Datei mit dem BasedHeap.'
MakeMsg ReadFileError, '*** Fehler beim Lesen der Datei mit dem BasedHeap.'
MakeMsg OutputError, '*** Fehler beim Schreiben in die Ausgabe-Datei.'
; Meldungen
; ------------------------------------------
MakeMsg HeapInitMsg, '--- Richte den BasedHeap ein ...'
MakeMsg MakeDummys, '--- Erstelle die Dummy-Blöcke ...'
MakeMsg ReadLinesMsg, '--- Lese die Eingabe-Datei ...'
MakeMsg CollectMsg, '--- Reorganisiere die freien Blöcke auf dem BasedHeap ...'
MakeMsg ProceedMsg, '--- Bearbeite die Zeilen ... '
MakeMsg ShrinkMsg, '--- Verkleinere den BasedHeap ...'
MakeMsg WriteFileMsg, '--- Sichere den BasedHeap in die Datei DEMO.BHP ... '
MakeMsg DeleteMsg, '--- Lösche den BasedHeap ...'
MakeMsg NewInitMsg, '--- Richte den BasedHeap neu ein ...'
MakeMsg ReadFileMsg, '--- Lese den BasedHeap aus der Datei DEMO.BHP ...'
MakeMsg ExpandMsg, '--- Vergrößere den BasedHeap ...'
MakeMsg ShowHeapMsg, '--- Schreibe die Zeilen in die Ausgabe-Datei ...'
MakeMsg DeleteMsg1, '--- Lösche den BasedHeap ...'
MakeMsg Lines1Msg, '_____ Elemente auf dem BasedHeap.'
MakeMsg Lines2Msg, '_____ Zeilen werden geschrieben.'
; Variablen
; ------------------------------------------
; Puffer zum Lesen der Zeilen der Eingabe-Datei
LineBuffer db 0,255 dup 20h
; Variablen zum Verwalten der Ein- und Ausgabe-
; Dateien
OutputFileHandle dw 0 ; Handle der Ausgabe-Datei
InputFileHandle dw 0 ; Handle der Eingabe-Datei
InputFileLength dw 0 ; Größe der Eingabe-Datei
; Zum Lesen und Schreiben wird der gleiche
; Puffer verwendet!
OutputFileOff LABEL WORD ; Pufferzeiger für die Ausgabe-Datei
InputFileOff dw 0 ; Pufferzeiger für die Eingabe-Datei
InOutFileSeg dw 0 ; Segment des Speicherblocks zum Lesen der
; Eingabe-Datei und Schreiben der Ausgabe-Datei
; ------------------
; Name der Datei zum Sichern des BasedHeaps
BHeapFileName db 'DEMO.BHP',0
BHeapFileHandle dw 0 ; Handle der Datei zum Sichern des BasedHeaps
BHeapFileLength dw 0 ; Länge der Datei zum Sichern des BasedHeaps
BasedheapLength dw 01000h ; Länge des Speicherblocks für den BasedHeap
; in Paragraphen, Voreinstellung: 1 Segment
; ------------------
; Aufbau der Blöcke auf dem BasedHeap
; ------------------------------------------
HeapBlock STRUC
Previous dw ? ; Zeiger auf den Vorgänger
Next dw ? ; Zeiger auf den Nachfolger
LineLength db ? ; Länge der Zeile
Line db ? ; Zeileninhalt (variabel!)
ENDS
; ----------------------------
start:
call ShowLogoAndAsk ; Logo ausgeben, Speicherblock verkleinern
; und Taste lesen
; ----------------------------
; Ein- und Ausgabe-Dateien eröffnen
call OpenInAndOutputFiles
IF c jmp ErrorEnde1 ; Fehler!
; ----------------------------
l1:
; 1. Teil: BasedHeap anlegen und Zeilen lesen
; -------------------------------------------
Write_String HeapInitMsg
call BuildBasedHeap ; BasedHeap einrichten
IF c jmp ErrorEnde1 ; Fehler!
; Größe des Speicherblocks für den BasedHeap
; sichern
mov BasedHeapLength,cx
call ShowBasedHeapData
IF c jmp ErrorEnde1
; ES = BasedHeap-Segment
Write_String MakeDummys
; Kette für die Zeilen initialisieren
call InitBasedHeapKette
IF c jmp ErrorEnde1 ; Fehler!
call ShowBasedHeapData
IF c jmp ErrorEnde1
; SI -> 1. DummyBlock
; DI -> 2. DummyBlock
; alle weiteren Blöcke werden zwischen diesen
; beiden Blöcken in die Kette eingefügt
; ------------------
Write_String ReadLinesMsg
; Such-Strategie ändern
or b es:BHeapFlags,TryLastPtrFirst
and b es:BHeapFlags,FreePtrFirst
; nun alle Zeilen aus der Eingabe-Datei
; bearbeiten
mov B PunktZaehler,0
ReadLineLoop:
call LaufZeitAnzeige
; Zeile lesen
call GetNextLine
jc >l1 ; EOF erreicht
call GetNewHeapBlock ; neuen Block erstellen
call CheckBasedHeapError
jnc ReadLineLoop
push ax,bx,cx,dx
call ShowCR_LF
call ZeigeAnzahl
call ShowBasedHeapData
pop dx,cx,bx,ax
jmp ErrorEnde1
; ------------------
l1:
mov B PunktZaehler,0
; Dateiende erreicht
call ShowCR_LF
call ZeigeAnzahl
call ShowBasedHeapData
IF c jmp ErrorEnde1
; ----------------------------
; 2. Zeilen Bearbeiten
; --------------------
Write_String ProceedMsg
call ProceedLines
IF c jmp ErrorEnde1 ; Fehler!
call ZeigeAnzahl
call ShowBasedHeapData
IF c jmp ErrorEnde1
Write_String CollectMsg
call ChainFreeBHeapBlocks ; freie Blöcke zusammenfassen
call CheckBasedHeapError
if c jmp ErrorEnde1
call ShowBasedHeapData
if c jmp ErrorEnde1
; ----------------------------
; 3. BasedHeap sichern
; --------------------
Write_String ShrinkMsg
call ShrinkBasedHeap ; BasedHeap verkleinern
call ShowBasedHeapData
IF c jmp ErrorEnde1
Write_String WriteFileMsg
call SaveBasedHeap ; BasedHeap sichern
if c jmp ErrorEnde1
; ----------------------------
; 4. BasedHeap löschen
; ---------------------
Write_String DeleteMsg
mov es,W BHeapSeg ; BasedHeap-Segment freigeben
mov ah,049h
int 021h
mov es,cs ; ES = CS
mov ah,048h ; ein Dummy-Segment belegen, damit sich
mov bx,010h ; das Segment des BasedHeaps verschiebt
int 021h
jnc >l1
l2:
; Speicherfehler!
mov dx,offset MemoryError
mov cx,MemoryError_LENGTH
jmp ErrorEnde1
l1:
; ----------------------------
; 5. BasedHeap neu einrichten
; ---------------------------
Write_String NewInitMsg
; ein neues Segment für den BasedHeap belegen
call BuildBasedHeap
IF c jmp ErrorEnde1
; CX = Länge des neu eingerichteten BasedHeaps
cmp cx,BasedHeapLength
jb l2 ; Fehler: Basedheap muß mindestens genauso
; groß sein wie beim erstenmal
call ShowBasedHeapData
IF c jmp ErrorEnde1
; ----------------------------
; 6. BasedHeap aus der Datei lesen
; --------------------------------
Write_String ReadFileMsg
; BasedHeap lesen
call ReadSavedBaseHeap
IF c jmp ErrorEnde1
call ShowBasedHeapData
IF c jmp ErrorEnde1
Write_String ExpandMsg
call ExpandBasedHeap ; BasedHeap vergrößeren
call ShowBasedHeapData
IF c jmp ErrorEnde1
; ----------------------------
; 7. Zeilen in die Ausgabedatei schreiben
; ---------------------------------------
Write_String ShowHeapMsg
mov es,W BHeapSeg ; ES = Segment des BasedHeaps
call ZeigeAnzahl ; Anzahl der Elemente auf dem BasedHeap ausgeben
call WriteHeapElements
mov ds,cs ; DS = CS
jc ErrorEnde1
Write_String DeleteMsg1 ; BasedHeap löschen
call GetFirstBHeapBlock
call CheckBasedHeapError
jc ret ; Fehler!
; ES:BX -> 1. Block auf dem BasedHeap
call ReleaseBHeapMem ; alle Blöcke ab dem 1. Block löschen
; ->> gesamten BasedHeap löschen
; (geht auch durch den erneuten Aufruf
; von InitBHeap)
call CheckBasedHeapError
jc ret ; Fehler!
call ShowBasedHeapData
IF c jmp ErrorEnde1
mov al,0
jmp SHORT Ende
; ----------------------------
; DX = Offset einer Fehlermeldung
; CX = Länge der Fehlermeldung
ErrorEnde1:
call ShowCR_LF
call OutputMsg ; Fehlermeldung ausgeben
call ShowCR_LF
ErrorEnde:
mov al,0FFh
Ende:
push ax
call CloseFiles ; Dateien schliessen
pop ax
EndProcess
; ----------------------------
; ShrinkBasedHeap
;
; Funktion: Verkleinert den BasedHeap
;
; Ausgabe: CF = 0 ->> okay
; CF = 1 ->> Fehler, AX = Fehlernummer
; DX = Offset der Fehlermeldung
; CX = Länge der Fehlermeldung
;
ShrinkBasedHeap:
mov es,BheapSeg
; 1. Mindestgröße des BasedHeaps ermitteln
; (= Länge des belegten Teils)
call GetMaxBHeapPointer
call CheckBasedHeapError
jc ret ; Fehler!
mov cx,ax ; CX = Länge des belegten Teils
;
call ChangeBHeapSize ; 2. BasedHeap verkleinern
call CheckBasedHeapError
jc ret
; 3. Speichersegment verkleinern
mov bx,cx ; BX = neue Größe des BasedHeaps
; in Bytes
test bx,0Fh
pushf
shr bx,1
shr bx,1
shr bx,1
shr bx,1
popf
if nz inc bx ; BX = neue Größe des BasedHeaps
; in Paragraphen
mov BasedHeapLength,bx
mov ah,04Ah
int 021h ; Speicherblock verkleinern
jnc ret
l8:
mov dx,offset MemoryError
mov cx,MemoryError_LENGTH
ret
; ----------------------------
; ExpandBasedHeap
;
; Funktion: Vergrößert den BasedHeap
;
; Ausgabe: CF = 0 ->> okay
; CF = 1 ->> Fehler, AX = Fehlernummer
; DX = Offset der Fehlermeldung
; CX = Länge der Fehlermeldung
;
ExpandBasedHeap:
; 1. Speichersegment vergrößern
mov es,BHeapSeg
mov bx,1000h
mov ah,04Ah ; Größe des Speicherblocks ändern
int 021h
jnc >l1 ; okay
; Fehler
cmp ax,08 ; Fehler 8?
jne >l8 ; nein, raus
mov ah,04Ah ; ja, versuchen wir es nochmal
int 021h
jnc >l1
l8:
mov dx,offset MemoryError
mov cx,MemoryError_LENGTH
stc
ret
l1:
cmp BasedHeapLength,bx
ja l8 ; zuwenig Speicher
mov BasedHeapLength,bx
mov cx,bx ; CX = neue Größe des Speicherblocks
shl cx,1 ; in Paragraphen
shl cx,1
shl cx,1
shl cx,1
or cx,cx
if z dec cx ; CX = neue Größe des Speicherblocks
; in Bytes
call ChangeBHeapSize ; 2. BasedHeap vergrößern
call CheckBasedHeapError
ret
; ----------------------------
; SaveBasedHeap
;
; Funktion: Sichert den BasedHeap
;
; Ausgabe: CF = 0 ->> okay
; CF = 1 ->> Fehler, AX = Fehlernummer
; DX = Offset der Fehlermeldung
; CX = Länge der Fehlermeldung
;
SaveBasedHeap:
mov cx,0 ; Datei zum Sichern des BasedHeaps
mov ah,03Ch ; anlegen und öffnen
mov dx,offset BHeapFileName
int 021h
jc >l2 ; Fehler beim Öffnen der Datei
; FileHandle sichern
mov BHeapFileHandle,ax
; Größe des zu sichernden Teils ermitteln
call GetMaxBHeapPointer
call CheckBasedHeapError
jc ret ; Fehler!
; AX = Größe des zu sichernden BasedHeaps
mov BHeapFileLength,ax
mov cx,ax ; CX = Größe des zu sichernden BasedHeaps
mov bx,BHeapFileHandle
mov dx,0
mov ds,W BHeapSeg ; DS <> CS
mov ah,040h
int 021h
mov ds,cs ; DS = CS
jc >l2 ; Fehler beim Schreiben der Datei
cmp ax,cx
jne >l2 ; Fehler beim Schreiben der Datei
mov ah,03Eh
int 021h ; Datei schließen
jnc >l1
; Fehler beim Schliessen der Datei
l2:
mov dx,Offset WriteFileError
mov cx,WriteFileError_LENGTH
stc
l1:
ret
; ----------------------------
; ReadSavedBaseHeap
;
; Funktion: Liest den BasedHeap aus einer Datei
;
; Ausgabe: CF = 0 ->> okay
; CF = 1 ->> Fehler, AX = Fehlernummer
; DX = Offset der Fehlermeldung
; CX = Länge der Fehlermeldung
;
ReadSavedBaseHeap:
mov ax,03D00h ; Datei zum Lesen öffnen
mov dx,offset BHeapFileName
int 021h
jc >l2 ; Fehler beim Öffnen der Datei
mov BHeapFileHandle,ax ; FileHandle sichern
mov cx,BHeapFileLength ; CX = Größe des zu lesenden BasedHeaps
mov bx,BHeapFileHandle
mov ds,W BHeapSeg ; DS <> CS
mov dx,0
mov ah,03Fh
int 021h
mov ds,cs ; DS = CS
jc >l2
cmp ax,cx
jnz >l2 ; Fehler beim Lesen
mov ah,03Eh
int 021h ; Datei schließen
jnc >l1
; Fehler beim Schliessen der Datei
l2:
mov dx,offset ReadFileError
mov cx,ReadFileError_LENGTH
stc
l1:
ret
; ----------------------------
; BuildBasedHeap
;
; Funktion: Richtet den BasedHeap ein
;
; Ausgabe: CF = 0 ->> okay, ES = Segment des BasedHeaps
; CX = Länge des Speicherblocks des
; BasedHeaps in Paragraphen
; CF = 1 ->> Fehler, AX = Fehlernummer
; DX = Offset der Fehlermeldung
; CX = Länge der Fehlermeldung
;
BuildBasedHeap:
mov ah,048h ; Neues Segment für den BasedHeap anfordern
mov bx,BasedHeaplength
int 021h
jnc >l1
cmp ax,8
jne >l2 ; Fehler!
mov ah,048h ; nehmen wir was wir kriegen können
int 021h
jnc >l1
l2:
; Speicherfehler!
mov dx,offset MemoryError
mov cx,MemoryError_LENGTH
stc
jmp ret
l1:
; AX = Segment für den BasedHeap
mov cx,bx
push cx
mov cl,4 ; Größe des BasedHeaps in Bytes berechnen
shl bx,cl
or bx,bx
if z mov bx,0FFFFh ; BX = Größe des BasedHeaps in Byte
; BasedHeap einrichten
mov cx,bx ; CX = Größe des BasedHeaps in Byte
mov es,ax ; ES = Segment des BasedHeaps
call InitBHeap
pop cx
call CheckBasedHeapError ; auf Fehler testen
jc ret ; Fehler beim Einrichten des BasedHeaps
; Das Benutzerfeld am Offset BHeapUserData1
; wird vom Demo als Zähler für die belegten
; Blöcke benutzt
mov w es:BHeapUserData1,0
; Das Benutzerfeld am Offset BHeapUserData2
; wird vom Demo als Zähler für die Anzahl
; der Zeilen der Ausgabe-Datei benutzt
mov w es:BHeapUserData2,0
ret
; ----------------------------
; InitBasedHeapKette
;
; Funktion: Initialisiert die Kette auf dem BasedHeap
;
; Eingabe: ES = Segment des BasedHeaps
;
; Ausgabe: CF = 0 ->> okay, ES = Segment des BasedHeaps
; SI = erster Block
; DI = letzter Block
; CF = 1 ->> Fehler, AX = Fehlernummer
; DX = Offset der Fehlermeldung
; CX = Länge der Fehlermeldung
;
InitBasedHeapKette:
; Dummyblöcke einrichten (vereinfacht die
; Kettenbearbeitung)
mov cx, TYPE (HeapBlock) + 255
call GetBHeapMem
call CheckBasedHeapError
jc ret
mov si,bx ; ES:SI -> erster Dummyblock
mov cx, TYPE (HeapBlock) + 255
call GetBHeapMem
call CheckBasedHeapError
jc ret
mov di,bx ; ES:DI -> zweiter Dummyblock
; 1. Dummyblock füllen
mov es:Previous[si],0
mov es:Next[si],di
mov es:LineLength[si],255
push di
mov di,si
add di,offset Line
mov cx,255
mov al,0
rep stosb
pop di
; 2. Dummyblock füllen
mov es:Previous[di],si
mov es:Next[di],0FFFFh
mov es:LineLength[di],255
push di
add di,offset Line
mov cx,255
mov al,0FFh
rep stosb
pop di
clc
ret
; ----------------------------
; ProceedLines
;
; Funktion: Bearbeitet die Zeilen nach folgendem Schema:
; Zeilen, die mit einem Semikolon beginnen werden entfernt
; und leere Zeilen werden durch die Zeile ';;' ersetzt
;
; Ausgabe: CF = 0 ->> okay
; CF = 1 ->> Fehler, AX = Fehlernummer
; DX = Offset der Fehlermeldung
; CX = Länge der Fehlermeldung
;
ProceedLines:
mov es,w BHeapSeg ; ES = BasedHeap-Segment
; Zu Demo-Zwecken die Zusammenfassung von
; freien Blöcken unterbinden
or b es:BHeapFlags,NoBigFreeBlocks
call GetFirstBHeapBlock
call CheckBasedHeapError
jc ret ; Fehler!
; ES:BX -> 1. Block
mov ds,es ; DS = BasedHeap-Segment
mov si,bx ; DS:SI -> erstes Element = Dummy
mov si,Next[si] ; DS:SI -> erstes reales Element der Kette
; ------------------
ProceedLineLoop:
cmp si,0FFFFh ; auf Ende testen
IF e jmp ProceedLineEnd
; ------------------
cmp LineLength[si],0
jne >l1
; ------------------
; leere Zeilen durch die Zeile ';;' ersetzen
; neuen Block anfordern
mov cx,4+4+1+4
call GetNewBHeapBlock
jc ProceedLineEnd ; Fehler!
; BX -> neuer Block
; Inhalt füllen
mov LineLength[bx],2
mov w Line[bx],';;'
xchg bx,si ; BX -> alter Block
; SI -> neuer Block
push w Previous[bx]
push w Next[bx] ; Zeiger des alten Blocks sichern
; alten Block löschen
call FreeBHeapMem ; und Block freigeben
call CheckBasedHeapError
pop w Next[si] ; Zeiger des neuen Blocks setzen
pop w Previous[si]
jc ProceedLineEnd ; Fehler
inc w BHeapUserData2 ; Zähler erhöhen
mov bx,Previous[si]
mov Next[bx],si ; Vorgänger korrigieren
mov bx,Next[si]
mov Previous[bx],si ; Nachfolger korrigieren
mov si,Next[si] ; SI -> nächster Block
jmp SHORT ProceedLineLoopEnd
; ------------------
l1:
cmp Line[si],';'
jne >l1
; ------------------
; Kommentar-Zeilen löschen
mov bx,si
mov si,Next[bx] ; SI -> nächster Block
call DeleteBlock
jc ProceedLineEnd
jmp SHORT ProceedLineLoopEnd
; ------------------
l1:
; alle anderen Zeilen so übernehmen
inc w BHeapUserData2
mov si,Next[si] ; SI -> nächster Block
; ------------------
ProceedLineLoopEnd:
call LaufZeitAnzeige
jmp ProceedLineLoop
; ------------------
ProceedLineEnd:
mov ds,cs ; DS = CS
pushf
call ShowCR_LF
popf
ret
; ----------------------------
; GetNewBHeapBlock
;
; Funktion: Belegt einen neuen Block auf dem BasedHeap
;
; Eingabe: DS = ES = Segment des BasedHeaps
; CX = Länge für den neuen Block
;
; Ausgabe: CF = 0 ->> okay
; DS:BX -> neuer Block
; CF = 1 ->> Fehler
; DX -> Fehlermeldung
; CX -> Länge der Fehlermeldung
;
GetNewBHeapBlock:
push ds
push bp
mov bp,sp
mov ds,cs
l0:
push cx
call GetBHeapMem ; Speicher anfordern
jnc >l10
; Fehler
cmp ax,BHeapMemoryError
jne >l1
; Fehler 'Kein freier Block mehr vorhanden'
test b es:BHeapFlags,NoBigFreeBlocks
jz >l1 ; nichts mehr zu machen
call ShowBasedHeapData
jc >l10
Write_String CollectMsg
call ChainFreeBHeapBlocks ; freie Blöcke zusammenfassen
jc >l1
call ShowBasedHeapData
jc >l10
and b es:BHeapFlags,BigFreeBlocks
pop cx
jmp l0 ; und neuer Versuch
l1:
call CheckBasedHeapError
l10:
mov sp,bp
pop bp
pop ds
ret
; ----------------------------
; DeleteBlock
;
; Funktion: Löscht einen Block vom BasedHeap
;
; Eingabe: DS:BX -> zu löschender Block
;
; Ausgabe: CF = 0 ->> okay
; CF = 1 ->> Fehler
; DX -> Fehlermeldung
; CX -> Länge der Fehlermeldung
;
DeleteBlock:
push di,si,bx
dec w BHeapUserData1 ; Zähler korrigieren
mov si,Previous[bx] ; SI = Vorgänger
; BX = Block
mov di,Next[bx] ; DI = Nachfolger
; Zeiger korrigieren
mov Next[si],di
mov Previous[di],si
call FreeBHeapMem ; und Block freigeben
call CheckBasedHeapError
DeleteBlockEnd:
pop bx,si,di
ret
; ----------------------------
; WriteHeapElements
;
; Funktion: Ausgabe der Elemente auf dem BasedHeap
; in die Ausgabe-Datei
;
; Ausgabe: CF = 0 ->> okay
; CF = 1 ->> Fehler, AX = Fehlernummer
; DX = Offset der Fehlermeldung
; CX = Länge der Fehlermeldung
; DS = BasedHeap-Segment
;
WriteHeapElements:
mov OutPutFileOff,0 ; Pufferzeiger zurücksetzen
mov es,w BHeapSeg ; ES = BasedHeap-Segment
; Anzahl der Elemente auf dem BasedHeap ausgeben
mov di,offset Lines2Msg
mov ax,es:[BHeapUserData2]
dec ax
push es
mov es,cs ; ES = CS
call Konvert_AX_To_Dezstring
Write_String Lines2Msg
pop es
call GetFirstBHeapBlock
call CheckBasedHeapError
jc ret ; Fehler!
; ES:BX -> akt. Element
mov ds,es ; DS = BasedHeap-Segment
mov si,bx ; DS:SI -> erstes Element = Dummy
mov si,Next[si] ; DS:SI -> erstes reales Element der Kette
xor cx,cx
l00:
cmp Next[si],0FFFFh
je >l9 ; Ende erreicht
lea dx,Line[si] ; DX -> Inhalt
mov cl,LineLength[si] ; CX -> L(Inhalt)
call PutNextLine ; Zeile in den Ausgabe-Puffer übernehmen
mov si,Next[si] ; und nächstes Element
jmp l00
l9: ; und Puffer schreiben
call WriteOutPutFileBuffer
jnc >l1
; Fehler beim Schreiben
mov dx,offset OutputError
mov cx,OutputError_LENGTH
push ax
call OutputMsg
pop ax
stc
l1:
ret
; ----------------------------
; GetNewHeapBlock
;
; Funktion: Belegt einen neuen Block auf dem BasedHeap
;
; Eingabe: Die Zeile steht in LineBuffer
; SI -> Vorgänger
; DI -> Nachfolger
; DS = CS
;
; Ausgabe: CF = 0 ->> okay, SI und DI enthalten die Vorgänger
; und Nachfolger für den nächsten Block
; CF = 1 ->> Fehler, AX = Fehlernummer
; DX = Offset der Fehlermeldung
; CX = Länge der Fehlermeldung
;
GetNewHeapBlock:
; Länge des neuen Blocks berechnen
mov cl,LineBuffer ; CL = Länge der Zeile
xor ch,ch
inc cx
add cx,TYPE (HeapBlock)
cmp cx,5
if b mov cx,5 ; CX = Länge des neuen Blocks
l0:
call GetBHeapMem ; neuen Block anfordern
jc ret
; Zähler für die BasedHeap-Elemente erhöhen
inc w es:[BHeapUserData1]
; Zeiger des Blocks belegen
; SI -> Vorgänger
; BX -> neuer Block
; DI -> Nachfolger
mov ax,es:Next[si] ; AX = Nachfolger des Vorgängers
mov es:Next[bx],ax
mov ax,es:Previous[di] ; AX = Vorgänger des Nachfolgers
mov es:Previous[bx],ax
mov es:Next[si],bx ; Nachfolger des Vorgängers korrigieren
mov es:Previous[di],bx ; Vorgänger des Nachfolgers korrigieren
mov si,bx ; neuen Vorgänger nach SI
mov di,es:Next[bx] ; neuer Nachfolger nach DI
mov cl,LineBuffer ; Blockinhalt belegen
xor ch,ch
inc cx ; CX = Länge der Zeile für den Block
; (incl. Längenzähler)
push di,si
lea di,LineLength[bx]
mov si,offset LineBuffer
rep movsb
pop si,di
clc
ret
; ----------------------------
; OpenInAndOutputFiles
;
; Funktion: Öffnet die Ein- und Ausgabe-Dateien und liest die Eingabe-Datei
;
; Ausgabe: CF = 0 ->> okay
; CF = 1 ->> Fehler
; DX = Offset der Fehlermeldung
; CX = Länge der Fehlermeldung
;
OpenInAndOutputFiles:
mov bx,1000h ; Speicher zum Lesen der Eingabe-Datei anfordern
mov ah,048h ; 1 Segment
int 021h
jnc >l1
; Fehler, nicht genügend Speicher vorhanden
mov dx,offset MemoryError
mov cx,MemoryError_LENGTH
stc
ret
; ------------------
l1:
mov InOutFileSeg,ax ; Segment sichern
mov si,080h ; Parameter bearbeiten
lodsb
or al,al
jnz >l1
; Fehler: Keine Parameter angegeben
ParameterError:
mov dx,offset ParamError
mov cx,ParamError_LENGTH
stc
ret
; ------------------
l1:
call GetFileName ; Anfang des ersten Dateinamens suchen
jc ParameterError
; DS:DX -> erster Dateiname als ASCIIZ-String
; ------------------
mov ax,03D02h ; Eingabe-Datei öffnen
int 021h
jnc >l1
; ------------------
InputFileError:
mov dx,offset IFileError
mov cx,IFileError_LENGTH
stc
ret
; ------------------
l1:
mov InputFileHandle,ax ; Handle der Eingabe-Datei sichern
; ------------------
call GetFileName ; Name der Ausgabe-Datei ermitteln
jc ParameterError
; ------------------
; Ausgabe-Datei anlegen
mov cx,0 ; CX = Standard-Attribte
mov ah,03Ch ; Datei erstellen
int 021h
jnc >l1
; ------------------
OutputFileError:
mov dx,offset OFileError
mov cx,OFileError_LENGTH
stc
ret
; ------------------
l1:
mov OutputFileHandle,ax ; Handle der Ausgabe-Datei sichern
; ------------------
mov ah,03Fh ; und Eingabe-Datei lesen
mov cx,0FFF5h
mov bx,InputFileHandle
lds dx,InputFileOff ; DS <> CS
int 021h
mov ds,cs ; DS = CS
jc InputFileError
cmp ax,cx
jb >l1
; ------------------
InputFileError1:
mov dx,offset IFileError1
mov cx,IFileError1_LENGTH
stc
ret
; ------------------
l1:
mov InputFileLength,ax ; Länge der Datei sichern
clc
ret
; ----------------------------
; GetFileName
;
; Funktion: Ermittelt den nächsten Parameter und konvertiert ihn in
; einen ASCIIZ-String
;
; Eingabe: SI -> Ende des letzte Parameters
;
; Ausgabe: CF = 0 ->> okay, DX -> Anfang des Parameters
; CF = 1 ->> Fehler
;
GetFileName:
l0: ; Anfang des Parameters suchen
lodsb
cmp al,BLANK
je l0
cmp al,TAB
je l0
cmp al,CR
je >l8
; ------------------
lea dx,[si-1] ; Anfang des Parameters gefunden
l1: ; Ende des Parameters suchen
lodsb
cmp al,BLANK
je >l2
cmp al,TAB
je >l2
cmp al,CR
je >l2
jmp l1
l2:
mov b[si-1],0 ; Nullbyte eintragen
clc
ret
; ------------------
l8:
stc
ret
; ----------------------------
; GetNextLine
;
; Funktion: Ermittelt die nächste Zeile der Eingabe-Datei aus dem Puffer
;
; Eingabe: DS = CS
;
; Ausgabe: CF = 0 ->> LineBuffer ist gefüllt
; CF = 1 ->> EOF erreicht
;
GetNextLine:
mov ax,InputFileOff
cmp ax,InputFileLength
jb >l1
stc ; EOF erreicht
ret
l1:
push ds,es,si,di,cx
mov es,cs ; ES = CS
mov di,offset LineBuffer
; ES:DI -> Längenzähler des Zeilenpuffers
xor cx,cx ; CX = Längenzähler
lds si,cs:InputFileOff ; DS:SI -> akt. Position im Puffer
push di
inc di ; ES:DI -> Zeilenpuffer
l0:
cmp cl,255xD ; max. Zeilenlänge erreicht?
je >l1 ; ja
lodsb
cmp al,CR
je >l1 ; Zeilenende erreicht
stosb ; Zeichen übernehmen
inc cx ; Zähler korrigieren
jmp l0
l1:
cmp b[si],LF
if e inc si ; LF am Zeilenende überlesen
pop di
mov es:[di],cl ; Länge der Zeile eintragen
mov cs:InputFileOff,si ; und Pufferzeiger sichern
l9:
clc
pop cx,di,si,es,ds
ret
; ----------------------------
; PutNextLine
;
; Funktion: Übernimmt die nächste Zeile in den Puffer für die Ausgabe-Datei
;
; Eingabe: DS:DX = Zeile
; CX = Länge der Zeile
;
PutNextLine:
push es,si,di,cx
les di,cs:OutputFileOff
; ES:DI -> akt. Stelle im Puffer
; (Test auf Überlauf kann im Demo entfallen)
mov si,dx ; SI -> Zeile
; CX = Anzahl Zeichen
cld
rep movsb
mov ax,0A0Dh ; CR und LF anhängen
stosw
mov cs:OutputFileOff,di
pop cx,di,si,es
ret
; ----------------------------
; WriteOutputFileBuffer
;
; Funktion: Schreibt den Puffer in die Ausgabe-Datei
;
; Ausgabe: CF = 0 ->> okay
; CF = 1 ->> Fehler
; AX = Fehlernummer
;
WriteOutputFileBuffer:
push ds,dx,bx
lds cx,cs:OutputFileOff
xor dx,dx
; DS:DX -> Puffer
; CX = Anzahl Zeichen im Puffer
mov bx,cs:OutputFileHandle
mov ah,040h
int 021h
pop bx,dx,ds
ret
; ----------------------------
; Zeigeanzahl
;
; Funktion: Ausgabe der Anzahl Elemente auf dem BasedHeap
;
; Eingabe: ES = BasedHeap-Segment
;
ZeigeAnzahl:
mov di,offset Lines1Msg
mov ax,es:[BHeapUserData1]
push es
push ds
pop es
call Konvert_AX_To_Dezstring
pop es
Write_String Lines1Msg
ret
; ----------------------------
; ShowBasedHeapData
;
; Funktion: Ausgabe der Daten des BasedHeaps
;
; Bes.: Falls ein Fehler auftritt, wird das Programm beendet.
;
;
DataMsg db 'Daten des BasedHeaps: '
db CR,LF
db 'freier Speicher: '
m2 db '_____, größter freier Block: '
m3 db '_____, ('
m4 db '_____ freie Blöcke)'
db CR,LF
db 'Länge des belegten Teils: '
m5 db '_____'
db CR,LF
db '(Segment: '
m6 db '____h, Länge in Paragraphen: '
m7 db '____h)'
db CR,LF
db CR,LF
GETLENGTH DataMsg
ShowBasedHeapData:
push es,di,ax
mov es,BHeapSeg
mov ax,es
dec ax
mov es,ax
mov ax,es:[03h] ; AX = L(Speicherblock des BasedHeaps)
mov es,cs
mov di,offset m7
call Konvert_AX_To_Hexstring
mov ax,BHeapSeg ; AX = Segment des BasedHeaps
mov di,offset m6
call Konvert_AX_To_Hexstring
mov es,BHeapSeg
call GetBHeapMemAvail
call CheckBasedHeapError
jc >l8
mov es,cs
mov di,offset m4 ; AX = Anzahl freier Blöcke
call Konvert_AX_TO_Dezstring
mov ax,cx ; AX = größter freier Block
mov di,offset m3
call Konvert_AX_To_Dezstring
mov ax,dx ; AX = max. freier Speicher
mov di,offset m2
call Konvert_AX_To_Dezstring
mov es,BHeapSeg
call GetMaxBheapPointer
call CheckBasedHeapError
jc >l8
mov es,cs ; AX = Länge des belegten Teils
mov di,offset m5
call Konvert_AX_To_Dezstring
Write_String DataMsg
clc
l8:
pop ax,di,es
ret
; ----------------------------
; CheckBasedHeapError
;
; Funktion: Ermitteln der zu einer Fehlernummer
; gehörenden Fehlermeldung
;
; Eingabe: AX = Fehlercode der Routine
; CF = CF der Routine
;
; Bes.: Im falle eines Fehler springt die Routine direkt zum
; Label ErrorEnde1
; (mit: DX = Offset der Fehlermeldung
; CX = Länge der Fehlermeldung)
;
; Fehlermeldungen
; ---------------
BasedHeapErrorMsg1 db '*** Verwaltungsstrukturen des BasedHeaps sind defekt!'
BasedHeapErrorMsg2 db '*** Falscher Zeiger angegeben!'
BasedHeapErrorMsg3 db '*** Falscher Zeiger für einen freien Block angegeben!'
BasedHeapErrorMsg4 db '*** Falsche Größe für den BasedHeap angegeben!'
BasedHeapErrorMsg5 db '*** Keine weiteren Blocks vorhanden!'
BasedHeapErrorMsg6 db '*** Freizugebender Block ist schon frei!'
BasedHeapErrorMsg7 db '*** Kein freier Block in der angegebenen Größe mehr vorhanden!'
BasedHeapErrorMsg8 db '*** Reparatur des BasedHeaps gelungen!'
BasedHeapErrorMsgU db '*** DOS-Fehler, Fehlernummer: '
UErrorNumber db '____h'
BasedHeapErrorMsgL db 0 ; Dummy-Eintrag
; Tabelle der Fehlernummern und Fehlermeldungen
; ---------------------------------------------
; Fehlernummern Offset der Fehlermeldung
; -----------------------------------------------
BasedHeapErrorTable dw BHeapFatalError , Offset BasedHeapErrorMsg1
dw BHeapPointerError , Offset BasedHeapErrorMsg2
dw BHeapFPointerError , Offset BasedHeapErrorMsg3
dw BHeapLengthError , Offset BasedHeapErrorMsg4
dw BHeapNoMoreBlocks , Offset BasedHeapErrorMsg5
dw BHeapFreeBlError , Offset BasedHeapErrorMsg6
dw BHeapMemoryError , Offset BasedHeapErrorMsg7
dw BHeapRepaired , Offset BasedHeapErrorMsg8
; Eintrag für unbekannte Fehlercodes
BasedHeapUnknownErr dw 0 , Offset BasedHeapErrorMsgU
; Eintrag für die Ermittlung der Länge
; der letzten Fehlermeldung
dw 0 , Offset BasedHeapErrorMsgL
CheckBasedHeapError:
jnc ret ; CF = 0 ->> kein Fehler aufgetreten
push si,ds,ax ; CF = 1 ->> Fehler aufgetreten,
; Offset der Fehlermeldung ermitteln
mov ds,cs ; DS = CS
mov si,offset BasedHeapErrorTable
; DS:SI -> Fehlertabelle
; Eintrag für unbekannte Fehlercodes korrigieren
mov BasedHeapUnknownErr,ax
push es,di,ax
mov di,offset UErrorNumber
mov es,cs
call Konvert_AX_To_Hexstring
pop ax,di,es
mov dx,ax ; Fehlernummer nach DX
l0:
lodsw
cmp ax,dx
lodsw
jne l0
mov dx,ax ; DX = Offset der Fehlermeldung
mov cx,[si+2] ; CX = Offset der nächsten Fehlermeldung
sub cx,dx ; CX = Länge der Fehlermeldung
stc
pop ax,ds,si
ret