home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Power-Programmierung
/
CD1.mdf
/
assemblr
/
library
/
lib4a86
/
demo
/
mstack.dem
< prev
next >
Wrap
Text File
|
1992-02-16
|
15KB
|
497 lines
; ----------------------------
; MSTACK.DEM - Demoprogramm für die Routinen aus MSTACK.LIB
; (für den A86)
;
; (c) Bernd Schemmer 1992
; Letzter Update: 15.02.1992
;
; Übersetzen:
; A86 MSTACK.DEM DEMOS.INC TO MSTACK.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 'MSTACK.DEM - Demoprogramm für die Routinen aus MSTACK.LIB' ,CR,LF
db '---------------------------------------------------------' ,CR,LF
db 'Das Programm erstellt eine neue Datei in der die Zeilen ' ,CR,LF
db 'der Eingabe-Datei in umgekehrter Reihenfolge stehen.' ,CR,LF
db CR,LF
db 'Das Demo muß folgendermaßen aufgerufen werden:' ,CR,LF
db ' MSTACK.COM eingabedatei ausgabedatei' ,CR,LF
db 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ß'
; Meldungen
MakeMsg ReadMsg, '--- Lese die Eingabe-Datei ...'
MakeMsg InitMsg, '--- Richte den Stack ein ...'
MakeMsg ProceedMsg, '--- Bearbeite die Eingabe-Datei ...'
MakeMsg WriteMsg, '--- Schreibe die Zeilen in die Ausgabe-Datei ...'
MakeMsg Lines1Msg, '_____ Elemente auf dem Stack.'
; Variablen
; Puffer zum Lesen der Zeilen der Eingabe-Datei
LineBuffer db 0,260xD dup 20h
OutputFileHandle dw 0 ; Handle der Ausgabe-Datei
InputFileHandle dw 0 ; Handle der Eingabe-Datei
InputFileLength dw 0 ; Größe der Eingabe-Datei
InputFileOff dw 0 ; Pufferzeiger für die Eingabe-Datei
InputFileSeg dw 0 ; Segment des Speicherblocks zum Lesen der
; Eingabe-Datei
; ----------------------------
start:
call ShowLogoAndAsk ; Logo ausgeben, Speicherblock verkleinern
; und Taste lesen
; ----------------------------
Write_String ReadMsg ; Ein- und Ausgabe-Dateien eröffnen
call OpenInAndOutputFiles
if c jmp ErrorEnde1
; ----------------------------
Write_String InitMsg ; Stack einrichten
; Speicher für den Stack anfordern
mov bx,1000h ; 1 Segment
mov ah,048h
int 021h
jnc >l1 ; 1 Segment kriegen wir nicht,
mov ah,048h ; nehmen wir was wir kriegen können
int 021h
call CheckMStackError
if c jmp ErrorEnde1
l1:
mov es,ax ; ES = Segment des Speicherblocks
mov cx,bx
shl cx,1
shl cx,1
shl cx,1
shl cx,1
or cx,cx
if z mov cx,0FFFFh ; CX = Größe für den Stack in Byte
call InitMStack ; Stack einrichten
call CheckMStackError
if c jmp ErrorEnde1
; ----------------------------
; Zeilen auf den Stack schreiben
Write_String ProceedMsg
call ProceedLines
if c jmp ErrorEnde1
call GetMStackStatistik_A
call CheckMStackError
if c jmp ErrorEnde1
call ZeigeAnzahl
; ----------------------------
; und Zeilen in die Ausgabe-Datei schreiben
Write_String WriteMsg
call WriteLines
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:
call CloseFiles ; Dateien schliessen
EndProcess
; ----------------------------
; ProceedLines
;
; Funktion: Sichert die Zeilen auf den Stack
;
; Ausgabe: CF = 1 ->> okay
; CF = 1 ->> Fehler
; DX -> Fehlermeldung
; CX = Länge der Fehlermeldung
;
ProceedLines:
ProceedLineLoop:
call GetNextLine ; nächste Zeile ermitteln
jc ProceedLineLoopEnd ; Dateiende erreicht
mov si,offset LineBuffer
mov cl,[si]
xor ch,ch ; CX = Länge der Meldung
inc si ; DS:SI -> Meldung
call WriteMStack_A ; Zeile auf den Stack sichern
call CheckMStackError
jc ret
jmp ProceedLineLoop
ProceedLineLoopEnd:
clc
ret
; ----------------------------
; WriteLines
;
; Funktion: Schreibt die Zeilen vom Stack in die Ausgabe-Datei
;
; Ausgabe: CF = 1 ->> okay
; CF = 1 ->> Fehler
; DX -> Fehlermeldung
; CX = Länge der Fehlermeldung
;
WriteLines:
WriteLineLoop:
mov si,offset LineBuffer
mov cx,255xD
; DS:SI -> Puffer
; CX = Länge des Puffers
call ReadMStack_A
call CheckMStackError
jnc >l1
; Fehler aufgetreten
cmp ax,MStackIsEmpty ; erwarteter Fehler?
je WriteLineLoopEnd ; ja, Stack ist leer
jmp >l8 ; nein, raus
l1:
mov dx,si ; DX -> Zeile
; CR und LF anhängen
add si,cx
mov w[si],LF by CR
inc cx
inc cx
; Zeile schreiben
mov bx,OutputFileHandle
mov ah,040h
int 021h
l0:
call CheckMStackError
jnc WriteLineLoop
cmp ax,cx
je WriteLineLoop
mov ax,0FFFFh ; Disk voll, Fehler 0FFFFh simulieren
stc
jmp l0
; Fehler beim Schreiben
l8:
stc
ret
WriteLineLoopEnd:
clc
ret
; ----------------------------
; Zeigeanzahl
;
; Funktion: Ausgabe der Anzahl Elemente auf dem Stack
;
; Eingabe: AX = Anzahl Elemente auf dem Stack
;
ZeigeAnzahl:
push es
push ds
pop es
mov di,offset Lines1Msg
call Konvert_AX_To_Dezstring
pop es
Write_String Lines1Msg
ret
; ----------------------------
; CheckMStackError
;
; Funktion: Ermitteln der zu einer Fehlernummer der Routinen für die
; Verwaltung des Stacks gehörenden Fehlermeldung
;
; Eingabe: AX = Fehlernummer der Routine
; CF = CF der Routine
;
; Ausgabe: CF = 0 ->> kein Fehler
; kein Register verändert
; CF = 1 ->> Fehler
; DX = Offset der Fehlermeldung
; CX = Länge der Fehlermeldung
; AX unverändert
;
; Fehlermeldungen
; ---------------
ErrorMsg1 db '*** Keine weitere Meldung auf dem Stack!'
ErrorMsg2 db '*** Nicht mehr genug freier Speicher auf dem Stack!'
ErrorMsg3 db '*** Falsche Größe für den Stack angegeben!'
ErrorMsg4 db '*** Der Puffer ist für die nächste Meldung zu klein!'
ErrorMsg5 db '*** Die Meldung ist zu lang!'
ErrorMsg6 db '*** Gleichzeitiger Zugriff von mehreren Routinen auf den Stack nicht möglich!'
ErrorMsgU db '*** Unbekannte Fehlernummer: ____h!'
ErrorMsgL db 0 ; Dummy-Eintrag
; Offset für die Ausgabe der Fehlernummer bei
; unbekannten Fehlercodes
ErrorNrMsg EQU (Offset ErrorMsgU + 29)
; Tabelle der Fehlernummern und Fehlermeldungen
; ---------------------------------------------
; Fehlernummern Offset der Fehlermeldung
; -----------------------------------------------
ErrorTable dw MStackIsEmpty , Offset ErrorMsg1
dw MStackIsFull , Offset ErrorMsg2
dw MStackLengthError , Offset ErrorMsg3
dw MStackBufferError , Offset ErrorMsg4
dw MStackMessageError , Offset ErrorMsg5
dw MStackAktivError , Offset ErrorMsg6
; Eintrag für unbekannte Fehlernummern
UnknownErr dw 0 , Offset ErrorMsgU
; Eintrag für die Ermittlung der Länge
; der letzten Fehlermeldung
dw 0 , Offset ErrorMsgL
CheckMStackError:
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 ErrorTable
; DS:SI -> Fehlertabelle
mov UnknownErr,ax ; Eintrag für unbekannte Fehlernummern korrigieren
push ax,di,es
mov es,cs
mov di,ErrorNrMsg
call Konvert_AX_To_Hexstring
pop es,di,ax
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
; ----------------------------
; 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 InputFileSeg,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