8086 Assembler (MS-DOS):
INT 21h (DOS-Interrupt)

Die nachfolgende Zusammenstellung betrifft den sogenannten DOS-Interrupt INT 21h.

Die Beschreibung gilt bis MS-DOS Version 6 einschließlich. Ich hatte mir diese Zusammenstellung gemacht, als ich mich seinerzeit mit dem 8086-Assembler beschäftigt hatte.

Aufruf und Fehlercodes bei den READ- und WRITE-Funktionen

Der Aufruf läuft nach folgendem Schema ab:
  • Man versorgt die Register mit den benötigten Eingabeparametern.
  • Die Funktionsnummer kommt nach AH, die eventuell benötigte Unterfunktionsnummer nach AL.
  • Die Funktion wird ausgeführt. Bis auf wenige Ausnahmen ändert sie nur die Register, die zur Übergabe der Ergebnisse dienen.

Die CP/M-kompatiblen Funktionen verwenden AL zur Kennzeichnung von Fehlern. Die neueren Funktionen melden mit dem gesetzten Carryflag (CF), dass ein Fehler aufgetreten ist. Falls ja, steht im Register AX eine Fehlernummer.

Fehlercodes bei den READ- und WRITE-Funktionen (READ-Funktionen: 14H, 21H, 27H und WRITE-Funktionen: 15H, 22H, 28H):

  • 1. Ungültiger Funktionscode. Die gewählte Funktion gibt es nicht. bei READ-Funktion: Dateiende (EOF) ist erreicht. bei WRITE-Funktion: Disk voll.
  • 2. Überlauf des DTA-Buffers bei READ- und WRITE Funktion: Im DTA-Buffer wurde das Offset 0FFFFH erreicht. Ein weiteres Lesen/ Schreiben hätte den Offset 0 zur Folge.
  • 3. Pfad nicht gefunden. bei READ- Funktion: Dateiende (EOF) wurde beim Lesen des letzen Satzes erreicht. Der letzte Satz steht im DTA-Buffer bereit und wurde mit 00H-Bytes auf die Satzlänge (RECLEN) aufgefüllt.
  • 4. Zu viele Dateien offen. Die maximale Anzahl gleichzeitig geöffneter Dateien ist erschöpft.
  • 5. Zugriff verweigert.
  • 6. Ungültiges Handle. Das Handle bezieht sich nicht auf eine geöffnete Datei.
  • 7. Speicherkontrollblöcke zerstört. Die interne Speicherverwaltung von MS-DOS wurde beschädigt.
  • 8. Nicht genügend Platz frei. Die von MS-DOS angeforderte Speichermenge kann nicht zur Verfügung gestellt werden.
  • 9. Ungültige Adresse Speicherkontrollblock. Die übergebende Adresse kennzeichnet nicht den Beginn eines Speicherkontrollblocks.
  • 10. Ungültige Umgebungsadresse. Die übergebende Adresse kennzeichnet nicht den Beginn eines Environments.
  • 11. Ungültiges Format. Das angegebene Programm ist intern nicht korrekt aufgebaut (z.B. Dateilänge=0 oder fehlerhafter Programmvorspann bei einem .EXE-Programm).
  • 12. Ungültiger Zugriffscode. Die bits 0 bis 3 von AL hatten beim Aufruf keinen Wert von 0 bis 3.
  • 13. Ungültige Daten. Tritt bei Funktion 44 auf. Die genaue Bedeutung ist unbekannt.
  • 14. Reserviert
  • 15. Ungültiges Laufwerk. Es wurde versucht, auf ein nicht existierendes Laufwerk zuzugreifen.
  • 16. Aktuelles Directory nicht löschbar. (das zu löschende Directory muss vor dem Löschen verlassen werden).
  • 17. Nicht dasselbe Gerät. Die Funktion erlaubt keine Angabe von zwei verschiedenen Laufwerken.
  • 18. Keine weitere Datei vorhanden. Die Suche nach weiteren Einträgen im Directory bzw. in der Zuordnungsliste (Netzwerk) war erfolglos.
  • 33. Sperren/Freigeben nicht möglich. Es wurde entweder versucht, einen Dateibereich zu sperren, der bereits ganz oder teilweise gesperrt ist, oder der freizugebende Teil entspricht in seiner Länge dem vorher gesperrten Teil.
  • 80. Datei existiert bereits. Die Funktion 5BH erzeugt nur dann eine neue Datei, wenn diese noch nicht vorhanden ist.

