home *** CD-ROM | disk | FTP | other *** search
- ; ----------------------------
- ; 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
-
-