home *** CD-ROM | disk | FTP | other *** search
/ Power-Programmierung / CD1.mdf / assemblr / library / lib4a86 / demo / recordio.dem < prev    next >
Text File  |  1992-02-16  |  45KB  |  1,499 lines

  1. ; ----------------------------
  2. ; RECORDIO.DEM - Demoprogramm für die Routinen aus RECORDIO.LIB
  3. ;                (für den A86)
  4. ;
  5. ;                (c) Bernd Schemmer 1992
  6. ;                Letzter Update: 15.02.1992
  7. ;
  8. ; Übersetzen:
  9. ;  A86 RECORDIO.DEM DEMOS.INCIO.COM
  10. ;
  11. ; Hinweis: Die Environment-Variable 'A86' muß den Dateinamen 'MACROS.MAC'
  12. ;          enthalten und die .LIB-Dateien müssen über die Datei A86.LIB
  13. ;          erreichbar sein.
  14. ;
  15. ; ---------------------------
  16.  
  17.          jmp start
  18.  
  19. ; ----------------------------
  20. ; GetSTDInKey (Macro)
  21. ;
  22. ; Funktion: Liest eine Taste von der Standard-Eingabe,
  23. ;           wandelt die Taste in Großbuchstaben um
  24. ;           und schreibt CR und LF auf die Standard-Ausgabe
  25. ;
  26. ; Aufruf:   GetSTDInKey {NoCRLF}
  27. ;
  28. ; Parameter:
  29. ;           NoCRLF  = Kein CR/LF nach dem Lesen der Taste ausgeben
  30. ;
  31. ; Ausgabe:  AL = gedrückte Taste als Großbuchstabe
  32. ;
  33. ;
  34. GetSTDInKey MACRO
  35.          mov ah,01            ; Taste lesen
  36.          int 021h
  37.          or al,al
  38.          jnz >m1
  39.                               ; Funktionstaste
  40.          mov ah,01
  41.          int 021h
  42.          xor al,al
  43. m1:
  44.          and al,0DFh          ; Tasten in Großbuchstaben konvertieren
  45.  
  46. ##IF #NL EQ 0
  47.          call ShowCR_LF
  48. ##ENDIF
  49. #EM
  50.  
  51. ; ----------------------------
  52.                               ; Meldungen und Fehlermeldungen
  53. logo  db CR,LF
  54.       db 'RECORDIO.DEM  - Demoprogramm für die Routinen aus RECORDIO.LIB' ,CR,LF
  55.       db '--------------------------------------------------------------' ,CR,LF
  56.       db CR,LF
  57.       db 'Das Demo erstellt zuerst die Record-Datei RECORDIO.BSP mit'     ,CR,LF
  58.       db 'bis zu 100.000 Sätzen á 32 Byte (Dateilänge: ca. 3,2 Megabyte,' ,CR,LF
  59.       db 'nur falls sie noch nicht existiert bzw. ein falsches Format'    ,CR,LF
  60.       db 'hat) und ermöglicht danach im Dialog das Lesen und Schreiben'   ,CR,LF
  61.       db 'von Sätzen aus der Datei.'                                      ,CR,LF
  62.       db 'Die Datei RECORDIO.BSP wird vom Programm NICHT gelöscht.'       ,CR,LF
  63.       db 'Das Programm setzt temporär den Interrupt 21h um, damit'        ,CR,LF
  64.       db 'wirkliche Zugriffe auf die Datei sichtbar werden.'              ,CR,LF
  65.       db CR,LF,CR,LF
  66.       db 'Bitte eine Taste drücken (ESC = Programm-Abbruch) ...'          ,CR,LF
  67.       db CR,LF
  68. GETLENGTH logo
  69.  
  70. ; ------------------
  71.                               ; Meldungen
  72. MakeMsg  BuildMsg,       'Erstelle die Datei ...'
  73. MakeMsg  MakeOkay, CR,LF,'Datei angelegt.'
  74. MakeMsg  ExistMsg,       'Datei existiert schon.'
  75. MakeMsg  CloseMsg,       'Schließe die Datei ... '
  76. MakeMsg  ReorgMsg,       'ReOrganisiere die Puffer für die Dialog-Bearbeitung ...'
  77. MakeMsg  OpenMsg,        'Öffne die Datei wieder ...'
  78. MakeMsg1 UseMsg,         'Existierende Datei benutzen? (j/n) ==> '
  79.  
  80. ; ------------------
  81.                               ; Variablen
  82.  
  83.                               ; Puffer zum Lesen einer Eingabe von der
  84.                               ; Standard-Eingabe
  85. LineBuffer    db 16,0,20 dup 20h
  86.  
  87. ; ------------------
  88.  
  89.                               ; Satz für die Datei
  90.                               ; ------------------
  91. DateiSatz     dw 0,0          ; Satznummer im binären Format
  92. DateiText1    db 10 dup (20h) ; Nummer des Satzes in Stringform
  93. DateiText2    db '>'
  94.               db 16 dup ('_') ; beliebiger weiterer Text
  95.               db '<'
  96.                               ; Länge eines Satzes
  97. SatzLaenge EQU ($ - Offset DateiSatz)
  98.  
  99. ; ------------------
  100.  
  101. ExtraSeg           dw 0       ; Segment des Speicherblocks für die Puffer
  102. ExtraSegLength     dw 0       ; Länge des Segments
  103.  
  104. ; ------------------
  105.                               ; Name der Datei
  106. DefString bspfile, 0, 'RECORDIO.BSP'
  107.  
  108. ; ------------------
  109.                               ; Beispiel-Header für die Datei
  110.  
  111. FileHeader    db CR,LF, 'RECORDIO.BSP - Record-Datei des Demo-Programms RECORDIO.DEM'
  112.               db CR,LF, '               aus der Sammlung Lib4A86'
  113.               db CR,LF,01Ah
  114. FileHeader_LENGTH EQU $ - Offset FileHeader
  115.  
  116. ; ------------------
  117.  
  118. RecordFileTablePtr dw 04000h  ; Zeiger auf die Datei-Tabelle
  119.  
  120.                               ; Aufbau der Datei-Tabelle
  121.                               ; ------------------------
  122.                               ; Die Felder, die initialisiert werden,
  123.                               ; sind mit einem Asterix (*) markiert
  124. RecordFileTable STRUC
  125.                               ; Datei-Tabelle für die Record-Datei
  126.                               ; ----------------------------------
  127.     RecordFileHandle   dw ?   ; Handle                     (*)
  128.     RecordFileLastRec  dw ?,? ; Offset des letzten Satzes
  129.  
  130.     RecordFileHeaderL  dw ?,? ; Länge des Headers          (*)
  131.  
  132.     RecordFileRecordL  dw ?   ; Länge eines Satzes         (*)
  133.  
  134.     RecordFileFPointer dw ?,?
  135.  
  136.     RecordFileBufferC  dw ?   ; Anzahl Puffer              (*)
  137.  
  138.     RecordFileBufferL  dw ?   ; Länge eines Puffers        (*)
  139.  
  140.     RecordFileFlags    db ?   ; Flags                      (*)
  141.     RecordFileEmpty    db ?   ; Indikator für eine leere Datei
  142. ; ------------------
  143.                               ; Aufbau des ersten Puffer-Records
  144.                               ; --------------------------------
  145.     _1BufferRecordU1   dw ?   ; 1. Puffer-Record ...
  146.     _1BufferRecordOfs  dw ?   ;                            (*)
  147.     _1BufferRecordSeg  dw ?   ;                            (*)
  148.     _1BufferRecordU2   dw ?,?
  149.  
  150. ; ------------------
  151.                               ; Länge eines Puffer-Records
  152. BufferRecordLength EQU $ - Offset _1BufferRecordU1
  153.                 ENDS
  154.  
  155. ; ----------------------------
  156. start:
  157.          call ShowLogoAndAsk  ; Logo ausgeben, Speicherblock verkleinern
  158.                               ; und Taste lesen
  159. ; ----------------------------
  160.                               ; Speicher für die Puffer anfordern
  161.          call GetMemForBuffer
  162.          if c jmp ErrorEnde1
  163.  
  164. ; ----------------------------
  165.                               ; Dateitabelle anlegen
  166.          call InitFileTable
  167.  
  168. ; ------------------
  169.                               ; Interrupt 21h umsetzen
  170.          call SetNewInt21h
  171.  
  172. ; ------------------
  173.                               ; Datei eröffnen (falls möglich)
  174.          mov di,offset BspFile
  175.                               ; ES:DI -> Name der Datei
  176.          mov bx,RecordFileTablePtr
  177.                               ; DS:BX -> Datei-Tabelle
  178.          call ResetRecordFile
  179.          jc ErstelleDatei     ; Datei existiert nicht oder hat ein falsches
  180.                               ; Format
  181.  
  182.                               ; Datei existiert und hat das richtige Format
  183.          Write_String ExistMsg
  184.  
  185.          call ShowFileData    ; Daten der Datei ausgeben
  186.          call CheckRECORDIOError
  187.          if c jmp ErrorEnde1
  188.  
  189.  
  190.          Write_String UseMsg
  191.          mov ah,01
  192.          int 021h
  193.          call ShowCR_LF
  194.          and al,0DFh
  195.          cmp al,'N'
  196.          if ne jmp BenutzeDatei         ; existierende Datei benutzen
  197.  
  198.          mov bx,RecordFileTablePtr
  199.          call CloseRecordFile
  200.          call CheckRECORDIOError
  201.          if c jmp ErrorEnde1
  202.  
  203.  
  204. ; ----------------------------
  205. ErstelleDatei:
  206.          Write_String BuildMsg
  207.  
  208.          mov di,offset BspFile
  209.                               ; ES:DI -> Name der Datei
  210.          mov bx,RecordFileTablePtr
  211.                               ; DS:BX -> Datei-Tabelle
  212.  
  213.                               ; Datei existiert nocht nicht oder hat ein
  214.                               ; falsches Format ->> Datei neu aufbauen oder
  215.                               ; erstellen
  216.          call CreateRecordFile
  217.          call CheckRECORDIOError
  218.          if c jmp ErrorEnde1
  219.  
  220. ; ------------------
  221.          call ShowFileData    ; Daten der Datei ausgeben
  222.          call CheckRECORDIOError
  223.          if c jmp ErrorEnde1
  224.  
  225.          call ShowBufferData  ; Daten der Puffer ausgeben
  226.  
  227. ; ----------------------------
  228.                               ; Header der Datei schreiben
  229.  
  230.          mov di,offset FileHeader
  231.                               ; ES:DI -> File-Header
  232.          mov bx,RecordFileTablePtr
  233.                               ; DS:BX -> Datei-Tabelle
  234.          call WriteRecordFileHeader
  235.          call CheckRECORDIOError
  236.          if c jmp ErrorEnde1
  237.  
  238. ; ----------------------------
  239.                               ; Datei (sequentiell) füllen
  240.          call FillFile
  241.          call CheckRECORDIOError
  242.          if c jmp ErrorEnde1
  243.  
  244.          Write_String MakeOkay
  245.  
  246. ; ------------------
  247. BenutzeDatei:
  248.          call ShowFileData    ; Daten der Datei ausgeben
  249.          call CheckRECORDIOError
  250.          if c jmp ErrorEnde1
  251.          call ShowBufferData  ; Daten der Puffer ausgeben
  252.  
  253. ; ----------------------------
  254.          Write_String CloseMsg
  255.  
  256.                               ; Datei schliessen
  257.          mov bx,RecordFileTablePtr
  258.                               ; DS:BX -> Datei-Tabelle
  259.          call CloseRecordFile
  260.          call CheckRECORDIOError
  261.          if c jmp ErrorEnde1
  262.  
  263. ; ----------------------------
  264.          Write_String ReOrgMsg
  265.                               ; Puffer umorganisieren
  266.          call ReOrgBuffer
  267.  
  268. ; ----------------------------
  269.          Write_String OpenMsg
  270.                               ; Datei wieder eröffnen
  271.          mov di,offset BspFile
  272.                               ; ES:DI -> Name der Datei
  273.          mov bx,RecordFileTablePtr
  274.                               ; DS:BX -> Datei-Tabelle
  275.          call ResetRecordFile
  276.          call CheckRECORDIOError
  277.          if c jmp ErrorEnde1
  278.  
  279.          call ShowFileData    ; Daten der Datei ausgeben
  280.          call CheckRECORDIOError
  281.          if c jmp ErrorEnde1
  282.          call ShowBufferData  ; Daten der Puffer ausgeben
  283.  
  284. ; ----------------------------
  285.                               ; Datei im Dialog bearbeiten
  286.          call DialogMenue
  287.          call CheckRECORDIOError
  288.          if c jmp ErrorEnde1
  289.  
  290. ; ----------------------------
  291.          mov al,0
  292.          jmp SHORT Ende
  293.  
  294. ; ----------------------------
  295.                               ; Fehlerausgang
  296.  
  297.                               ; DX = Offset einer Fehlermeldung
  298.                               ; CX = Länge der Fehlermeldung
  299. ErrorEnde1:
  300.          call ShowCR_LF
  301.          call OutputMsg       ; Fehlermeldung ausgeben
  302.          call ShowCR_LF
  303.  
  304. ; ----------------------------
  305. ErrorEnde:
  306.          mov al,0FFh
  307. ; ------------------
  308. Ende:
  309.          push ax              ; Datei schliessen
  310.          mov bx,RecordFileTablePtr
  311.                               ; DS:BX -> Datei-Tabelle
  312.          call CloseRecordFile
  313.          pop ax
  314.  
  315.          EndProcess
  316.  
  317. ; ----------------------------
  318. ; InitFileTable
  319. ;
  320. ; Funktion: Initialisiert die Datei-Tabelle für das
  321. ;           Anlegen der Datei
  322. ;
  323. InitFileTable:
  324.                               ; Die Dateitabelle wird hinter dem Code
  325.                               ; des Demos angelegt.
  326.          mov bx,RecordFileTablePtr
  327.                               ; DS:BX -> Datei-Tabelle
  328.  
  329.                               ; Felder der Datei-Tabelle initialisieren
  330.          mov RecordFileHandle[bx],0FFFFh
  331.  
  332.          mov RecordFileHeaderL[bx],FileHeader_LENGTH
  333.          mov RecordFileHeaderL[bx+2],0
  334.  
  335.          mov RecordFileRecordL[bx],SatzLaenge
  336.  
  337.          mov RecordFileFlags[bx],0
  338.  
  339.                               ; beim Anlegen arbeiten wir nur mit
  340.                               ; einem großen Puffer
  341.          mov w RecordFileBufferC[bx],1
  342.  
  343.          mov ax,ExtraSegLength
  344.          mov w RecordFileBufferL[bx],ax
  345.  
  346.                               ; Puffer-Record füllen
  347.          mov ax,ExtraSeg
  348.          mov w _1BufferRecordOfs[bx],0
  349.          mov w _1BufferRecordSeg[bx],ax
  350.          ret
  351.  
  352. ; ----------------------------
  353. ; FillFile
  354. ;
  355. ; Funktion: Füllt die Datei sequentiell
  356. ;
  357. ; Ausgabe:  CF = 0 ->> okay
  358. ;           CF = 1 ->> Fehler
  359. ;                      AX = Fehlernummer
  360. ;
  361. FillFileMsg0 db 'Dateierstellung wird fortgesetzt ...'
  362.              db CR,LF
  363. FillFileMsg  db 'Sie können die Erstellung der Datei jederzeit'
  364.              db ' durch einen Tastendruck beenden'
  365.              db CR,LF
  366. GetLength FillFileMsg
  367. GetLength FillFileMsg0
  368.  
  369. MakeMsg1 FillFileAsk, CR,LF,'Datei-Erstellung beenden (j/n)? ==> '
  370.  
  371. MakeMsg1 LaufzeitA, 'Schreibe Satz Nummer 0000000000',CR
  372.  
  373.  
  374. L_MaxSatzLow  EQU [BP-2]      ; lokale Variablen
  375. L_MaxSatzHigh EQU [BP-4]
  376.  
  377. FillFile:
  378.          push bp
  379.          mov bp,sp
  380.  
  381.          mov cx,005F5h
  382.          mov bx,0E100h        ; CX:BX = 100.000 = max. Anzahl Sätze für die Datei
  383.  
  384.          push bx
  385.          push cx              ; lokale Variablen einrichten
  386.  
  387.          Write_String FillFileMsg
  388.  
  389.          xor dx,dx
  390.          xor ax,ax            ; DX:AX = Satzzähler
  391.  
  392. ; ------------------
  393. FillFileLoop:
  394.          mov DateiSatz,ax     ; akt. Satznummer sichern
  395.          mov DateiSatz+2,dx
  396.  
  397. ; ------------------
  398.          mov ah,01h           ; Testen, ob eine Taste gedrückt wurde
  399.          int 016h
  400.          jz >l1               ; keine Taste gedrückt
  401.  
  402. ; ------------------
  403.                               ; Taste gedrückt, fragen ob die Dateierstellung
  404.                               ; beendet werden soll
  405.          Write_String FillFileAsk
  406.          mov ah,00h
  407.          int 016h             ; gedrückte Taste ignorieren
  408.  
  409.          mov ah,00h           ; Taste lesen
  410.          int 016h
  411.          and al,0DFh
  412.  
  413.          cmp al,'J'
  414.          if e jmp FillFileEnd ; Dateierstellung beenden
  415. ; ------------------
  416.                               ; Dateierstellung fortsetzen
  417.          Write_String FillFileMsg0
  418.  
  419. ; ------------------
  420. l1:
  421.                               ; Satz füllen
  422.          mov ax,DateiSatz
  423.          mov dx,DateiSatz+2   ; DX:AX = Satznummer für den nächsten Satz
  424.  
  425.                               ; Zähler im String-Format eintragen
  426.          mov di,offset DateiText1
  427.          call KonvertDXAXToDezstring
  428.  
  429.                               ; und Satz schreiben
  430.          mov di,offset DateiSatz
  431.                               ; ES:DI -> zu schreibender Satz
  432.          mov bx,RecordFileTablePtr
  433.                               ; DS:BX -> Datei-Tabelle
  434.  
  435.          push ax,dx           ; Satznummer sichern
  436.          call WriteRecord
  437.          if c jmp FillFileEnd ; CF = 1 ->> Fehler!
  438.  
  439. ; ------------------
  440.                               ; Laufzeit-Anzeige ausgeben
  441.          mov si,offset LaufZeitA+30
  442.  
  443. l00:                          ; Zähler in der Meldung erhöhen
  444.          mov al,b[si]
  445.          inc al
  446.          cmp al,'9'
  447.          jbe >l1
  448.          mov al,'0'
  449.          mov b[si],al
  450.          dec si
  451.          jmp l00
  452. l1:
  453.          mov b[si],al
  454.  
  455.          mov si,Offset LaufZeitA
  456.          cld
  457. l01:
  458.          lodsb
  459.          int 029h
  460.          cmp al,CR
  461.          jne l01
  462.  
  463. ; ------------------
  464.          pop dx,ax            ; DX:AX = Satznummer
  465.  
  466.          inc ax
  467.          adc dx,0             ; Zähler erhöhen
  468.  
  469.          cmp dx,L_MaxSatzHigh ; auf Schleifenende testen
  470.          jne >l1
  471.          cmp ax,L_MaxSatzLow
  472.          je FillFileEnd
  473. l1:
  474.          jmp FillFileLoop
  475.  
  476. l8:
  477.  
  478. FillFileEnd:
  479.          mov sp,bp
  480.          pop bp
  481.          ret
  482.  
  483. ; ----------------------------
  484. ; ReOrgBuffer
  485. ;
  486. ; Funktion: Reorganisiert die Puffer für die Dateibearbeitung im Dialog
  487. ;           Für die Bearbeitung der Datei im Dialog ist es sinnvoller,
  488. ;           mit mehreren kleinen Puffern zu arbeiten.
  489. ;
  490. ReOrgBuffer:
  491.          mov ax,ExtraSegLength
  492.                               ; mal schauen wieviel Puffer wir anlegen
  493.                               ; können
  494.  
  495.          push ax              ; AX = Länge des Speicherblocks für die Puffer
  496.          xor dx,dx
  497.          mov cx,SatzLaenge*16 ; 16 Sätze/Puffer
  498.                               ; 16 * 32 = 512 (Länge eines Sektors)
  499.          div cx
  500.          mov bx,ax            ; BX = Anzahl Sätze für die im Puffer Platz ist
  501.  
  502.          mov ax,sp
  503.          sub ax,RecordFileTablePtr
  504.                               ; DS:BX -> Datei-Tabelle
  505.  
  506.          sub ax,10000xD       ; AX = Freier Platz für Puffer-Records in
  507.                               ;      diesen Segment
  508.          xor dx,dx
  509.          mov cx,10xD          ; CX = Länge eines Puffer-Records
  510.          div cx               ; AX = Anzahl Puffer-Records für die wir Platz
  511.                               ;      haben
  512.          cmp ax,bx            ;
  513.          if b mov bx,ax       ; BX = Anzahl möglicher Puffer
  514.          cmp bx,250xD
  515.          if a mov bx,250xD    ; max. sind nur 250 Puffer möglich
  516.          pop ax
  517.  
  518.          xor dx,dx            ; DX:AX = Länge des Speicherblocks für die Puffer
  519.          div bx               ; BX = Anzahl Puffer
  520.                               ; AX = Größe eines Puffers
  521.          mov cx,bx            ; CX = Anzahl Puffer
  522.  
  523.                               ; Dateitabelle korrigieren
  524.          mov bx,RecordFileTablePtr
  525.                               ; DS:BX -> Datei-Tabelle
  526.  
  527.                               ; Puffer-Anzahl korrigieren
  528.          mov RecordFileBufferC[bx],cx
  529.                               ; Puffer-Größe korrigieren
  530.          mov RecordFileBufferL[bx],ax
  531.  
  532.                               ; Puffer-Records korrigieren
  533.          xor dx,dx            ; DX = Offset des ersten Puffers
  534.          mov si,ExtraSeg      ; SI = Segment aller Puffer
  535.  
  536.          add bx,offset _1BufferRecordOfs[bx]
  537.                               ; BX = Offset-Feld des ersten Puffer-Records
  538.  
  539. l00:
  540.          mov [bx],dx          ; Offset des Puffers eintragen
  541.          mov [bx+2],si        ; Segment des Puffers eintragen
  542.  
  543.          add dx,ax            ; DX = Offset des nächsten Puffers
  544.  
  545.          add bx,BufferRecordLength
  546.                               ; BX = Offset-Feld des nächsten Puffer-Records
  547.          loop l00
  548.          ret
  549.  
  550. ; ----------------------------
  551. ; DialogMenue
  552. ;
  553. ; Funktion: Bearbeiten der Datei im Dialog
  554. ;
  555. ; Ausgabe:  CF = 0 ->> okay
  556. ;           CF = 1 ->> Fehler
  557. ;                      AX = Fehlernummer
  558. ;
  559.  
  560. DiagMsg  db CR,LF
  561.          db ' -------------------------------- Dialog-Menue --------------------------------'
  562.          db CR,LF
  563.          db ' X = Ende,  S = Statistik anzeigen, F = Puffer schreiben, D = Dateigröße ändern'
  564.          db CR,LF
  565.          db '       W = Write-Through ein/aus, N = nächster Satz, V = vorheriger Satz'
  566.          db CR,LF
  567.          db '                               0 ..n = Datensatz'
  568.          db CR,LF
  569.          db 'Hinweis: Wirkliche Zugriffe auf die Datei werden hier angezeigt.'
  570.          db CR,LF
  571.          db '                                     ┌────────────┴──────────────────────────┐'
  572.          db CR,LF
  573.          db ' ==> '
  574.  
  575. GetLength DiagMsg
  576.  
  577. DiagMsg1 db CR,LF, ' ------------------------------------------------------------------------------'
  578.          db CR,LF
  579. GetLength DiagMsg1
  580.  
  581. MakeMsg  DiagErr,       'Fehlerhafte Datensatz-Nummer eingegeben!'
  582.  
  583. MakeMsg1 NrMsg,         'Nummer des Datensatzes (0..n) ==> '
  584.  
  585. MakeMsg1 NewMsg,        'Datensatz nicht vorhanden, neu anlegen (j/n)? ==> '
  586. MakeMsg1 Update,  CR,LF,'Datensatz ändern (j/n)? ==> '
  587. MakeMsg1 Update1,       'Neuen Inhalt2 für den Datensatz eingeben (max. 16 Zeichen) ',CR,LF,'==> '
  588. MakeMsg  Update2,       'Datensatz geändert bzw. neu angelegt.'
  589. MakeMsg  FlushMsg,      'Puffer geschrieben.'
  590. MakeMsg  WTOnMsg,       'Write-Through eingeschaltet.'
  591. MakeMsg  WTOffMsg,      'Write-Through ausgeschaltet.'
  592. MakeMsg  LengthMsg1,    'Dateigröße korrigiert (falls kein Fehlermeldung angezeigt wurde).'
  593.  
  594. LengthMsg db ' ---- Ändern der Dateigröße ---- '
  595.           db CR,LF
  596.           db 'Anzahl Sätze für die Datei eingeben (CR = keine Änderung)'
  597.           db CR,LF
  598.           db '==> '
  599. GetLength LengthMsg
  600.  
  601. ; ------------------
  602.  
  603. SatzNummer dw 0,0             ; Satznummer des akt. Satzes
  604.  
  605. ; ------------------
  606. DialogMenue:
  607.  
  608. ; ------------------
  609.          Write_String DiagMsg ; Eingabe-Aufforderung ausgeben
  610.  
  611. ; ------------------
  612.          GetSTDInKey NoCRLF   ; Taste lesen
  613.  
  614.          push ax
  615.          Write_String DiagMsg1
  616.          pop ax
  617. ; ------------------
  618.          cmp al,'D'
  619.          jne >l1
  620.                               ; D : Dateigröße ändern
  621. l00:
  622.          Write_String LengthMsg
  623.  
  624.          mov dx,offset LineBuffer
  625.          mov ah,0Ah
  626.          int 021h             ; Anzahl Sätze für die Datei lesen
  627.          call ShowCR_LF
  628.  
  629.          cmp LineBuffer+1,0
  630.          if e jmp DialogMenue
  631.  
  632.          call GetNumber       ; Anzahl Sätze ermitteln
  633.          jnc >l01
  634. ; ------------------
  635.                               ; Fehlerhafte Anzahl angegeben!
  636.          Write_String DiagErr
  637.          jmp l00
  638. l01:
  639.          mov bx,RecordFileTablePtr
  640.          call SetRecordFileSize
  641.          jnc >k2
  642.          push ax
  643.          call CheckRECORDIOError
  644.          pop ax
  645.          jc DiagEnde1
  646. k2:
  647.          Write_String LengthMsg1
  648.          call ShowFileData    ; und neue Daten der Datei ausgeben
  649.          jmp DialogMenue
  650.  
  651. ; ------------------
  652. l1:
  653.          cmp al,'N'
  654.          jne >l1
  655.                               ; N : nächster Datensatz
  656.          mov ax,SatzNummer
  657.          mov dx,SatzNummer+2
  658.          inc ax
  659.          adc dx,0
  660.          jmp DatenSatzAnzeigen
  661. ; ------------------
  662. l1:
  663.          cmp al,'V'
  664.          jne >l1
  665.                               ; V : vorheriger Datensatz
  666.          mov ax,SatzNummer
  667.          mov dx,SatzNummer+2
  668.          push ax
  669.          or ax,dx
  670.          pop ax
  671.          jz >l01              ; kein vorheriger vorhanden
  672.          dec ax
  673.          sbb dx,0
  674. l01:
  675.          jmp DatenSatzAnzeigen
  676.  
  677. ; ------------------
  678. l1:
  679.          cmp al,'S'
  680.          jne >l1
  681.                               ; S : globale Daten ausgeben
  682.          call ShowFileData
  683.          pushf
  684.          call ShowBufferData
  685.          popf
  686.          jnc >k1
  687.          push ax
  688.          call CheckRECORDIOError
  689.          pop ax
  690.          jc DiagEnde1
  691. k1:
  692.          jmp DialogMenue
  693.  
  694. DiagEnde1:
  695.          jmp DiagEnde         ; Fehler!
  696. ; ------------------
  697. l1:
  698.          cmp al,'F'
  699.          jne >l1
  700.                               ; F : Puffer schreiben
  701.          mov bx,RecordFileTablePtr
  702.          call FlushRecordFile
  703.          jnc >k1
  704.          push ax
  705.          call CheckRECORDIOError
  706.          pop ax
  707.          jc DiagEnde1
  708. k1:
  709.  
  710.          mov dx,offset FlushMsg
  711.          mov cx,FlushMsg_LENGTH
  712.  
  713. DialogMenue1:
  714.          call OutputMsg       ; Meldung ausgeben
  715.          jmp DialogMenue
  716.  
  717. ; ------------------
  718. l1:
  719.          cmp al,'W'
  720.          jne >l1
  721.                               ; W : WriteThrough umschalten
  722.          mov bx,RecordFileTablePtr
  723.          xor RecordFileFlags[bx],RF_WriteThrough
  724.  
  725.          mov dx,offset WTOnMsg
  726.          test RecordFileFlags[bx],RF_WriteThrough
  727.          if z mov dx,offset WTOffMsg
  728.  
  729.          mov cx,WTOnMsg_Length
  730.          jmp DialogMenue1
  731.  
  732. ; ------------------
  733. l1:
  734.          cmp al,'X'
  735.          jne NummerEingegeben
  736.                               ; X : Ende
  737.          jmp DiagEnde
  738.  
  739. ; ------------------
  740.                               ; sonst: Datensatz-Nummer
  741. NummerEingegeben:
  742.          Write_String NrMsg
  743.          mov dx,offset LineBuffer
  744.          mov ah,0Ah
  745.          int 021h             ; Nummer für den Datensatz lesen
  746.          call ShowCR_LF
  747.  
  748.          cmp LineBuffer+1,0
  749.          if e jmp DialogMenue
  750.  
  751.          call GetNumber       ; Nummer des Satzes ermitteln
  752.          jnc DatenSatzAnzeigen
  753. ; ------------------
  754.                               ; Fehlerhafte Nummer angegeben!
  755.          Write_String DiagErr
  756.          jmp DialogMenue
  757.  
  758. ; ------------------
  759. DatenSatzAnzeigen:
  760.                               ; DX:AX = Nummer des Datensatzes
  761.          mov SatzNummer,ax    ; Satznummer sichern
  762.          mov SatzNummer+2,dx
  763.  
  764.          mov bx,RecordFileTablePtr
  765.                               ; DS:BX -> Datei-Tabelle
  766.          call TestRecord      ; Testen, ob der Satz existiert
  767.          jnc >l1
  768.          jmp DiagEnde
  769. l1:
  770.          jnz >l1              ; Satz existiert
  771.  
  772. ; ------------------
  773.                               ; Datensatz existiert nicht
  774.  
  775.          Write_String NewMsg  ; Fragen, ob der Datensatz angelegt werden soll
  776.  
  777.          GetSTDInKey          ; Taste lesen
  778.  
  779.          cmp al,'J'
  780.          if ne jmp DialogMenue  ; Satz soll nicht angelegt werden
  781.  
  782. ; ------------------
  783.                               ; Datensatz anlegen
  784.  
  785.                               ; Datei evtl. mit leeren Sätzen auffüllen
  786.          call InsertEmptyRecords
  787.          if c jmp DiagEnde
  788.          jmp >l2              ; und neuen Satz anlegen
  789.  
  790. ; ------------------
  791. l1:
  792.                               ; Satz lesen
  793.          mov di,offset DateiSatz
  794.                               ; ES:DI -> Puffer für den Satz
  795.          mov bx,RecordFileTablePtr
  796.                               ; DS:BX -> Datei-Tabelle
  797.          call ReadRecord
  798.          jnc >k1
  799.          push ax
  800.          call CheckRECORDIOError
  801.          pop ax
  802.          if c jmp DiagEnde
  803. k1:
  804.  
  805.          call ShowDatenSatz   ; Satz anzeigen
  806.  
  807. ; ------------------
  808.                               ; Fragen, ob der Satz geändert werden soll
  809.          Write_String Update
  810.  
  811.          GetSTDInKey          ; Taste lesen
  812.          cmp al,'J'
  813.          if ne jmp DialogMenue  ; Satz soll nicht geändert werden
  814.  
  815. ; ------------------
  816. l2:
  817.                               ; Satz soll geändert werden
  818.          Write_String update1
  819.  
  820.                               ; neuen Inhalt für den Satz lesen
  821.          mov dx,offset LineBuffer
  822.          mov ah,0Ah
  823.          int 021h
  824.                               ; neuen Inhalt in den Satz übertragen
  825.          mov si,offset LineBuffer+2
  826.          mov di,offset DateiText2+1
  827.          mov cl,LineBuffer+1
  828.          xor ch,ch
  829.          push cx
  830.          rep movsb
  831.          pop ax
  832.  
  833.          mov cx,16            ; Mit Blanks auffüllen
  834.          sub cx,ax
  835.          mov al,' '
  836.          rep stosb
  837.                               ; und Satz schreiben
  838.          mov ax,SatzNummer
  839.          mov dx,SatzNummer+2
  840.  
  841.          mov di,offset DateiSatz
  842.  
  843.          push di
  844.          mov w[di],ax
  845.          mov w[di+2],dx
  846.          mov di,offset DateiText1
  847.          call KonvertDXAXToDezString
  848.          pop di
  849.                               ; ES:DI -> zu schreibender Satz
  850.          mov bx,RecordFileTablePtr
  851.                               ; DS:BX -> Datei-Tabelle
  852.          call WriteRecord
  853.          jnc >k1
  854.          push ax
  855.          call CheckRECORDIOError
  856.          pop ax
  857.          if c jmp DiagEnde
  858. k1:
  859.  
  860.          Write_String Update2
  861.          jmp DialogMenue
  862.  
  863. ; ------------------
  864.  
  865. DiagEnde:
  866.          ret
  867.  
  868. ; ----------------------------
  869. ; InsertEmptyRecords
  870. ;
  871. ; Funktion: Schreibt leere Sätze zwischen den letzten belegten
  872. ;           Satz und den neuen Satz
  873. ;
  874. ; Ausgabe:  CF = 0 ->> okay
  875. ;           CF = 1 ->> Fehler
  876. ;                      AX = Fehlernummer
  877. ;
  878. ; Bes.:     Während des Auffüllens wird das Ignore-LRU-Bit
  879. ;           gesetzt, damit immer nur ein Puffer überschrieben
  880. ;           wird und die Inhalt der anderen Puffer erhalten
  881. ;           bleiben.
  882. ;
  883.                               ; Leerer Satz für die Datei
  884.                               ; ------------------
  885. LeererSatz    dw 0,0          ; Satznummer im binären Format
  886. LeererText1   db 10 dup (20h) ; Nummer des Satzes in Stringform
  887. LeererText2   db '?'
  888.               db 16 dup ('-') ; beliebiger weiterer Text
  889.               db '?'
  890.  
  891. MakeMsg1 InsertMsg,        'Fülle die Datei mit leeren Datensätzen auf ... '
  892. MakeMsg  InsertMsg1, CR,LF,'__________ leere Datensätze geschrieben.',CR,LF
  893.  
  894. EmptyRecords dw 0,0           ; Anzahl der leeren Sätze
  895.  
  896. InsertEmptyRecords:
  897.          Write_String InsertMsg
  898.  
  899.          mov EmptyRecords,0   ; Zähler für die leeren Sätze auf 0 setzen
  900.          mov EmptyRecords+2,0
  901.  
  902.          mov bx,RecordFileTablePtr
  903.                               ; DS:BX -> Datei-Tabelle
  904.  
  905.                               ; Ignore LRU-Bit setzen
  906.          or RecordFileFlags[bx],RF_IgnoreLRU
  907.  
  908.                               ; Anzahl Sätze in der Datei ermitteln
  909.          call GetRecordFileSize
  910.          jc >l8
  911.                               ; CX:BX = Anzahl Sätze in der Datei
  912.          mov ax,bx
  913.          mov dx,cx            ; DX:AX = Anzahl Sätze in der Datei
  914.                               ;       = Nummer des nächsten Satzes
  915. l00:
  916.          mov bx,SatzNummer
  917.          mov cx,SatzNummer+2  ; CX:BX = Nummer des neuen Satzes
  918.  
  919.          cmp dx,cx            ; neuen Satz erreicht?
  920.          jb >l1
  921.          ja >l9
  922.          cmp ax,bx
  923.          jae >l9              ; ja, fertig
  924.  
  925. l1:
  926.                               ; nein, leeren Satz schreiben
  927.          mov LeererSatz,ax
  928.          mov LeererSatz+2,dx
  929.  
  930.          mov di,offset LeererText1
  931.          call KonvertDXAXToDezString
  932.  
  933.          mov di,offset LeererSatz
  934.                               ; ES:DI -> zu schreibender Satz
  935.          mov bx,RecordFileTablePtr
  936.                               ; DS:BX -> Datei-Tabelle
  937.          call WriteRecord
  938.          jnc >k1
  939.          push ax
  940.          call CheckRECORDIOError
  941.          pop ax
  942.          jc >l8
  943. k1:
  944.  
  945.          push ax              ; Laufzeit-Anzeige ausgeben
  946.          mov al,'.'
  947.          int 029h
  948.          pop ax
  949.  
  950.          inc EmptyRecords     ; Anzahl der leeren Sätze erhöhen
  951.          adc EmptyRecords+2,0
  952.  
  953.          inc ax
  954.          adc dx,0             ; Satzzähler erhöhen
  955.          jmp l00
  956. l9:
  957.          mov bx,RecordFileTablePtr
  958.                               ; DS:BX -> Datei-Tabelle
  959.  
  960.                               ; Ignore LRU-Bit löschen
  961.          and RecordFileFlags[bx], RF_DontIgnoreLRU
  962.  
  963.                               ; Anzahl der geschriebenen leeren Sätze ausgeben
  964.          mov di,offset InsertMsg1+2
  965.          mov ax,EmptyRecords
  966.          mov dx,EmptyRecords+2
  967.          call KonvertDXAXToDezString
  968.          Write_String InsertMsg1
  969.          clc
  970. l8:
  971.          ret
  972.  
  973. ; ----------------------------
  974. ; GetNumber
  975. ;
  976. ; Funktion: Ermittelt die eingegebene Satznummer
  977. ;
  978. ; Ausgabe:  CF = 0 ->> okay
  979. ;                      DX:AX = Satznummer
  980. ;           CF = 1 ->> Fehler
  981. ;
  982. GetNumber:
  983.          mov si,offset LineBuffer+2
  984.          mov cl,LineBuffer+1
  985.          xor ch,ch            ; CX = Anzahl Stellen
  986.  
  987.          xor dx,dx
  988.          xor ax,ax            ; Satznummer initialisieren
  989.  
  990.          xor bh,bh
  991. l00:
  992.          mov bl,[si]
  993.          inc si               ; BL = akt. Zeichen
  994.  
  995.          cmp bl,'.'           ; Punkte überlesen
  996.          je >l01
  997.  
  998.          sub bl,'0'
  999.          cmp bl,9
  1000.          ja >L8               ; Fehler!
  1001.  
  1002.          push bx,cx
  1003.          mov bx,10xD          ; alter_Wert = Alter_Wert * 10xD
  1004.          mov cx,0
  1005.          call MulLongInt
  1006.          pop cx,bx
  1007.  
  1008.          add ax,bx            ; und neue Ziffer auf den Wert aufaddieren
  1009.          adc dx,0
  1010. l01:
  1011.          loop l00
  1012.  
  1013.          clc
  1014.          ret
  1015.  
  1016. l8:
  1017.          stc
  1018.          ret
  1019.  
  1020. ; ----------------------------
  1021. ; ShowDatenSatz
  1022. ;
  1023. ; Funktion: Ausgabe des Inhaltes des akt. Datensatzes
  1024. ;
  1025. SatzMsg  db 'Inhalt des Datensatzes: '
  1026.          db                         'Interner Satzzähler: '
  1027. SatzMsg1 db                                              '________h, Inhalt: '
  1028.          db CR,LF
  1029.          db '                        Inhalt1: '
  1030. GetLength SatzMSG
  1031.  
  1032. SatzMsg2 db CR,LF
  1033.          db '                        Inhalt2: '
  1034. GetLength SatzMsg2
  1035.  
  1036. ShowDatensatz:
  1037.          mov di,offset SatzMsg1
  1038.          mov ax,DateiSatz+2
  1039.          call Konvert_AX_To_Hexstring
  1040.          mov ax,DateiSatz
  1041.          call Konvert_AX_To_Hexstring
  1042.  
  1043.          Write_String SatzMsg
  1044.  
  1045.          mov dx,offset DateiText1
  1046.          mov cx,10xD
  1047.          call OutPutMsg
  1048.  
  1049.          Write_String SatzMsg2
  1050.  
  1051.          mov dx,offset DateiText2
  1052.          mov cx,18xD
  1053.          call OutPutMsg
  1054.  
  1055.          call ShowCR_LF
  1056.          ret
  1057.  
  1058. ; ----------------------------
  1059. ; ShowFileData
  1060. ;
  1061. ; Funktion: Ausgabe der globalen Daten der Datei
  1062. ;
  1063. ; Ausgabe:  CF = 0 ->> okay
  1064. ;           CF = 1 ->> Fehler
  1065. ;                      AX = Fehlernummer
  1066. ;
  1067. GlobalData db '-Dateistatus-  Die Datei belegt '
  1068. m1         db                                 '__________ Byte Speicher ',CR,LF
  1069.            db '               und besteht aus  '
  1070. m2         db                                 '__________ Sätzen',CR,LF
  1071. GETLENGTH GlobalData
  1072.  
  1073. ShowFileData:
  1074.          mov bx,RecordFileTablePtr
  1075.                               ; DS:BX -> Datei-Tabelle
  1076.          call GetRecordFileSize
  1077.          jc ret
  1078.          mov di,offset m1
  1079.          call KonvertDXAXToDezString
  1080.          mov dx,cx
  1081.          mov ax,bx
  1082.          mov di,offset m2
  1083.          call KonvertDXAXToDezString
  1084.  
  1085.          Write_String GLobalData
  1086.          clc
  1087.          ret
  1088.  
  1089. ; ----------------------------
  1090. ; ShowBufferData
  1091. ;
  1092. ; Funktion: Ausgabe der Anzahl und Größe der Puffer
  1093. ;
  1094. BufferMsg  db '-Pufferstatus- Benutze               '
  1095. m1         db                                      '_____ Puffer á '
  1096. m2         db                                                     '_____ Byte'
  1097.            db CR,LF
  1098.            db '                                           (-> '
  1099. m3         db                                                '_____ Sätze/Puffer)'
  1100.            db CR,LF
  1101. GetLength BufferMsg
  1102.  
  1103. BufMsg1   db  '               Write-Through ist eingeschaltet.'
  1104.           db CR,LF
  1105. GetLength BufMsg1
  1106.  
  1107. BufMsg2   db  '               Write-Through ist ausgeschaltet.'
  1108.           db CR,LF
  1109. GetLength BufMsg2
  1110.  
  1111. ShowBufferData:
  1112.          mov bx,RecordFileTablePtr
  1113.                               ; DS:BX -> Datei-Tabelle
  1114.  
  1115.          mov di,offset m1
  1116.          mov ax,RecordFileBufferC[bx]
  1117.                               ; AX = Anzahl der Puffer
  1118.          call Konvert_AX_To_Dezstring
  1119.  
  1120.          mov di,offset m2
  1121.          mov ax,RecordFileBufferL[bx]
  1122.                               ; AX = Länge eines Puffers
  1123.          push ax
  1124.          call Konvert_AX_To_Dezstring
  1125.          pop ax
  1126.  
  1127.          mov cx,RecordFileRecordL[bx]
  1128.                               ; CX = Länge eines Satzes
  1129.          xor dx,dx
  1130.          div cx               ; AX = Anzahl Sätze pro Puffer
  1131.          mov di,offset m3
  1132.          call Konvert_AX_To_Dezstring
  1133.  
  1134.          Write_String BufferMsg
  1135.  
  1136.          mov dx,offset BufMsg1
  1137.          test RecordFileFlags[bx],RF_WriteThrough
  1138.          if z mov dx,offset BufMsg2
  1139.  
  1140.          mov cx,BufMsg1_LENGTH
  1141.          call OutputMsg
  1142.  
  1143.          ret
  1144.  
  1145. ; ----------------------------
  1146. ; CheckRECORDIOError
  1147. ;
  1148. ; Funktion: Ermitteln der zu einer Fehlernummer der Routinen
  1149. ;           gehörenden Fehlermeldung
  1150. ;
  1151. ; Eingabe:  AX = Fehlernummer der Routine
  1152. ;           CF = CF der Routine
  1153. ;
  1154. ; Ausgabe:  CF = 0 ->> kein Fehler
  1155. ;                      kein Register verändert
  1156. ;           CF = 1 ->> Fehler
  1157. ;                      DX = Offset der Fehlermeldung
  1158. ;                      CX = Länge der Fehlermeldung
  1159. ;                      AX unverändert
  1160. ;
  1161. ;
  1162.  
  1163. MakeMsg1 ErrorAsk, CR,LF, 'Programm abbrechen? ==> '
  1164.  
  1165. ; Fehlermeldungen
  1166. ; ---------------
  1167. ; Die Fehlermeldunge, die nicht mit einem '*'  beginnen, führen NICHT
  1168. ; zum Programm-Ende
  1169. ;
  1170.          ErrorMsg1 db '*** Fehler: Datei-Tabelle ist fehlerhaft'
  1171.          ErrorMsg2 db '*** Fehler: Datei ist geschlossen'
  1172.          ErrorMsg3 db '*** Fehler: Datei ist noch offen'
  1173.          ErrorMsg4 db '+++ Fehler: Lesefehler, unerwartetes Dateiende'
  1174.          ErrorMsg5 db '+++ Fehler: Schreibfehler, Disk ist voll'
  1175.          ErrorMsg6 db '+++ Fehler: Falsche Satznummer angegeben'
  1176.          ErrorMsg7 db '*** Fehler: Die Datei hat eine falsche Länge'
  1177.          ErrorMsg8 db '*** Fehler: Geräte können mit diesen Routinen nicht verwaltet werden!'
  1178.          ErrorMsg9 db '*** Fehler: Falsche Länge für den Header angegeben'
  1179.  
  1180.          ErrorMsgA db '*** Zuwenig freier Speicher'
  1181.  
  1182.          ErrorMsgU db '*** Unbekannte Fehlernummer: ____h!'
  1183.          ErrorMsgL db 0       ; Dummy-Eintrag
  1184.  
  1185.                               ; Offset für die Ausgabe der Fehlernummer bei
  1186.                               ; unbekannten Fehlercodes
  1187. ErrorNrMsg EQU (Offset ErrorMsgU + 29)
  1188.  
  1189. ; Tabelle der Fehlernummern und Fehlermeldungen
  1190. ; ---------------------------------------------
  1191.  
  1192.                ; Fehlernummern         Offset der Fehlermeldung
  1193.                ; -----------------------------------------------
  1194. ErrorTable    dw RFileTableError     , Offset ErrorMsg1
  1195.               dw RFileNotOpen        , Offset ErrorMsg2
  1196.               dw RFileAlreadyOpen    , Offset ErrorMsg3
  1197.               dw RFileReadError      , Offset ErrorMsg4
  1198.               dw RFileWriteError     , Offset ErrorMsg5
  1199.               dw RFileRecordError    , Offset ErrorMsg6
  1200.               dw RFileLengthError    , Offset ErrorMsg7
  1201.               dw RFileDeviceError    , Offset ErrorMsg8
  1202.               dw RFileHeaderError    , Offset ErrorMsg9
  1203.  
  1204.               dw 08h                 , Offset ErrorMsgA
  1205.                         ; Eintrag für unbekannte Fehlernummern
  1206. UnknownErr    dw 0                   , Offset ErrorMsgU
  1207.                         ; Eintrag für die Ermittlung der Länge
  1208.                         ; der letzten Fehlermeldung
  1209.               dw 0                   , Offset ErrorMsgL
  1210.  
  1211. CheckRECORDIOError:
  1212.          jnc ret              ; CF = 0 ->> kein Fehler aufgetreten
  1213.  
  1214.          push si,ds,ax        ; CF = 1 ->> Fehler aufgetreten,
  1215.                               ;            Offset der Fehlermeldung ermitteln
  1216.          mov ds,cs            ; DS = CS
  1217.          mov si,offset ErrorTable
  1218.                               ; DS:SI -> Fehlertabelle
  1219.  
  1220.          mov UnknownErr,ax    ; Eintrag für unbekannte Fehlernummern
  1221.                               ; korrigieren
  1222.  
  1223.          push ax,di,es
  1224.          mov es,cs
  1225.          mov di,ErrorNrMsg
  1226.          call Konvert_AX_To_Hexstring
  1227.          pop es,di,ax
  1228.  
  1229.          mov dx,ax            ; Fehlernummer nach DX
  1230. l0:
  1231.          lodsw
  1232.          cmp ax,dx
  1233.          lodsw
  1234.          jne l0
  1235.  
  1236.          mov dx,ax            ; DX = Offset der Fehlermeldung
  1237.          mov cx,[si+2]        ; CX = Offset der nächsten Fehlermeldung
  1238.          sub cx,dx            ; CX = Länge der Fehlermeldung
  1239.  
  1240.          mov si,dx
  1241.          cmp b[si],'*'
  1242.          stc
  1243.          je >l1               ; Programm-Abbruch
  1244.  
  1245.          call OutputMsg       ; Nur Fehlermeldung ausgeben, kein Programm-Abbruch
  1246.  
  1247.          mov dx,offset ErrorAsk
  1248.          mov cx,ErrorAsk_LENGTH
  1249.          call OutputMsg
  1250.          GetSTDInKey
  1251.          cmp al,'J'
  1252.          stc
  1253.          je >l1
  1254.          clc
  1255. l1:
  1256.          pop ax,ds,si
  1257.          ret
  1258.  
  1259. ; ----------------------------
  1260. ; KonvertDXAXToDezstring
  1261. ;
  1262. ; Funktion: Konvertiert (vorzeichenlos) DX:AX zu einem Dezimal-String bei ES:DI
  1263. ;
  1264. ; Eingabe:  DX:AX = zu konvertierender Wert
  1265. ;
  1266. ; Ausgabe:  Dezstring bei ES:DI
  1267. ;
  1268. k1       db 0
  1269.  
  1270. k0:
  1271.          call DivLongInt
  1272.          cmp al,0
  1273.          jne >k01
  1274.          cmp k1,al
  1275.          jne >k01
  1276.          mov al,' '
  1277.          jmp >k02
  1278. k01:
  1279.          add al,'0'
  1280.          mov k1,al
  1281. k02:
  1282.          stosb
  1283.  
  1284.          mov dx,cx            ; Rest nach DX:AX
  1285.          mov ax,bx
  1286.          ret
  1287.  
  1288. KonvertDXAXToDezstring:
  1289.          push ax,bx,cx,dx
  1290.          mov k1,0
  1291.  
  1292.          mov cx,03B9Ah
  1293.          mov bx,0CA00h        ; CX:BX = 1.000.000.000
  1294.          call K0
  1295.  
  1296.          mov cx, 05F5h
  1297.          mov bx,0e100h        ; CX:BX =   100.000.000
  1298.          call K0
  1299.  
  1300.          mov cx, 0098h
  1301.          mov bx,09680h        ; CX:BX =    10.000.000
  1302.          call K0
  1303.  
  1304.          mov cx,   0Fh
  1305.          mov bx,04240h        ; CX:BX =     1.000.000
  1306.          call K0
  1307.  
  1308.          mov cx,   01h
  1309.          mov bx,086A0h        ; CX:BX =       100.000
  1310.          call K0
  1311.  
  1312.          mov cx,    0h
  1313.          mov bx,02710h        ; CX:BX =        10.000
  1314.          call K0
  1315.  
  1316.          mov cx,    0h
  1317.          mov bx,003E8h        ; CX:BX =         1.000
  1318.          call K0
  1319.  
  1320.          mov cx,    0h
  1321.          mov bx,00064h        ; CX:BX =           100
  1322.          call K0
  1323.  
  1324.          mov cx,    0h
  1325.          mov bx,0000Ah        ; CX:BX =            10
  1326.          call K0
  1327.  
  1328.          mov al,bl
  1329.          add al,'0'
  1330.          stosb
  1331.  
  1332.          pop dx,cx,bx,ax
  1333.          ret
  1334.  
  1335. ; ----------------------------
  1336. ; GetMemForBuffer
  1337. ;
  1338. ; Funktion: Allociert den Speicher für die Puffer
  1339. ;
  1340. ; Ausgabe:  CF = 0 ->> Okay
  1341. ;           CF = 1 ->> Fehler
  1342. ;                      AX = Fehlernummer
  1343. ;
  1344. GetMemForBuffer:
  1345.          mov bx,1000h         ; 1 Segment möchten wir ...
  1346.          mov ah,048h
  1347.          int 021h
  1348.          jnc >l1
  1349.                               ; 1 Segment kriegen wir nicht, nehmen wir
  1350.          mov ah,048h          ; also was wir kriegen können
  1351.          int 021h
  1352.          jc >l0               ; immer noch Fehler
  1353.          cmp ax,512           ; 512 Byte sollten es aber schon sein
  1354.          ja >l1
  1355.          stc                  ; 512 Byte gibt's auch nicht, also Ende
  1356.          mov ax,08h           ; 08h = Zu wenig Speicher
  1357. l0:
  1358.          ret
  1359.  
  1360. l1:
  1361.          mov ExtraSeg,ax
  1362.          shl bx,1
  1363.          shl bx,1
  1364.          shl bx,1
  1365.          shl bx,1
  1366.          or bx,bx
  1367.          if z dec bx
  1368.          mov ExtraSegLength,bx
  1369.          clc
  1370.          ret
  1371.  
  1372. ; ----------------------------
  1373. ; SetNewInt21h
  1374. ;
  1375. ; Funktion: Speichern des alten Interrupt 21h und umsetzen des
  1376. ;           Interrupt 21h auf unsere Routine
  1377. ;
  1378. SetNewInt21h:
  1379.          mov ax,03521h
  1380.          int 021h
  1381.          mov OldInt21h,bx
  1382.          mov OldInt21h+2,es
  1383.          push cs
  1384.          pop es
  1385.          mov dx,offset NewInt21h
  1386.          mov ax,02521h
  1387.          int 021h
  1388.          ret
  1389.  
  1390. ; ----------------------------
  1391. ; NewInt21h
  1392. ;
  1393. ; Funktion: Neuer Interrupt-Handler für den Interrupt 21h
  1394. ;           Gibt vor dem Ausführen der Funktionen 40h und 3Fh
  1395. ;           mit dem Handle der Record-Datei eine Meldung aus
  1396. ;           und setzt vor dem Ausführen der Funktion 00h oder
  1397. ;           4Ch den Interrupt 21h zurück.
  1398. ;
  1399. ;           Der Handler wird während der Dateibearbeitung
  1400. ;           eingebunden, so daß erkennbar ist, wann die
  1401. ;           Pufferverwaltung wirklich auf die Datei zugreifen muß.
  1402. ;
  1403. Int21ReadMsg  db CR,LF
  1404.               db '                                     ┌───────────────────────────────────────┐ '
  1405.               db CR,LF
  1406.               db '                                     │ ---- Lese aus der Datei ...     ----- │ '
  1407.               db CR,LF
  1408.               db '                                     └───────────────────────────────────────┘ '
  1409.               db CR,LF
  1410. GetLength Int21ReadMsg
  1411.  
  1412. Int21WriteMsg db CR,LF
  1413.               db '                                     ┌───────────────────────────────────────┐ '
  1414.               db CR,LF
  1415.               db '                                     │ ---- Schreibe in die Datei ...  ----- │ '
  1416.               db CR,LF
  1417.               db '                                     └───────────────────────────────────────┘ '
  1418.               db CR,LF
  1419. GetLength Int21WriteMsg
  1420.  
  1421. Int21SizeMsg  db CR,LF
  1422.               db '                                     ┌───────────────────────────────────────┐ '
  1423.               db CR,LF
  1424.               db '                                     │ ---- Ändere die Dateigröße ...  ----- │ '
  1425.               db CR,LF
  1426.               db '                                     └───────────────────────────────────────┘ '
  1427.               db CR,LF
  1428. GetLength Int21SizeMsg
  1429.  
  1430. Int21Msg_LENGTH EQU Int21SizeMsg_LENGTH
  1431.  
  1432. OldInt21h dw ?,?              ; Adresse der alten Routine
  1433.  
  1434. NewInt21h:
  1435.          pushf
  1436.          cmp ah,040h
  1437.          je Func40_3f
  1438.          cmp ah,03Fh
  1439.          je Func40_3f
  1440.          cmp ah,04Ch
  1441.          je Func00_4c
  1442.          cmp ah,00h
  1443.          je Func00_4c
  1444.  
  1445. Int21Through:                 ; Weiter zur alten Routine
  1446.          popf
  1447.          jmp dword ptr cs:OldInt21h
  1448.  
  1449. Func00_4c:
  1450.          push ax,bx,cx,dx     ; Funktion 00h und 4Ch: Zuerst den
  1451.                               ; Interrupt 21h zurücksetzen
  1452.          push ds
  1453.          lds dx,cs:OldInt21h
  1454.          mov ax,02521h
  1455.          int 021h
  1456.          pop ds
  1457.          pop dx,cx,bx,ax
  1458.          jmp Int21Through
  1459.  
  1460. Func40_3f:                    ; Funktion 40h und 3Fh: Ausgabe einer
  1461.                               ; Meldung falls in die Record-Datei
  1462.                               ; geschrieben wird bzw. aus ihr gelesen
  1463.                               ; wird
  1464.  
  1465.          push si              ; angegebenes Handle testen
  1466.          mov si,cs:RecordFileTablePtr
  1467.          cmp bx,cs:[si]
  1468.          pop si
  1469.          jne Int21Through
  1470.  
  1471.                               ; Handle stimmt
  1472.          push ds
  1473.          push ax,bx,cx,dx
  1474.  
  1475.          mov ds,cs
  1476.  
  1477.          mov dx,offset Int21ReadMsg
  1478.          cmp ah,03Fh
  1479.          je >l1               ; Lesen aus der Datei
  1480.  
  1481.          mov dx,offset Int21SizeMsg
  1482.          jcxz >l1             ; Dateigröße wird verändert
  1483.  
  1484.                               ; Schreiben in die Datei
  1485.          mov dx,offset Int21WriteMsg
  1486. l1:
  1487.          mov cx,Int21Msg_LENGTH
  1488.          mov ah,040h
  1489.          mov bx,StdOut
  1490.          int 021h             ; Meldung ausgeben
  1491.  
  1492.          pop dx,cx,bx,ax
  1493.          pop ds
  1494.          jmp Int21Through     ; und weiter zur alten Routine
  1495.  
  1496. ;
  1497. ; ----------------------------
  1498.  
  1499.