Aufbau des Attributbytes:

Bit
76543210wenn gesetztwenn 0 (=nicht gesetzt)
xDatei nur lesbarDatei les- und schreibbar
xversteckte Dateisichtbare Datei
xSystemdateinormale Datei
xDatenträgernamenormale Datei
xVerzeichnisnamenormale Datei
xnach Sicherung geändertseit Sicherung unverändert
xxreserviertreserviert

Directoryeinträge:

OffsetLängeBeschreibungFormat
08 ByteDateinameASCII,
siehe Hinweis unter
dieser Tabelle!
83 ByteDateityp (Erweiterung)ASCII
0Bh1 ByteAttributbytesiehe Attributbyte,
Tabelledirekt oberhalb
0Ch10 BytereserviertASCII
16h1 WortZeit letzte Aktualisierungkodiertes Wort
18h1 WortDatum letzt Aktualisierungkodiertes Wort
1Ah1 WortNr. des Startclustersbinäre Ganzzahl
1Ch1 Doppel-
wort
Dateigrößebinäre Ganzzahl

Das 1.Byte des Dateinamens hat folgende Sonderbedeutung:
00h=Eintrag / Name wurde nie verwendet
05h=Das erste Zeichen des Namens ist eigentlich E5h
E5h=Datei wurde verwendet, ist jedoch gelöscht
2Eh=Eintrag ist ein Verzeichnis, wenn das 2.Byte auch 2Eh ist, enthält das Clusterfeld die Clusternummer des übergeordneten Verzeichnisses.

DTA / FCB

Die CP/M kompatiblen Diskfunktionen verwenden File Control Blocks (FCB)s.

Da der FCB keine Möglichkeit der Pfadangabe hat, beziehen sich diese Funktionen immer auf das aktuelle Directory.

Als Wildcard-Angabe für die CP/M-kompatiblen Funktionen ist nur das ? möglich, nicht das *.

Sämtlicher Datentranfers findet bei den FCB-behafteten Funktionen über die Disk Transfer Address (DTA) statt. Die DTA ist die Anfangsadresse eines beliebigen Puffers im Hauptspeicher. Die maximale Größe ist 64 K Byte. Effektiv genutzt werden kann nur der Bereich zwischen dem Offset der DTA und 0FFFFH. Hatte z.B. die DTA die Adresse 3000:FFF0H so könnten maximal 16 Bytes genutzt werden. Als Default-DTA-Adresse gibt MS-DOS DS:80H vor. Da die Programme bei DS:100H beginnen, ist der Puffer somit 128 Bytes lang. Die DTA-Adresse befindet sich im Program-Segment Prefix (PSP), welches den Anfang eines jeden Programmes bildet. Im PSP befinden sich an den Offsets 5CH und 6CH ebenfalls zwei ungeöffnete FCBs.

Vor Verwendung bitte die hier gemachten Angaben zum FCB prüfen, ggf. korrigieren!

normaler FCB:
drive    db  ?        ;gewähltes Laufwerk, 0= aktuelles, 1=A, usw.
fname    db  8 dup (' ')     ;Dateiname, linksbündig mit Space aufgefüllt
fext     db  3 dup (' ')     ;Erweiterung, linksbündig mit
                             ;Space aufgefüllt
curblk   dw  0               ;Nr. des aktuellen Blockes
recln    dw  0               ;logische Satzlänge (default: 80H)
fsize    dd  0               ;Dateilänge in Bytes
fdate    db  0,0             ;Dateidatum gepackt, jjjj jjjj mmmt tttt
ftime    db  0,0             ;Dateizeit gepackt,  hhhh hmmm mmms ssss
reserv   db  8 dup (0)       ;intern von DOS benutzt
currec   db  0               ;aktueller Satz in curblk
relrec   dd  0     ;relative Satznr. bei Randomverarbeitung
                       ;keine Vorbelegung durch OPEN,
                       ;benutzt werden:
                       ;4 Byte bei reclen >64 bytes
                       ;3 byte bei reclen <=64 Bytes

