home *** CD-ROM | disk | FTP | other *** search
/ Power-Programmierung / CD1.mdf / assemblr / library / lib4a86 / doc / recordio.doc < prev    next >
Text File  |  1992-02-22  |  20KB  |  523 lines

  1.   ─────────────────────────────────────────────────────────────────────────────
  2.   Dokumentation zur Datei: RECORDIO.INC
  3.  
  4.   ─────────────────────────────────────────────────────────────────────────────
  5.    
  6.     RECORDIO.INC - Routinen zur gepufferten Bearbeitung von Record-Dateien
  7.                    (für den Assembler A86)
  8.    
  9.                    (c) Bernd Schemmer 1992
  10.                    Letzter Update: 22.02.1992
  11.    
  12.    
  13.     ■ Beschreibung:
  14.     ---------------
  15.     RECORDIO.INC stellt Routinen zur gepufferten Bearbeitung von
  16.     Record-Dateien (d.h. satzorientierten Dateien mit wahlfreien,
  17.     direkten Lese- und Schreibzugriffen) zur Verfügung. Die Routinen
  18.     können beliebig viele Dateien gleichzeitig und bis zu 250 Puffer
  19.     pro Datei verwalten. Die Puffer werden nach einer LRU-Strategie
  20.     verwaltet. LRU (= Last Reasently Used) bedeutet, daß, falls ein
  21.     Puffer überschrieben werden muß, immer der Puffer, der am
  22.     längsten nicht mehr genutzt wurde, überschrieben wird. Hierbei
  23.     wird nicht unterschieden, ob ein Puffer zum Lesen oder Schreiben
  24.     benutzt wurde.
  25.     Die Routinen berücksichtigen auch einen eventuell vorhandenen
  26.     Datei-Header vor den Sätzen in der Datei.
  27.     Jeder Puffer muß mindestens einen kompletten Satz (= Record)
  28.     aufnehmen können. Jeder Puffer wird nur soweit genutzt, daß genau
  29.     n Sätze rein passen,  d.h. die Länge eines Puffers sollte
  30.     möglichst ein Vielfaches der Satzlänge sein. Zur Erhöhung der
  31.     Performance der Lese- und Schreibvorgänge sollte die Länge
  32.     eines Puffers und des Headers (falls vorhanden) auch ein
  33.     Vielfaches von 512 (= Sektorlänge) sein (muß aber nicht!).
  34.     Es ist auch möglich, die Verwendung der Puffer auf das Lesen
  35.     von Sätzen einzuschränken (d.h. die Puffer können auch im Modus
  36.     'Write Through' betrieben werden).
  37.    
  38.     Für die Routinen gelten folgende Limits:
  39.    
  40.     max. Dateigröße:   2.147.483.647
  41.     max. Headergröße:  2.147.483.647
  42.     max. Satzgröße:           65.535
  43.     min. Satzgröße:                2
  44.     max. Anzahl Sätze: 2.147.483.647
  45.     max. Anzahl Puffer:          250
  46.     max. Größe eines Puffers: 65.535
  47.    
  48.     Folgende Bedingungen müssen ebenfalls eingehalten werden:
  49.    
  50.             Größe eines Puffer >= Satzgröße
  51.      Dateitgröße + Headergröße <= 2.147.483.647
  52.    
  53.      Falls der Header länger als 65.535 Byte ist, kann er mit dem
  54.      Routinen aus dieser Datei weder gelesen noch geschrieben werden.
  55.    
  56.     ■ Aufbau der Datei-Tabelle
  57.    
  58.     Für jede Datei muß eine Tabelle mit folgendem Aufbau vom Programm
  59.     zur Verfügung gestellt werden:
  60.    
  61.      Offset |  Länge   | Inhalt
  62.      -------+----------+-------------------------------------------
  63.     * 00h   | 1 Wort   | Handle der Datei
  64.       02h   | 2 Wörter | Offset des letzten Satzes
  65.     * 06h   | 2 Wörter | Länge des Headers der Datei
  66.             |          | oder 0 falls die Datei keinen Header hat
  67.     * 0Ah   | 1 Wort   | Länge eines Satzes der Datei (Länge >= 2)
  68.       0Ch   | 2 Wörter | Datei-Zeiger oder 0FFFFh:0FFFFh
  69.     * 10h   | 1 Wort   | Anzahl der Puffer   (Anzahl >= 1)
  70.     * 12h   | 1 Wort   | Größe eines Puffers ( >= Länge eines Satzes)
  71.             |          | Der Inhalt dieses Feldes wird vor der ersten
  72.             |          | Benutzung auf ein Vielfaches der Satzlänge
  73.             |          | abgerundet.
  74.     * 14h   | 1 Byte   | Flags, Aufbau: siehe unten
  75.       15h   | 1 Byte   | Indikator für eine leere Datei
  76.    
  77.     DIREKT HINTER dieser Tabelle muß für jeden Puffer eine Tabelle mit
  78.     folgenden Aufbau deklariert werden:
  79.    
  80.      Offset |  Länge   | Inhalt
  81.      -------+----------+-------------------------------------------
  82.       00h   | 1 Byte   | LRU-Inex
  83.       01h   | 1 Byte   | Flags des Puffers
  84.     * 02h   | 2 Wörter | Zeiger auf den Puffer (Offset, Segment)
  85.       06h   | 2 Wörter | Datei-Offset des ersten Satzes im Puffer
  86.    
  87.     Die Puffer müssen alle gleich groß sein, sie können aber in
  88.     beliebigen Speicherbereichen angelegt werden. Der Speicher
  89.     für die Puffer muß von der aufrufenden Routine zur Verfügung
  90.     gestellt werden. Die Adressen der Puffer werden vor der ersten
  91.     Benutzung in das Format ssss:000o gebracht (d.h. normalisiert).
  92.    
  93.     ■ Aufbau des Flagbytes beim Offset 14h:
  94.    
  95.     Bit     | Bedeutung
  96.     --------+------------------------------------------------------------
  97.      0      | Writethrough-Bit, falls dieses Bit auf 1 steht, werden
  98.             | die Puffer nur zum Lesen benutzt und jeder veränderte
  99.             | Satz wird sofort in die Datei übertragen.
  100.             | Da das Schreiben in die Datei nur Pufferweise vorgenommen
  101.             | wird, sollte zur Verbesserung der Performance in diesem
  102.             | Fall jeder Puffer nur 1 bis 4 Sätze aufnehmen können.
  103.             |
  104.      1      | Ignore-LRU-Bit, falls dieses Bit auf 1 steht, werden
  105.             | die akt. Werte der Puffer für die LRU-Verwaltung NICHT
  106.             | mehr verändert. D.h. falls ein Puffer überschrieben
  107.             | werden muß, wird immer der gleiche Puffer benutzt
  108.             | und die anderen Puffer behalten ihren Inhalt.
  109.             | Dies ist z.B. sinnvoll, falls die Datei mit leeren
  110.             | Sätzen aufgefüllt werden soll.
  111.             |
  112.      2..7   | reserviert
  113.    
  114.     ALLE mit einem Asterix (*) gekennzeichneten Felder in den Tabellen
  115.     müssen von der aufrufenden Routine VOR dem ersten Benutzen der
  116.     Tabelle durch die aufrufende Routine gefüllt werden.
  117.     Nach dem Eröffnen oder Erstellen einer  Datei darf, außer dem Feld
  118.     mit dem Flags, kein Feld mehr verändert werden!
  119.    
  120.     Hinweis:
  121.     Eine Änderung des WriteThrough-Bits bezieht sich nur auf
  122.     zukünftige Schreibvoränge. Es sollte daher nach oder vor dem
  123.     Setzen des WriteThrough-Bits die Routine 'FlushRecordFile'
  124.     zum Sichern der geänderten Puffer aufgerufen werden.
  125.    
  126.     Das Feld für das Handle muß mit -1 initialisiert werden.
  127.     Alle Wörter, Doppelwörter und Adressen müssen im INTEL-Format
  128.     eingetragen werden.
  129.    
  130.     Die Routinen benutzen das Register AX als Arbeitsregister und
  131.     verändern das Directionflag.
  132.    
  133.    
  134.     ■ Variablen:
  135.     ------------
  136.     RFOpenMode
  137.    
  138.          Byte, diese Variable enthält den Modus, der zum Öffnen einer
  139.          Datei verwendet wird. Voreinstellung für den Modus ist 02h;
  140.          der Inhalt der Variable ist nur bei der Eröffnung einer
  141.          bestehenden Datei von Bedeutung. (Aufbau: siehe unten)
  142.    
  143.     CreateRFileAttr
  144.    
  145.          Wort, Attribute für eine neu zu erstellende Datei
  146.          (nur für die Routinen CREATE... von Bedeutung)
  147.          Voreinstellung für das Attribut ist 0, folgende Bits werden
  148.          ignoriert: Bit 3 (08h, Volume-Bit)
  149.                     Bit 4 (10h, Directory-Bit)
  150.                     und
  151.                     Bit 6 und 7 (40h und 80h, reservierte Bits)
  152.          (Aufbau: siehe unten)
  153.    
  154.    
  155.     ■ Routinen:
  156.     -----------
  157.     ResetRecordFile       - Öffnet eine bestehende Record-Datei
  158.     CreateRecordFile      - Erstellt eine Record-Datei
  159.     CreateNewRecordFile   - Erstellt eine neue Record-Datei
  160.     CloseRecordFile       - Schließt eine Record-Datei
  161.     FlushRecordFile       - Schreibt alle veränderten Puffer einer
  162.                             Record-Datei
  163.     WriteRecord           - Schreibt einen Satz der Datei
  164.     ReadRecord            - Liest einen Satz der Datei
  165.     TestRecord            - Überprüft, ob ein Satz vorhanden ist
  166.     ReadRecordFileHeader  - Liest den Header einer Record-Datei
  167.     WriteRecordFileHeader - Schreibt den Header einer Record-Datei
  168.     GetRecordFileSize     - Ermittelt die Größe und die Anzahl der
  169.                             Sätze einer Record-Datei
  170.     SetRecordFileSize     - Vergrößert oder verkleinert eine
  171.                             Record-Datei
  172.    
  173.     und falls nötig (d.h. die .LIB-Dateien mit den entsprechenden
  174.     Routinen werden nicht benutzt):
  175.    
  176.     MulLongInt            - Multipliziert zwei LongInt-Werte
  177.     DivLongInt            - Dividiert zwei LongInt-Werte
  178.     Make20BitValue        - Rechnet eine 32-Bit-Adresse in eine
  179.                             20-Bit-Zahl um
  180.     Make32BitAdress       - Rechnet eine 20-Bit-Zahl in eine
  181.                             32-Bit-Adresse um
  182.    
  183.    
  184.     ■ Aufbau des Modus-Bytes für die Eröffnung einer bestehenden
  185.       Datei (= Variable RFOpenMode):
  186.    
  187.       Bit    | Bedeutung     | Aufschlüsselung der Bits
  188.       -------+---------------+-------------------------------------------
  189.       0..3   | Zugriffscode  | 0000 nur Lesen
  190.              |               | 0001 nur Schreiben
  191.              |               | 0010 Lesen + Schreiben
  192.              |               |
  193.       4..6   | Sharing-Code  | 000  Kompatibilitätsmodus
  194.              |               | 001  ablehnender Schreib/Lese-Modus
  195.              |               | 010  ablehnender Schreibmodus
  196.              |               | 011  ablehnender Lesemodus
  197.              |               | 100  nicht-ablehnender Modus
  198.              |               |
  199.       7      | Inherit-Bit   | 0    Zugriff für Unterprozesse erlaubt
  200.              |               | 1    Zugriff für Unterprozesse verboten
  201.    
  202.     RFOpenMode       DB 002h    ; Modus für die Eröffnung von Dateien
  203.    
  204.    
  205.     ■ Aufbau des Attributes für die Erstellung einer neuen Datei
  206.       (= Variable CreateRFileAttr)
  207.    
  208.       Bit    | Bedeutung
  209.       -------+---------------
  210.        0     | Read-Only-Bit
  211.        1     | Hidden-Bit
  212.        2     | System-Bit
  213.        3     | Volume-Bit
  214.        4     | SubDir-Bit
  215.        5     | Archive-Bit
  216.        6     | reserviert
  217.        7     | reserviert
  218.      8..15   | reserviert
  219.    
  220.     CreateRFileAttr DW 0h       ; Attribut für neu zu erstellende Dateien
  221.    
  222.    
  223.                                 ; EQUs für das Flag-Byte
  224.                                 ; -----------------------------
  225.     RF_WriteThrough     EQU 01h ; Write-Through-Bit einschalten
  226.     RF_IgnoreLRU        EQU 02h ; Ingore-LRU-Bit einschalten
  227.    
  228.     RF_DontWriteThrough EQU NOT RF_WriteThrough
  229.     RF_DontIgnoreLRU    EQU NOT RF_IgnoreLRU
  230.    
  231.    
  232.     Fehlernummern der Routinen
  233.     --------------------------
  234.    
  235.     Alle Fehlernummern der Routinen haben das Format 86xx, wobei xx die
  236.     Nummer des eigentlichen Fehlers ist. Neben diesen werden auch die
  237.     DOS-Fehlernummern im Format 00xx zurück geliefert.
  238.    
  239.     Name                   Nummer   Bedeutung
  240.     ----------------------------------------------------------------------
  241.                            000xxh ; DOS-Fehlernummer
  242.    
  243.     RFileTableError   EQU  08601h ; Die Datei-Tabelle ist fehlerhaft
  244.    
  245.     RFileNotOpen      EQU  08602h ; Die Datei ist geschlossen
  246.    
  247.     RFileAlreadyOpen  EQU  08603h ; Die Datei ist noch offen
  248.    
  249.     RFileReadError    EQU  08604h ; Lesefehler, unerwartetes Dateiende
  250.    
  251.     RFileWriteError   EQU  08605h ; Schreibfehler, Disk ist voll
  252.    
  253.     RFileRecordError  EQU  08606h ; Falsche Satznummer angegeben
  254.                                   ; beim Lesen: Satz nicht vorhanden
  255.                                   ; beim Verlängern: Datei kann nicht
  256.                                   ; auf die angegebene Länge verlängert
  257.                                   ; werden.
  258.     RFileLengthError  EQU  08607h ; Die Länge der Datei stimmt nicht
  259.                                   ; mit den Werten in der Datei-Tabelle
  260.                                   ; überein.
  261.    
  262.     RFileDeviceError  EQU  08608h ; Die Verwaltung der Ein- und Ausgaben
  263.                                   ; von Geräten ist über diese Routinen
  264.                                   ; nicht möglich
  265.    
  266.     RFileHeaderError  EQU  08609h ; Der Datei-Header kann nur geschrieben
  267.                                   ; oder gelesen werden, falls die Länge
  268.                                   ; des Datei-Headers ungleich 0 und
  269.                                   ; kleiner als 65.536 ist.
  270.    
  271.    
  272.     ■ Hinweis: Da nicht alle Bezeichner aus dieser Datei dokumentiert
  273.                sind, sollten in eigenen Routinen keine Bezeichner mit
  274.                der Zeichenfolge 'RF_' verwendet werden.
  275.    
  276.    
  277.     ----------------------------
  278.     ResetRecordFile
  279.    
  280.     Funktion: Eröffnet eine bestehende Datei
  281.    
  282.     Eingabe:  DS:BX -> Datei-Tabelle
  283.               ES:DI -> Dateiname als String mit Längenzähler
  284.    
  285.     Ausgabe:  CF = 0 ->> okay
  286.               CF = 1 ->> Fehler
  287.                          AX = Fehlernummer
  288.    
  289.     Bes.:     Die Datei muß mindestens den Header (falls in der Datei-
  290.               Tabelle angegeben) enthalten, die Größe der Datei muß
  291.               ein Vielfaches der Satzlänge plus der Länge des Datei-
  292.               headers sein.
  293.               Der Modus der Datei (Lesen, Schreiben oder Lesen und
  294.               Schreiben) wird durch die Variable RFOpenMode bestimmt.
  295.               Geräte können über diese Routine nicht eröffnet werden.
  296.    
  297.     ----------------------------
  298.     CreateRecordFile
  299.    
  300.     Funktion: Erstellt eine neue Datei.
  301.    
  302.     Eingabe:  DS:BX -> Datei-Tabelle
  303.               ES:DI -> Dateiname als String mit Längenzähler
  304.    
  305.     Ausgabe:  CF = 0 ->> okay
  306.               CF = 1 ->> Fehler
  307.                          AX = Fehlernummer
  308.    
  309.     Bes.:     Eine bestehende Datei wird überschrieben!
  310.               Die Attribute der Datei werden durch die Variable
  311.               CreateRFileAttr bestimmt.
  312.               Geräte können über diese Routine nicht erstellt werden.
  313.    
  314.     ----------------------------
  315.     CreateNewRecordFile
  316.    
  317.     Funktion: Erstellt eine Datei
  318.    
  319.     Eingabe:  DS:BX -> Datei-Tabelle
  320.               ES:DI -> Dateiname als String mit Längenzähler
  321.    
  322.     Ausgabe:  CF = 0 ->> okay
  323.               CF = 1 ->> Fehler
  324.                          AX = Fehlernummer
  325.    
  326.     Bes.:     Eine bestehende Datei führt zu einem Fehler!
  327.               Die Attribute der Datei werden durch die Variable
  328.               CreateRFileAttr bestimmt.
  329.               Geräte können über diese Routine nicht erstellt werden.
  330.    
  331.     ----------------------------
  332.     CloseRecordFile
  333.    
  334.     Funktion: Schreibt alle Puffer mit veränderten Daten in die Datei
  335.               und schließt die Datei
  336.    
  337.     Eingabe:  DS:BX -> Datei-Tabele
  338.    
  339.     Ausgabe:  CF = 0 ->> okay
  340.               CF = 1 ->> Fehler
  341.                          AX = Fehlernummer
  342.    
  343.     ----------------------------
  344.     FlushRecordFile
  345.    
  346.     Funktion: Schreibt alle Puffer mit veränderten Daten in die Datei
  347.    
  348.     Eingabe:  DS:BX -> Datei-Tabelle
  349.    
  350.     Ausgabe:  CF = 0 ->> okay
  351.               CF = 1 ->> Fehler
  352.                          AX = Fehlernummer
  353.    
  354.     Bes.:     Ab DOS-Version 3.30 werden auch die DOS-internen Puffer
  355.               über die Funktion 68h des Interrupts 21h geschrieben.
  356.    
  357.     ----------------------------
  358.     ReadRecord
  359.    
  360.     Funktion: Liest einen Satz
  361.    
  362.     Eingabe:  DS:BX -> Datei-Tabelle
  363.               DX:AX = Nummer des Satzes (0..n)
  364.               ES:DI -> Puffer für den Satz
  365.    
  366.     Ausgabe:  CF = 0 ->> okay
  367.               CF = 1 ->> Fehler
  368.                          AX = Fehlernummer
  369.    
  370.     Bes.:     Die Satzlänge wird der Datei-Tabelle entommen.
  371.               Es können nur schon existierende Sätze gelesen werden.
  372.    
  373.     ----------------------------
  374.     TestRecord
  375.    
  376.     Funktion: Überprüft, ob ein Satz in der Datei vorhanden ist
  377.    
  378.     Eingabe:  DS:BX -> Datei-Tabelle
  379.               DX:AX = Nummer des Satzes (0..n)
  380.    
  381.     Ausgabe:  CF = 0 ->> okay
  382.                          ZF = 0 ->> Satz vorhanden
  383.                          ZF = 1 ->> Satz nicht vorhanden
  384.               CF = 1 ->> Fehler
  385.                          AX = Fehlernummer
  386.    
  387.     ----------------------------
  388.     WriteRecord
  389.    
  390.     Funktion: Schreibt einen Satz
  391.    
  392.     Eingabe:  DS:BX -> Datei-Tabelle
  393.               DX:AX = Nummer des Satzes (0..n)
  394.               ES:DI -> zu schreibender Satz
  395.    
  396.     Ausgabe:  CF = 0 ->> okay
  397.               CF = 1 ->> Fehler
  398.                          AX = Fehlernummer
  399.    
  400.     Bes.:     Die Satzlänge wird der Datei-Tabelle entommen.
  401.               Falls der Satz noch nicht existiert, wird die
  402.               Datei verlängert. Nach einer Verlängerung existieren
  403.               alle Sätze bis zum neuen Satz inclusive, wobei alle
  404.               Sätze zwischen den letzten Satz und dem neuen Satz
  405.               nur 'Datenmüll' enthalten.
  406.    
  407.     ----------------------------
  408.     GetRecordFileSize
  409.    
  410.     Funktion: Ermittelt die Größe einer Datei und die Anzahl
  411.               der Sätze in der Datei
  412.    
  413.     Eingabe:  DS:BX -> Datei-Tabelle
  414.    
  415.     Ausgabe:  CF = 0 ->> okay
  416.                          DX:AX = Größe der Datei (incl. Header)
  417.                          CX:BX = Anzahl der Sätze
  418.               CF = 1 ->> Fehler
  419.                          AX = Fehlernummer
  420.    
  421.     ----------------------------
  422.     SetRecordFileSize
  423.    
  424.     Funktion: Setzt die Größe einer Datei
  425.    
  426.     Eingabe:  DS:BX -> Datei-Tabelle
  427.               DX:AX = Anzahl der Sätze für die Datei
  428.    
  429.     Ausgabe:  CF = 0 ->> okay
  430.               CF = 1 ->> Fehler
  431.                          AX = Fehlernummer
  432.    
  433.     Bes.:     Falls die Datei verkleinert wird, sind alle Sätze,
  434.               die hinter dem neuen letzten Satz liegen verloren!
  435.               Falls die Datei vergrößert wird, enthalten alle neuen
  436.               Sätze nur 'Datenmüll'.
  437.               Nach der Veränderung der Größe der Datei werden die
  438.               Inhalte aller Puffer mit gültigen veränderten Daten
  439.               in die Datei geschrieben.
  440.    
  441.     ----------------------------
  442.     ReadRecordFileHeader
  443.    
  444.     Funktion: Liest den Header einer Datei
  445.    
  446.     Eingabe:  DS:BX -> Datei-Tabelle
  447.               ES:DI -> Puffer für den Header
  448.    
  449.     Ausgabe:  CF = 0 ->> okay
  450.               CF = 1 ->> Fehler
  451.                          AX = Fehlernummer
  452.    
  453.     Hinweis:  Die Länge des Headers wird aus der Datei-Tabelle entnommen,
  454.               für das Lesen des Headers wird kein Puffer benutzt.
  455.               Der Header kann nur gelesen werden falls gilt:
  456.                    0 < HeaderLength <= 65.535
  457.    
  458.    
  459.     ----------------------------
  460.     WriteRecordFileHeader
  461.    
  462.     Funktion: Schreibt den Header einer Datei
  463.    
  464.     Eingabe:  DS:BX -> Datei-Tabelle
  465.               ES:DI -> Header für die Datei
  466.    
  467.     Ausgabe:  CF = 0 ->> okay
  468.               CF = 1 ->> Fehler
  469.                          AX = Fehlernummer
  470.    
  471.     Hinweis:  Die Länge des Headers wird aus der Datei-Tabelle entnommen,
  472.               für das Schreiben des Headers wird kein Puffer benutzt.
  473.               Der Header kann nur geschrieben werden falls gilt:
  474.                    0 < HeaderLength <= 65.535
  475.    
  476.     ----------------------------
  477.     MulLongInt
  478.    
  479.     Funktion:  Multipliziert zwei Longint-Werte
  480.    
  481.     Eingabe:   DX:AX = 1. Operand
  482.                CX:BX = 2. Operand
  483.    
  484.     Ausgabe:   DX:AX = (DX:AX * CX:BX) = Ergebnis
  485.                Keine Überprüfung auf Überlauf!
  486.    
  487.     ----------------------------
  488.     DivLongInt
  489.    
  490.     Funktion:  Dividiert zwei Longint-Werte
  491.    
  492.     Eingabe:   DX:AX = 1. Operand
  493.                CX:BX = 2. Operand
  494.    
  495.     Ausgabe:   CF = 0 ->> okay
  496.                           DX:AX = (DX:AX DIV CX:BX) = Ergebnis
  497.                           CX:BX = (DX:AX MOD CX:BX) = Rest
  498.                CF = 1 ->> Fehler
  499.                           2. Operand ist 0
  500.    
  501.     ----------------------------
  502.     Make32BitAdress
  503.    
  504.     Funktion: Konvertiert eine 20-Bit-Zahl in eine normalisierte
  505.               Adresse aus Segment und Offset
  506.    
  507.     Eingabe:  DX:AX = 20-Bit-Zahl    (Aufbau: 000n:nnnn)
  508.    
  509.     Ausgabe:  DX:AX = 32-Bit-Adresse (Aufbau: ssss:000o)
  510.    
  511.     ----------------------------
  512.     Make20BitValue
  513.    
  514.     Funktion: Konvertiert eine Adresse aus Segment und Offset in
  515.               eine 20-Bit-Zahl
  516.    
  517.     Eingabe:  DX:AX = Adresse     (ssss:oooo)
  518.    
  519.     Ausgabe:  DX:AX = 20-Bit-Zahl (000n:nnnn)
  520.    
  521.     Bes.:     Die Adresse muß nicht normalisiert sein.
  522.    
  523.