erweiterter FCB:
dieser Kopf wird beim erweiterten FCB vor dem normalen FCB platziert:

flag     db  0ffh             ;Muss-Kennzeichner für
                              ;erweiterten FCB
dummy    db  5 dup (' ')      ;reserviert für zukünftige
                              ;Benutzung
fattr    db  ?                ;Attributbyte

spezieller FCB für Funktion 17 (Umbenennen von Dateien)
drive    db  ?                ;gewähltes Laufwerk,
                              ;0= aktuelles, 1=A, usw.
afname   db  8 dup (' ')      ;alter Dateiname, linksbündig
aext     db  3 dup (' ')      ;alte Erweiterung, linksbündig
         db  5 dup (0)        ;reserviert
nfname   db  8 dup (' ')      ;neuer Dateiname, linksbündig
next     db  3 dup (' ')      ;neue Erweiterung, linksbündig

         db  9 dup (0)        ;reserviert

Beispiel zur FCB-Behandlung:

comment #
Zweck:  Rename eines Unterverzeichnisses

Aufruf: rendir Altname Neuname
        Beide Dateinamen dürfen nur die reinen Dateinamen sein,
        da mit einem FCB gearbeitet wird
Quelle: c't 1988, Heft 6, Seite 204 mit Modifikationen
#
        .286c
dbl     macro     text      ;;define a line
        db        text,cr,lf
        endm

jmps    macro     to        ;;kurzer Sprung
        jmp       short to
        endm

prstr   MACRO     TEXT      ;;PRINT STRING
        CALL      PRMSG
        DB        TEXT,0
        ENDM

cr      equ       0dh
lf      equ       0ah

dos     equ       21h
lparm   equ       0080h      ;Parameterlänge
parm    equ       0081h      ;Parameter

code    segment
        assume    cs:code, ds:code, es:code

        org       100h
start:  mov       cl,byte ptr cs:lparm
        xor       ch,ch
        jcxz      leer       ;kein Parameter
        cld

;Altname als 1. Parameter suchen
        mov       di,parm
        mov       al,' '
        repe      scasb      ;führende blanks überlesen
        je        leer       ;nur blanks !

        lea       si,[di-1]  ;Anfang Altname nach DI

        repne     scasb      ;nächstes Blank als Ende Altname suchen
        jne       leer       ;Neuname fehlt

        mov       byte ptr[di-1],0        ;Markieren Ende Altname

        repe      scasb      ;weitere blanks überlesen
        je        leer       ;kein Neuname angegeben

        lea       dx,[di-1]        ;Anfang Neuname nach DX
        add       di,cx            ;hinter Neuname gehen
        mov       byte ptr[di],0   ;Markieren Ende Neuname
        jmps      name_to_fcb

leer:   prstr     'Usage: RENDIR Altname Neuname'
        jmp       ret1

;Altname in FCB eintragen
name_to_fcb:
        lea       di,fcb.fname
        call      tofcb
        jc        fdrive           ;Fehler im Namen

;Neuname in FCB eintragen
        mov       si,dx
        lea       di,fcb.nfname
        call      tofcb
        jc        fdrive           ;Fehler im Namen

;Rename versuchen
        mov       fcb.attr,10h     ;Attribut SubDir
        mov       ah,17h           ;Rename mit FCB
        lea       dx,fcb
        int       dos
        or        al,al            ;fehlerfrei?
        jnz       nicht_ok         ;nein
        jmp       ret0

fdrive: or        al,al            ;Fehlermeldung ermitteln
        jne       fdrive1          ;und ausgeben
        jmp       mdrive
fdrive1: prstr    'alter oder neuer Name zu lang !'
        jmp       ret1

nicht_ok: call    prmsg
        dbl       'SubDir ist nicht im aktuellen Directory'
        db        'oder den neuen Namen gibt es schon'
        db        0
        jmp       ret1

mdrive: prstr     'Laufwerks- bzw. Pfadangabe nicht möglich !'
        jmp       ret1

tofcb   proc near
comment #
Übernahme von Name und Erweiterung aus der Kommandozeile in den FCB
input  <si>=Beginn des Dasteinamens, mit 0 beendet
       <di>=Ziel für Dateiname in FCB
output   cf=0 Name und Erweiterung in FCB eingetragen
         cf=1 : al=0 Name enthält Laufwerks- oder Pfadangaben
                al=1 Nume+Erw. zu lang (>11 Byte)
#
        mov       cx,8       ;max. Länge für Name
        lea       bx,[di+8]  ;Offset für Erweiterung
toloop: lodsb
        or        al,al      ;Ende des Namens?
        je        toret      ;ja. fetig mit cf=0
        cmp       al,'.'     ;Erweiterung?
        jne       to10
        mov       di,bx      ;ja- ab jetzt in Erweiterung eintragen
        mov       cx,3
        jmps      toloop

to10:   cmp       al,':'     ;Laufwerk ?
        je        toerror
        cmp       al,'\'     ;Pfad?
        je        toerror
        stosb
        loop      toloop
        lodsb
        or        al,al      ;Ende mit 0?
        jz        toret      ;ja, dann OK
        mov       al,1       ;Name oder Erweiterung zu lang
        jmps      tofehler

toerror:
        mov       al,0
tofehler:
        stc
toret:  ret
tofcb   endp
;---------------

sfcb    struc                ;Struktur erweiterter FCB
        db        0ffh       ;Flag für erweitereten FCB
        db        5 dup (0)
attr    db        ?
drive   db        0
fname   db        '        ' ;alter Name
fext    db        '   '      ;alte Erweiterung
        db        5 dup (0)
nfname  db        '        ' ;neuer Name
nfext   db        '   '      ;neue Erweiterung
        db        15 dup (0)
sfcb    ends

fcb     sfcb      ><

;---------------------
;Unterprogrammsammlung
;---------------------
;PRINT MESSAGE FOLLOWING CALL PRMSG  AND ENDING WITH 0
PRMSG:  mov       word ptr PRMSG2,di
        POP       di
        CALL      PSTR
        PUSH      di        ;Returnadr.

        mov       di,0      ;mod
PRMSG2  EQU       $-2
        RET

;PRINT MESSAGE ADRESSED BY di, ENDING WITH 0
PSTR:   mov       dl,[di]
        INC       di
        cmp       dl,0
        jz        pstr99    ;FALLS FERTIG
        mov       ah,02
        int       21h
        jmp       short PSTR

pstr99: ret
;---------------
;diverse Programmbeendigungen
ret0:   mov       al,0
        jmps      raus

ret1:   mov       al,1

;Programmende
raus:   prstr     <cr,lf>
        mov       ah,4ch
        int       dos

code    ends
        end        start

Handles

Um eine Dateinummer zu erhalten, muss die Datei mit einer UNIX-kompatiblen Funktion (3CH, 3DH, 5AH, 5BH oder bei langen Dateinamen mit einer der Unterfunktionen 71xxh ) eröffnet bzw. eingerichtet werden. Hierzu übergibt man den Funktionen den Dateipfad. MS-DOS liefert als Ergebnis den HANDLE (=Dateinummer) zurück. Alle weiteren Zugriffe zu dieser Datei, bis hin zum Schließen, werden durch die Angabe des Handles gesteuert.

5 Handles sind vordefiniert:

Handle       Bezeichnung          Gerät
----------------------------------------
0 STDIN      Standard_Input       Tastatur
1 STDOUT     Standard_Output      Bildschirm
2 STDERR     Standard_Error       Bildschirm
3 STDAUX     Standard_Auxiliary   RS-232
4 STDPRN     Standard_Printer     Drucker

Beispielmacros zur Handle-Dateibehandlung:

Zur Anwendung vergleiche das Beispielprogramm. Die Beispielmacros sind in der Datei firm.mac enthalten, die unter Routinensammlung für COM-Programme eingesehen und heruntergeladen werden kann.

Bei den Beispielmacros wird davon ausgegangen, dass die Handlenummern in der durch den Parameter fhand spezifizierten Speicherstelle stehen. Eine Angabe der Handlenummer als Direktwert ist somit bei diesen Macros nicht möglich.

dos    equ      21h

;ldreg is an "inner" macro.
;It allows the caller of a macro to specify a register
;or a literal value as the parameter to the macro.

;This macro loads the correct register specified
;by the caller of the macro with the contents of
;the register, literal or ;memory location also specified.

;No code will be generated if the two ;parameters are
;the same.

ldreg   macro    destreg,source
        ifdif    <destreg>,<source>
        mov      destreg,source
        endif
        endm

;---------------------------
;handle-dateibehandlung
;---------------------------
fopen   macro fname,acode        ;;open file
        ifdif    <dx>,<fname>
        mov      dx,offset fname ;;address of file name
        endif
        ldreg    al,acode       ;;access code
                                ;;0=read,
                                ;;1=write,
                                ;;2=read & write
        mov      ah,3dh         ;;funtion call open file
        int      dos            ;;returns fhandle in ax
        endm

fcrat   macro fname,attrb       ;;create a file (eine alte Datei
        ifdif    <dx>,<fname>        ;;gleichen Namens wird
                                ;;dabei gelöscht). Die erzeugte Datei
                                ;;ist geoeffnet fuer Lesen und Schreiben.
        mov      dx,offset fname ;;address of file name
        endif
        ldreg    cx,attrb        ;;attribute
        mov      ah,3ch          ;;funtion call create file
        int      dos             ;;returns fhandle in ax
        endm

fwrit   macro fhand,wbuff,count  ;;write to file
        ldreg    bx,fhand        ;;address of file name
        ldreg    cx,count        ;;attribute
        ifdif    <dx>,<wbuff>
        mov      dx,offset wbuff ;;address of write buffer
        endif
        mov      ah,40h          ;;funtion write file
        int      dos
        endm

fclose  macro    fhand           ;;close file
        ldreg    bx,fhand        ;;file handle
        mov      ah,3eh          ;;function call close file
        int      dos
        endm

fread   macro    fhand,rbuff,count ;;read from file
        ldreg    bx,fhand          ;;get file handle
        ldreg    cx,count          ;;get this many byte(s)
        ifdif    <dx>,<rbuff>
        mov      dx,offset rbuff   ;;address of read buffer
        endif
        mov      ah,3fh            ;;function read handle
        int      dos
        endm

PSP und Umgebungsblock (Environment Block)

Der PSP ist 256 Bytes lang und beginnt stets vor dem Programm.

Beispiel eines PSP (in diesem Fall stehen ab Adresse 00A2 Überreste alter Befelszeilen):

D:\dos\ML\Test>debug test.com datei1.dat datei2.dat PARAMETER
-d0 ff
18A0:0000  CD 20 FF 9F 00 9A F0 FE-1D F0 4F 03 F3 12 8A 03   . ........O.....
18A0:0010  F3 12 17 03 F3 12 E2 12-01 01 01 00 02 FF FF FF   ................
18A0:0020  FF FF FF FF FF FF FF FF-FF FF FF FF 30 09 4C 01   ............0.L.
18A0:0030  B3 17 14 00 18 00 A0 18-FF FF FF FF 00 00 00 00   ................
18A0:0040  05 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00   ................
18A0:0050  CD 21 CB 00 00 00 00 00-00 00 00 00 00 44 41 54   .!...........DAT
18A0:0060  45 49 31 20 20 44 41 54-00 00 00 00 00 44 41 54   EI1  DAT.....DAT
18A0:0070  45 49 32 20 20 44 41 54-00 00 00 00 00 00 00 00   EI2  DAT........
18A0:0080  20 20 64 61 74 65 69 31-2E 64 61 74 20 64 61 74     datei1.dat dat
18A0:0090  65 69 32 2E 64 61 74 20-50 41 52 41 4D 45 54 45   ei2.dat PARAMETE
18A0:00A0  52 0D 41 52 41 4D 45 54-45 52 0D 00 00 00 00 00   R.ARAMETER......
18A0:00B0  00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00   ................
18A0:00C0  00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00   ................
18A0:00D0  00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00   ................
18A0:00E0  00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00   ................
18A0:00F0  00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00   ................

Hinweise zur folgenden Tabelle:

  • Länge: db=Byte, dw=Wort, dd=Doppelwort
  • Offsetangaben: Ein Stern hinter der Offsetangabe besagt, dass die hier genannte Bedeutung inhaltlich von der Beschreibung im „IBM DOS 3.3. Technical Reference” auf den Seiten 7-10 und 7-11 abweicht und somit nicht offiziell ist.
OffsetLängeStandard-
inhalt
Bemerkungen
0dwcd 20INT 20h Beendigungsadresse (veraltet)
2dw0080hSegmentadr. des zugewiesenen Speicherblockes (contains the segment address of the top of the transient program's allocated memory)
4db00hreserviert
55 Bytes9a ee fe 1d f0CALL FAR zum DOSFunktionsverteiler (überholt)
Addf5 02 c8 0eINT 22h Adresse (Terminator Handler)
Edd2e 03 c8 0eINT 23h Adresse CTRL-Break-Behandlung
12ddbd 02 c8 0eINT 24h Adresse Critcal Error Handler
16ddb6 0bSegmentadr. PSP des übergeordnetenBlockes,
beim Grundprozeß ist dies die eigene PSP-Adresse
1820 Bytes01 03 01 00 02
ff ff ... ff
Handle Tabelle, 1 Byte pro Handle. Die ersten 5 Handles sind initialisiert. ffh = Handle nicht belegt.
2cdw8a 0eSegmentadr. des eigenen Environmentblockes (Environment Segment)
2e *dw4e 01 00 12Adresse Stackbereich
32dw14 00Größe Handle Tabelle, 14 00 = 20 Einträge,
ab DOS 3.3 größere Tabellen mögl.
34dw12 00 oder
18 00
Wenn nicht 12H:
Offsetadresse der Handletabelle (ab DOS 3.3)
36dw75 12Segmentadresse der Handletabelle (ab DOS.3)
38 *ff ff ff ffvorheriges Segment von Share (immer-1)
3c *00 ... 00reserviert
50dwcd21hINT 21h - Aufruf. Der Return von hier erfolgt mit RET Far, so dass der Aufruf per Call Far erfolgen muss. In AH muss beim Aufruf der Funktionscode stehen.
52dbcbhRET FAR - Befehl
539 Bytes00reserviert
5c16/36 Bytesgeschlossener Standard-FCB 1
  • 1 Byte Laufwerk (0=Default), 1=A:, 2=B: usf.)
  • 8 Bytes Dateiname (ASCII)
  • 3 Bytes Dateinamenserweiterung (ASCII)
  • 2 Bytes Current Block Counter
  • 2 Bytes Satzgröße in Bytes (128)
Die zweite Längenangabe weist darauf hin, dass die 20 folgendne Bytes bei Eröffnung des FCB 1 überschrieben werden.
6c16 Bytes geschlossener Standard-FCB 2,
Aufbau wie der geschlossene FCB 1. Wenn FCB 1 eröffnet wird, wird dieser Bereich überschrieben.
7c4 Bytes00reserviert. Diese 4 Bytes liegen noch im Bereich des geöffneten FCB 1.
80db Bei Programmstart Länge der Kommandozeile einschließlich des abschließenden CR.
Später genutzt für die Länge des belegten Bereiches (maximal 127) der Standard-DTA.
81127 Bytes Bei ProgrammstartBefehlszeilenparameter,
beginnt mit Space, Abschluß CR. Standardumleitungen werden hier nicht abgelegt.
Später wird dieser Bereich als Standard Disk Transfer Area (Standard-DTA) verwendet.
Der Umgebungsblock (auch Environment Block oder gemischtsprachlich Environmentbereich) wird von MS-DOS für jeden Prozeß angelegt. Er besteht aus ASCIIZ-Zeichenketten im Format:

NAME=Parameter

Sein Ende wird durch ein weiteres Nullbyte hinter der abschließenden Null der letzten Zeichenkette markiert. Falls ein Prozess ohne Environment auskommt, besteht der Umgebungsblock aus einem Wort mit dem Inhalt 0000h.

Der erste String im Umgebungsblock ist der Name des verwendeten Kommandointerpreters. Weitere Eintragungen im Umgebungsblock stammen aus dem SET-Kommando wie in in der AUTOEXEC.BAT bzw. deren Nachfolgern angewendet wird.

Ab MS-DOS 3.0 folgen auf den Umgebungsblock weitere Initalisierungsparameter. Deren Anzahl wird durch ein Wort angekündigt. Es folgt der Dateiname des aufgerufenen Programmes, ggf. ergänzt um Pfadnamen und Laufwerksnamen.

OffsetLängeInhalt
0Umgebungszeichenkette in der Form Name=Parameter (ASCII)
im Anschluss1 Byte00h, kennzeichnet Ende der vorangegangenen Zeichenkette
Die vorhergehende in zwei Tabellenzeilen beschriebene Struktur tritt keinmal, einmal oder mehrmals auf
im Anschluss1 ByteZwei aufeinanderfolgende 00h (also 0000h) kennzeichnen das Ende der Umgebungsblöcke. Ist kein einziger Umgebungsblock vorhanden steht auf Offset 0 und Offset 1 jeweils 00h
im Anschluss1 WortAnzahl der folgenden Zeichenketten. Normalerweise ist der Inhalt 0001h und der folgende ASCIIZ-String verweist auf das aufgerufene Programm - je nach Aufruf auch mit Pfad- und Laufwerksnamen.

Das folgende Beispiel veranschaulicht, wie man mit DEBUG den Sachverhalt überprüfen kann. Auf Adresse 2ch des PSP steht die Segmentadresse des Umgebungsblockes (zuerst das wertniedrige Byte, dann das werthohe Byte).

D:\DOS\ML\TEST>debug test.com PARAMETER
-d20 2f
1932:0020  FF FF FF FF FF FF FF FF-FF FF FF FF 30 09 4C 01   ............0.L.
-d0930:0 100
0930:0000  43 4F 4D 53 50 45 43 3D-43 3A 5C 57 49 4E 44 4F   COMSPEC=C:\WINDO
0930:0010  57 53 5C 53 59 53 54 45-4D 33 32 5C 43 4F 4D 4D   WS\SYSTEM32\COMM
0930:0020  41 4E 44 2E 43 4F 4D 00-41 4C 4C 55 53 45 52 53   AND.COM.ALLUSERS
0930:0030  50 52 4F 46 49 4C 45 3D-43 3A 5C 50 52 4F 47 52   PROFILE=C:\PROGR
0930:0040  41 7E 32 00 41 50 50 44-41 54 41 3D 43 3A 5C 55   A~2.APPDATA=C:\U
0930:0050  73 65 72 73 5C 72 6F 6C-66 5C 41 70 70 44 61 74   sers\rolf\AppDat
(usf.) Bei 0930:0449 steht die Anzahl der folgenden Zeichenketten (zuerst das wertniedrige, dann das werthohe Byte). Hier ist es eine einzige Zeichenkette. Sie enthält den Namen des aufgerufenen Programms. Hinter der abschließenden Null auf Adresse 0930:0453 stehen Reste aus vorhergegangenen Aktivitäten.
0930:0430  45 52 50 52 4F 46 49 4C-45 3D 43 3A 5C 55 73 65   ERPROFILE=C:\Use
0930:0440  72 73 5C 72 6F 6C 66 00-00 01 00 54 45 53 54 2E   rs\rolf....TEST.
0930:0450  43 4F 4D 00 5C 4B 34 2E-43 4F 4D 00 FF EB 65 F6   COM.\K4.COM...e.
Letztes Upload: 24.03.2023 um 11:35:15 • Impressum und Datenschutzerklärung